4545
4646 <template v-else >
4747 <DynamicScroller
48- ref="scrollerRef"
4948 :items =" rowsWithId "
5049 :min-item-size =" 24 "
5150 key-field="rowId"
5655 :item =" row "
5756 :active =" active "
5857 :size-dependencies =" [
59- row .content ,
58+ row .plainText ,
59+ row .trailingPlainText ,
6060 activeFormat .messageTemplate ,
61+ activeFormat .messageSeparator ,
62+ activeFormat .docSeparator ,
63+ activeFormat .chunkSeparator ,
6164 ] "
6265 :data-index =" index "
6366 >
6467 <div class =" preview-row" >
6568 <div
66- v-if ="
67- row.type === 'documentSeparator' &&
68- activeFormat.docSeparator
69- "
69+ v-if =" row.type !== 'message'"
7070 class =" separator-preview"
7171 >
7272 <span
73- v-for =" (
74- token, tIdx
75- ) in docSeparatorTokens"
76- :key =" 'doc-' + tIdx"
73+ v-for =" (segment, tIdx) in row.segments"
74+ :key =" 'block-' + tIdx"
7775 >
78- <template v-if =" token .type === ' text' " >
79- {{ token.value }}
80- </template >
81- <br
82- v-else-if =" token.type === 'newline'"
83- />
84- <span
85- v-else-if =" token.type === 'tab'"
86- class =" tab-space"
87- ></span >
8876 <template
89- v-else-if ="
90- token .type === ' placeholder' &&
91- token .value === ' name'
92- "
77+ v-if =" segment .type === ' text' "
9378 >
94- {{ row.content }}
95- </template >
96- </span >
97- </div >
98-
99- <div
100- v-else-if ="
101- row.type === 'chunkSeparator' &&
102- activeFormat.chunkSeparator
103- "
104- class =" separator-preview"
105- >
106- <span
107- v-for =" (
108- token, tIdx
109- ) in chunkSeparatorTokens"
110- :key =" 'chunk-' + tIdx"
111- >
112- <template v-if =" token .type === ' text' " >
113- {{ token.value }}
79+ <span
80+ :style ="
81+ getSegmentStyle(segment)
82+ "
83+ >
84+ {{ segment.value }}
85+ </span >
11486 </template >
11587 <br
116- v-else-if =" token.type === 'newline'"
88+ v-else-if ="
89+ segment.type === 'newline'
90+ "
11791 />
11892 <span
119- v-else-if =" token .type === 'tab'"
93+ v-else-if =" segment .type === 'tab'"
12094 class =" tab-space"
12195 ></span >
122- <template
123- v-else-if ="
124- token .type === ' placeholder' &&
125- token .value === ' name'
126- "
127- >
128- {{ row.content }}
129- </template >
13096 </span >
13197 </div >
13298
133- <div
134- v-else-if =" row.type === 'message'"
135- class =" message-preview"
136- >
99+ <div v-else class =" message-preview" >
137100 <span
138- v-for =" (token , tIdx) in messageTokens "
101+ v-for =" (segment , tIdx) in row.segments "
139102 :key =" 'msg-' + tIdx"
140103 >
141- <template v-if =" token .type === ' text' " >
142- {{ token.value }}
104+ <template
105+ v-if =" segment .type === ' text' "
106+ >
107+ <span
108+ :style ="
109+ getSegmentStyle(segment)
110+ "
111+ >
112+ {{ segment.value }}
113+ </span >
143114 </template >
144115 <br
145- v-else-if =" token.type === 'newline'"
116+ v-else-if ="
117+ segment.type === 'newline'
118+ "
146119 />
147120 <span
148- v-else-if =" token .type === 'tab'"
121+ v-else-if =" segment .type === 'tab'"
149122 class =" tab-space"
150123 ></span >
151- <span
152- v-else-if ="
153- token.type === 'placeholder'
154- "
155- :style ="
156- getStyleForPlaceholder(
157- token.value,
158- row,
159- )
160- "
161- >
162- <template
163- v-for =" (
164- segment , segmentIdx
165- ) in getPlaceholderSegments (
166- token .value ,
167- row ,
168- ) "
169- :key =" ` placeholder-${tIdx }-${segmentIdx } ` "
170- >
171- <br
172- v-if ="
173- token.value ===
174- 'content' &&
175- segmentIdx > 0
176- "
177- />
178- {{ segment }}
179- </template >
180- </span >
181124 </span >
182125
183126 <span class =" message-separator" >
184127 <span
185128 v-for =" (
186- token , tIdx
187- ) in messageSeparatorTokens "
129+ segment , tIdx
130+ ) in row.trailingSegments "
188131 :key =" 'sep-' + tIdx"
189132 >
190133 <template
191- v-if =" token .type === ' text' "
134+ v-if =" segment .type === ' text' "
192135 >
193- {{ token.value }}
136+ <span
137+ :style ="
138+ getSegmentStyle(segment)
139+ "
140+ >
141+ {{ segment.value }}
142+ </span >
194143 </template >
195144 <br
196145 v-else-if ="
197- token .type === 'newline'
146+ segment .type === 'newline'
198147 "
199148 />
200149 <span
201- v-else-if =" token.type === 'tab'"
150+ v-else-if ="
151+ segment.type === 'tab'
152+ "
202153 class =" tab-space"
203154 ></span >
204155 </span >
216167<script setup lang="ts">
217168import { computed } from ' vue' ;
218169import { Eye , X , SquareSplitHorizontal } from ' @lucide/vue' ;
170+ import { DynamicScroller , DynamicScrollerItem } from ' vue-virtual-scroller' ;
171+ import ' vue-virtual-scroller/dist/vue-virtual-scroller.css' ;
172+
173+ import {
174+ renderExportDocument ,
175+ type RenderedExportSegment ,
176+ } from ' @/io/export/exportRender' ;
177+ import { flattenLogToRows } from ' @/io/export/flattener' ;
178+ import { useExportStore } from ' @/stores/exportStore' ;
219179import { useLogStore } from ' @/stores/logStore' ;
220180import { useStyleStore } from ' @/stores/styleStore' ;
221- import { useExportStore } from ' @/stores/exportStore' ;
222181import { useUiStore } from ' @/stores/uiStore' ;
223182import { useWindowStore } from ' @/stores/windowStore' ;
224- import { flattenLogToRows } from ' @/io/export/flattener' ;
225- import { parseTemplate , getPlaceholderValue } from ' @/io/export/templateParser' ;
226- import type { ExportRow } from ' @/types/export' ;
227- import { DynamicScroller , DynamicScrollerItem } from ' vue-virtual-scroller' ;
228- import ' vue-virtual-scroller/dist/vue-virtual-scroller.css' ;
229183
230184const logStore = useLogStore ();
231185const styleStore = useStyleStore ();
@@ -236,6 +190,7 @@ const props = defineProps<{
236190 windowId: string ;
237191 originalId: string ;
238192}>();
193+
239194const effectiveWindowId = computed (() => props .windowId );
240195const isActive = computed (() => windowStore .activeFocus === props .windowId );
241196const activeFormat = computed (
@@ -250,17 +205,19 @@ const canClose = computed(() => {
250205 );
251206});
252207
253- // 计算行数据,并为每一行添加 rowId 供虚拟滚动 key 使用
254208const rowsWithId = computed (() => {
255209 const rawRows = flattenLogToRows (
256210 logStore .documents ,
257211 styleStore .viewSettings ,
258212 styleStore .activeRules ,
259213 );
260- return rawRows .map ((row , index ) => ({
261- ... row ,
262- rowId: ` ${row .type }-${index } ` ,
263- }));
214+
215+ return renderExportDocument (rawRows , activeFormat .value ).blocks .map (
216+ (block , index ) => ({
217+ ... block ,
218+ rowId: ` ${block .type }-${index } ` ,
219+ }),
220+ );
264221});
265222
266223// 兼容旧变量名
@@ -289,41 +246,15 @@ function handleClose() {
289246 }
290247}
291248
292- const messageTokens = computed (() =>
293- parseTemplate (activeFormat .value .messageTemplate ),
294- );
295- const messageSeparatorTokens = computed (() =>
296- parseTemplate (activeFormat .value .messageSeparator ),
297- );
298- const docSeparatorTokens = computed (() =>
299- parseTemplate (activeFormat .value .docSeparator || ' ' ),
300- );
301- const chunkSeparatorTokens = computed (() =>
302- parseTemplate (activeFormat .value .chunkSeparator || ' ' ),
303- );
304-
305- function getPlaceholderSegments(key : string , row : ExportRow ): string [] {
306- const value = getPlaceholderValue (key , row , activeFormat .value );
307- return key === ' content' ? value .split (' \n ' ) : [value ];
308- }
309-
310- function getStyleForPlaceholder(
311- key : string ,
312- row : ExportRow ,
249+ function getSegmentStyle(
250+ segment : RenderedExportSegment ,
313251): Record <string , string > {
314- const exportStyle =
315- key === ' name'
316- ? row .nameStyle
317- : key === ' content'
318- ? row .contentStyle
319- : undefined ;
320-
321- if (! exportStyle ) return {};
252+ if (segment .type !== ' text' || ! segment .style ) return {};
322253
323254 const css: Record <string , string > = {};
324- if (exportStyle . color ) css .color = exportStyle .color ;
325- if (exportStyle .bold ) css .fontWeight = ' bold' ;
326- if (exportStyle .italic ) css .fontStyle = ' italic' ;
255+ if (segment . style . color ) css .color = segment . style .color ;
256+ if (segment . style .bold ) css .fontWeight = ' bold' ;
257+ if (segment . style .italic ) css .fontStyle = ' italic' ;
327258
328259 return css ;
329260}
0 commit comments