优化: 对话执行轨迹聚合与工具卡交互

前端聚合当前轮次工具调用数,替代每轮清零的完成计数,进度文案改轮次+累计口径
完成聚合语义由执行轨迹卡承接,工具卡复读修复与默认折叠收敛
流式与工具事件配套调整,新增轮次轨迹收集 composable
This commit is contained in:
lxy
2026-10-01 02:41:05 +08:00
parent e7cd035c62
commit 04acc4297d
15 changed files with 482 additions and 95 deletions
+29
View File
@@ -18,6 +18,13 @@
<span v-else-if="toolResultSummary(tc)" class="ai-tool-sub">{{ toolResultSummary(tc) }}</span>
</div>
<span class="ai-tool-status-dot" :class="'ai-tool-status-dot--' + (isFailed ? 'failed' : tc.status)"></span>
<!-- 统一卡形态第4要素:耗时(前端 startedAt/completedAt 差;历史消息无时间戳隐藏不显 0)。
hover 显绝对起止时刻,相对时间不再占卡片行(B 聚合卡统一)。 -->
<span
v-if="durationText"
class="ai-tool-duration"
:title="durationTitle"
>{{ durationText }}</span>
<span v-if="!shouldKeepOpen(tc)" class="ai-tool-collapse-hint" :class="{ 'is-open': isExpanded }">▸</span>
</div>
@@ -149,6 +156,8 @@ import {
import { parseDiffLines } from '@/composables/ai/useToolCardRender'
import { useToolCardHeader } from '@/composables/ai/useToolCardHeader'
import { useToolApproval } from '@/composables/ai/useToolApproval'
import { callDurationText } from '@/composables/ai/useTurnTrace'
import { formatDate } from '@/utils/time'
import type { AiToolCallInfo } from '@/api/types'
import ConfirmDialog from './ConfirmDialog.vue'
import ToolResultBody from './ToolResultBody.vue'
@@ -231,6 +240,15 @@ const isFailed = computed(() => {
/** write_file 审批 diff 行解析(复用 parseDiffLines 纯函数,数据源 props.tc.diff) */
const diffLines = computed(() => parseDiffLines(props.tc.diff))
/** 单卡耗时(前端时间差;历史消息无 startedAt/completedAt 返空串隐藏) */
const durationText = computed(() => callDurationText(props.tc.startedAt, props.tc.completedAt))
/** hover 提示:绝对起止时刻(相对时长 hover 可溯具体时间) */
const durationTitle = computed(() => {
const tc = props.tc
if (tc.startedAt == null || tc.completedAt == null) return ''
return `${formatDate(tc.startedAt)} ~ ${formatDate(tc.completedAt)}`
})
</script>
<style scoped>
@@ -299,6 +317,17 @@ const diffLines = computed(() => parseDiffLines(props.tc.diff))
/* -- Status dot (脉冲动画) -- */
.ai-tool-status-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
/* -- 卡片行耗时(统一卡形态第4要素:弱化等宽小字,不与工具名/摘要争焦点) -- */
.ai-tool-duration {
font-family: var(--df-font-mono);
font-size: 10px;
color: var(--df-text-dim);
opacity: 0.75;
flex-shrink: 0;
cursor: default;
user-select: none;
}
.ai-tool-status-dot--running {
background: var(--df-info); animation: pulseGlow 1.5s ease-in-out infinite; box-shadow: 0 0 6px var(--df-info);
}