@@ -178,24 +178,54 @@ const layoutNodes = computed(() => {
178178 const nodes: LayoutNode [] = []
179179 const nodeWidth = 200 // 增加节点宽度
180180 const nodeHeight = 45 // 稍微增加节点高度
181- const levelGap = Math .max (250 , containerWidth .value / 6 ) // 动态调整层级间距
181+ const levelGap = Math .min ( 280 , Math . max (220 , containerWidth .value / 8 )) // 限制最大层级间距,使布局更紧凑
182182 const siblingGap = 70 // 增加兄弟节点间距
183+ const truncateText = (text : string , maxWidth : number ) => {
184+ // 基于节点宽度和字体大小计算最大字符数
185+ // 节点宽度200px,减去图标35px和右侧边距20px,可用宽度约145px
186+ // 字体大小13px,平均字符宽度约8px(中文)或6px(英文)
187+ const availableWidth = maxWidth - 55 // 减去图标和边距
188+ const avgCharWidth = / [\u4e00 -\u9fa5 ] / .test (text ) ? 8 : 6 // 中文字符更宽
189+ const maxChars = Math .floor (availableWidth / avgCharWidth )
183190
191+ if (text .length <= maxChars ) {
192+ return text
193+ }
194+
195+ // 优先在标点符号处截断
196+ const punctuation = / [。!?;,、] /
197+ let truncateIndex = maxChars - 4 // 为省略号留空间
198+
199+ // 向前查找最近的标点符号
200+ for (let i = truncateIndex ; i >= Math .max (0 , truncateIndex - 10 ); i -- ) {
201+ if (punctuation .test (text [i ])) {
202+ truncateIndex = i + 1
203+ break
204+ }
205+ }
206+
207+ // 避免在单词中间截断(英文)
208+ if (! / [\u4e00 -\u9fa5 ] / .test (text )) {
209+ while (truncateIndex > 0 && text [truncateIndex ] !== ' ' && text [truncateIndex - 1 ] !== ' ' ) {
210+ truncateIndex --
211+ }
212+ }
213+
214+ return text .substring (0 , truncateIndex ).trim () + ' ...'
215+ }
184216 // 计算每个节点的位置
185217 const calculateLayout = (nodeId : string , level : number , siblingIndex : number , parentX ? : number , parentY ? : number ) => {
186218 const node = props .conversationTree .get (nodeId )
187219 if (! node ) return
188220
189- const truncatedText = node .content .length > 25
190- ? node .content .substring (0 , 25 ) + ' ...'
191- : node .content
221+ const truncatedText = truncateText (node .content , nodeWidth )
192222
193223 let x: number
194224 let y: number
195225
196226 if (level === 0 ) {
197- // 根节点居中
198- x = svgWidth .value / 2 - nodeWidth / 2
227+ // 根节点位置优化 - 不完全居中,留出更多右侧空间
228+ x = Math . min ( 100 , svgWidth .value / 6 )
199229 y = 60
200230 } else {
201231 // 子节点布局
@@ -343,7 +373,7 @@ onUnmounted(() => {
343373 border-left : 1px solid rgba (212 , 175 , 55 , 0.2 );
344374 overflow : hidden ;
345375 position : relative ;
346- min-width : 1200px ;
376+ /* min-width: 1200px; */
347377 width : 100% ; /* 确保占满父容器 */
348378}
349379
@@ -547,8 +577,18 @@ onUnmounted(() => {
547577 font-family : ' Inter' , ' SF Pro Display' , sans-serif ;
548578 font-weight : 500 ;
549579 transition : all 0.4s cubic-bezier (0.4 , 0 , 0.2 , 1 );
580+ /* 添加文字渲染优化 */
581+ text-rendering : optimizeLegibility ;
582+ -webkit-font-smoothing : antialiased ;
583+ /* 确保文字不会溢出节点 */
584+ dominant-baseline : middle ;
550585}
551586
587+ /* 添加省略号样式优化 */
588+ .node-text ::after {
589+ content : ' ' ;
590+ /* 可以通过伪元素添加更好的省略号效果 */
591+ }
552592.node-group :hover .node-text {
553593 font-weight : 600 ;
554594 fill : #ffffff ;
0 commit comments