From 5241d52b144f3294968ac3350018e31463a73f5e Mon Sep 17 00:00:00 2001 From: LTbinglingfeng Date: Thu, 5 Feb 2026 00:55:03 +0800 Subject: [PATCH] fix(model-alias): improve diagram mobile layout and refresh reliability --- .../ModelMappingDiagram.module.scss | 11 +++- .../modelAlias/ModelMappingDiagram.tsx | 45 +++++++++++++--- .../modelAlias/ModelMappingDiagramColumns.tsx | 54 +++++++++++-------- 3 files changed, 77 insertions(+), 33 deletions(-) diff --git a/src/components/modelAlias/ModelMappingDiagram.module.scss b/src/components/modelAlias/ModelMappingDiagram.module.scss index c850f9e..561a2c2 100644 --- a/src/components/modelAlias/ModelMappingDiagram.module.scss +++ b/src/components/modelAlias/ModelMappingDiagram.module.scss @@ -17,8 +17,8 @@ user-select: none; @media (max-width: 768px) { - justify-content: flex-start; - gap: 16px; + // Give mobile extra horizontal room to reduce line overlap; users can swipe to scroll. + min-width: max(100%, 960px); padding: 12px 0; } } @@ -158,6 +158,13 @@ } } +.providerGroup { + display: flex; + align-items: center; + justify-content: flex-end; + width: 100%; +} + .sourceItem, .aliasItem { cursor: grab; diff --git a/src/components/modelAlias/ModelMappingDiagram.tsx b/src/components/modelAlias/ModelMappingDiagram.tsx index 2fdd84c..57906d9 100644 --- a/src/components/modelAlias/ModelMappingDiagram.tsx +++ b/src/components/modelAlias/ModelMappingDiagram.tsx @@ -72,6 +72,7 @@ export const ModelMappingDiagram = forwardRef([]); const [contextMenu, setContextMenu] = useState(null); const [collapsedProviders, setCollapsedProviders] = useState>(new Set()); + const [providerGroupHeights, setProviderGroupHeights] = useState>({}); const [renameState, setRenameState] = useState<{ oldAlias: string } | null>(null); const [renameValue, setRenameValue] = useState(''); const [renameError, setRenameError] = useState(''); @@ -179,6 +180,7 @@ export const ModelMappingDiagram = forwardRef = {}; const bezier = ( x1: number, y1: number, @@ -193,6 +195,15 @@ export const ModelMappingDiagram = forwardRef 0) { + const firstEl = sourceRefs.current.get(sources[0].id); + const lastEl = sourceRefs.current.get(sources[sources.length - 1].id); + if (firstEl && lastEl) { + const height = Math.max(0, Math.round(lastEl.getBoundingClientRect().bottom - firstEl.getBoundingClientRect().top)); + if (height > 0) nextProviderGroupHeights[provider] = height; + } + } + const providerEl = providerRefs.current.get(provider); if (!providerEl) return; const providerRect = providerEl.getBoundingClientRect(); @@ -241,6 +252,17 @@ export const ModelMappingDiagram = forwardRef { + const prevKeys = Object.keys(prev); + const nextKeys = Object.keys(nextProviderGroupHeights); + if (prevKeys.length !== nextKeys.length) return nextProviderGroupHeights; + for (const key of nextKeys) { + if (!(key in prev) || prev[key] !== nextProviderGroupHeights[key]) { + return nextProviderGroupHeights; + } + } + return prev; + }); }, [providerNodes, collapsedProviders]); useImperativeHandle( @@ -263,6 +285,12 @@ export const ModelMappingDiagram = forwardRef { + updateLines(); + const raf = requestAnimationFrame(updateLines); + return () => cancelAnimationFrame(raf); + }, [providerGroupHeights, updateLines]); + useEffect(() => { if (!containerRef.current || typeof ResizeObserver === 'undefined') return; const observer = new ResizeObserver(() => updateLines()); @@ -452,14 +480,15 @@ export const ModelMappingDiagram = forwardRef handleContextMenu(e, type, data)} - label={t('oauth_model_alias.diagram_providers')} - expandLabel={t('oauth_model_alias.diagram_expand')} + providerNodes={providerNodes} + collapsedProviders={collapsedProviders} + getProviderColor={getProviderColor} + providerGroupHeights={providerGroupHeights} + providerRefs={providerRefs} + onToggleCollapse={toggleProviderCollapse} + onContextMenu={(e, type, data) => handleContextMenu(e, type, data)} + label={t('oauth_model_alias.diagram_providers')} + expandLabel={t('oauth_model_alias.diagram_expand')} collapseLabel={t('oauth_model_alias.diagram_collapse')} /> ; getProviderColor: (provider: string) => string; + providerGroupHeights?: Record; providerRefs: RefObject>; onToggleCollapse: (provider: string) => void; onContextMenu: (e: ReactMouseEvent, type: 'provider' | 'background', data?: string) => void; @@ -18,6 +19,7 @@ export function ProviderColumn({ providerNodes, collapsedProviders, getProviderColor, + providerGroupHeights = {}, providerRefs, onToggleCollapse, onContextMenu, @@ -37,34 +39,40 @@ export function ProviderColumn({
{label}
{providerNodes.map(({ provider, sources }) => { const collapsed = collapsedProviders.has(provider); + const groupHeight = collapsed ? undefined : providerGroupHeights[provider]; return (
{ - if (el) providerRefs.current?.set(provider, el); - else providerRefs.current?.delete(provider); - }} - className={`${styles.item} ${styles.providerItem}`} - style={{ borderLeftColor: getProviderColor(provider) }} - onContextMenu={(e) => { - e.preventDefault(); - e.stopPropagation(); - onContextMenu(e, 'provider', provider); - }} + className={styles.providerGroup} + style={groupHeight ? { height: groupHeight } : undefined} > - - - {provider} - - {sources.length} + + + {provider} + + {sources.length} +
); })}