55
66 <!-- 助手消息 -->
77 <div v-else-if =" message.type === 'ai'" class =" assistant-message" >
8- <div v-if =" message .reasoning_content" class =" reasoning-box" >
8+ <div v-if =" parsedMessage .reasoning_content" class =" reasoning-box" >
99 <a-collapse v-model:activeKey =" reasoningActiveKey" :bordered =" false" >
1010 <template #expandIcon =" { isActive } " >
1111 <caret-right-outlined :rotate =" isActive ? 90 : 0" />
1212 </template >
1313 <a-collapse-panel key =" show" :header =" message.status=='reasoning' ? '正在思考...' : '推理过程'" class =" reasoning-header" >
14- <p class =" reasoning-content" >{{ message .reasoning_content.trim() }}</p >
14+ <p class =" reasoning-content" >{{ parsedMessage .reasoning_content.trim() }}</p >
1515 </a-collapse-panel >
1616 </a-collapse >
1717 </div >
1818
1919 <!-- 消息内容 -->
2020 <!-- <div v-else-if="message.content" v-html="renderMarkdown(message)" class="message-md"></div> -->
21- <MdPreview v-else- if =" message .content" ref =" editorRef"
21+ <MdPreview v-if =" parsedMessage .content" ref =" editorRef"
2222 editorId =" preview-only"
2323 previewTheme =" github"
2424 :showCodeRowNumber =" false"
25- :modelValue =" message .content"
25+ :modelValue =" parsedMessage .content"
2626 :key =" message.id"
2727 class =" message-md" />
2828
29- <div v-else-if =" message .reasoning_content" class =" empty-block" ></div >
29+ <div v-else-if =" parsedMessage .reasoning_content" class =" empty-block" ></div >
3030
3131 <div v-if =" message.tool_calls && Object.keys(message.tool_calls).length > 0" class =" tool-calls-container" >
3232 <div v-for =" (toolCall, index) in message.tool_calls || {}" :key =" index" class =" tool-call-container" >
3838 <span class =" tool-name" >{{ toolCall.name || toolCall.function.name }}</span >
3939 </span >
4040 <span v-else >
41- <ThunderboltOutlined /> 工具 <span class =" tool-name" >{{ toolCall.name || toolCall.function.name }}</span > 执行完成
41+ <ThunderboltOutlined /> & nbsp ; 工具 <span class =" tool-name" >{{ toolCall.name || toolCall.function.name }}</span > 执行完成
4242 </span >
4343 </div >
4444 <div class =" tool-content" v-show =" expandedToolCalls.has(toolCall.id)" >
4545 <div class =" tool-params" v-if =" toolCall.args || toolCall.function.arguments" >
4646 <div class =" tool-params-content" >
47- <pre > 参数: {{ toolCall.args || toolCall.function.arguments }}</ pre >
47+ <strong > 参数:</ strong > {{ toolCall.args || toolCall.function.arguments }}
4848 </div >
4949 </div >
5050 <div class =" tool-result" v-if =" toolCall.tool_call_result && toolCall.tool_call_result.content" >
@@ -137,6 +137,26 @@ const isEmptyAndLoading = computed(() => {
137137 return isEmpty && isLoading;
138138});
139139
140+ const parsedMessage = computed (() => {
141+ const message = props .message ;
142+ if (message .content ) {
143+ // 匹配完整的 <think>...</think> 标签
144+ const thinkContent = message .content .match (/ <think>(. *? )<\/ think>/ s );
145+ if (thinkContent) {
146+ message .reasoning_content = thinkContent[1 ];
147+ message .content = message .content .replace (/ <think>(. *? )<\/ think>/ s , ' ' );
148+ } else {
149+ // 匹配未闭合的 <think> 标签,处理加载中的情况
150+ const incompleteThinkContent = message .content .match (/ <think>(. *? )$ / s );
151+ if (incompleteThinkContent) {
152+ message .reasoning_content = incompleteThinkContent[1 ];
153+ message .content = message .content .replace (/ <think>(. *? )$ / s , ' ' );
154+ }
155+ }
156+ }
157+ return message;
158+ });
159+
140160const toggleToolCall = (toolCallId ) => {
141161 if (expandedToolCalls .value .has (toolCallId)) {
142162 expandedToolCalls .value .delete (toolCallId);
@@ -207,14 +227,61 @@ const toggleToolCall = (toolCallId) => {
207227 .reasoning-box {
208228 margin-top : 10px ;
209229 margin-bottom : 15px ;
210- border-radius : 8px ;
211- border : 1px solid var (--main-light-3 );
230+ border-radius : 12px ;
231+ border : 1px solid var (--gray-200 );
232+ background-color : var (--gray-50 );
233+ box-shadow : 0 2px 4px rgba (0 , 0 , 0 , 0.02 );
234+ overflow : hidden ;
235+ transition : all 0.2s ease ;
236+
237+ & :hover {
238+ border-color : var (--main-300 );
239+ box-shadow : 0 4px 8px rgba (0 , 0 , 0 , 0.08 );
240+ }
241+
242+ :deep(.ant-collapse ) {
243+ background-color : transparent ;
244+ border : none ;
245+
246+ .ant-collapse-item {
247+ border : none ;
248+
249+ .ant-collapse-header {
250+ padding : 12px 16px ;
251+ background-color : var (--gray-100 );
252+ font-size : 14px ;
253+ font-weight : 500 ;
254+ color : var (--gray-800 );
255+ border-bottom : 1px solid var (--gray-200 );
256+ transition : all 0.2s ease ;
257+
258+ & :hover {
259+ background-color : var (--gray-150 );
260+ }
261+
262+ .ant-collapse-expand-icon {
263+ color : var (--main-600 );
264+ }
265+ }
266+
267+ .ant-collapse-content {
268+ border : none ;
269+ background-color : transparent ;
270+
271+ .ant-collapse-content-box {
272+ padding : 16px ;
273+ background-color : var (--gray-50 );
274+ }
275+ }
276+ }
277+ }
212278
213279 .reasoning-content {
214280 font-size : 13px ;
215281 color : var (--gray-800 );
216282 white-space : pre-wrap ;
217283 margin : 0 ;
284+ line-height : 1.6 ;
218285 }
219286 }
220287
@@ -251,11 +318,18 @@ const toggleToolCall = (toolCallId) => {
251318 :deep(.tool-call-display ) {
252319 background-color : var (--gray-50 );
253320 border : 1px solid var (--gray-200 );
254- border-radius : 8 px ;
321+ border-radius : 12 px ;
255322 overflow : hidden ;
323+ box-shadow : 0 2px 4px rgba (0 , 0 , 0 , 0.02 );
324+ transition : all 0.2s ease ;
325+
326+ & :hover {
327+ border-color : var (--main-300 );
328+ box-shadow : 0 4px 8px rgba (0 , 0 , 0 , 0.08 );
329+ }
256330
257331 .tool-header {
258- padding : 10 px 12px ;
332+ padding : 12px 16 px ;
259333 background-color : var (--gray-100 );
260334 font-size : 14px ;
261335 font-weight : 500 ;
@@ -267,9 +341,20 @@ const toggleToolCall = (toolCallId) => {
267341 cursor : pointer ;
268342 user-select : none ;
269343 position : relative ;
344+ transition : all 0.2s ease ;
345+
346+ & :hover {
347+ background-color : var (--gray-150 );
348+ }
270349
271350 .anticon {
272351 color : var (--main-600 );
352+ font-size : 16px ;
353+ }
354+
355+ .tool-name {
356+ font-weight : 600 ;
357+ color : var (--main-700 );
273358 }
274359
275360 .step-badge {
@@ -285,27 +370,30 @@ const toggleToolCall = (toolCallId) => {
285370
286371 .tool-content {
287372 transition : all 0.3s ease ;
373+
288374 .tool-params {
289- padding : 10 px 12 px ;
375+ padding : 16 px ;
290376 background-color : var (--gray-50 );
291377
292378 .tool-params-header {
293379 background-color : var (--gray-100 );
294380 font-size : 13px ;
295381 color : var (--gray-800 );
382+ margin-bottom : 8px ;
383+ font-weight : 500 ;
296384 }
297385
298386 .tool-params-content {
299387 margin : 0 ;
300388 font-size : 13px ;
301389 background-color : var (--gray-100 );
302- border-radius : 4px ;
303- padding : 8px ;
304390 overflow-x : auto ;
305391 color : var (--gray-800 );
392+ line-height : 1.5 ;
306393
307394 pre {
308395 margin : 0 ;
396+ font-family : ' Monaco' , ' Menlo' , ' Ubuntu Mono' , monospace ;
309397 }
310398 }
311399 }
@@ -315,7 +403,7 @@ const toggleToolCall = (toolCallId) => {
315403 background-color : transparent ;
316404
317405 .tool-result-header {
318- padding : 10 px 12px ;
406+ padding : 12px 16 px ;
319407 background-color : var (--gray-100 );
320408 font-size : 12px ;
321409 color : var (--gray-700 );
0 commit comments