优化: aichat 工具体验补强(切生成会话占位气泡治丢首响应/read_symbol符号级提示/失败引导/审批失败toast) + 修复 WorkflowDagDisplay 崩页与 aiChat i18n 缺key

This commit is contained in:
lxy
2026-08-09 21:34:53 +08:00
parent cad76ffdf2
commit 37040616bd
10 changed files with 335 additions and 21 deletions
+8
View File
@@ -188,6 +188,8 @@ const { toast, showToast } = useToast()
let _unlistenToolSlow: (() => void) | null = null
// AE-2025-04: 会话信任自动放行 toast unlistener(useAiEvents 经事件总线中转,同 _unlistenToolSlow 模式)
let _unlistenAutoApproved: (() => void) | null = null
// P1-e-d: 审批失败 toast unlistener(useAiApproval 审批 IPC 未送达经事件总线 emit,同 _unlistenToolSlow 模式)
let _unlistenAiToast: (() => void) | null = null
// 第二批抽离: inputText/inputEl/图片输入/技能/实体联想/handleSend 已迁移至 ChatInput.vue
// chatInputRef: 父调 expose(focus/startEditFocus/clearInput/hasUnsentInput/sendExamplePrompt)
@@ -466,6 +468,7 @@ onBeforeUnmount(() => {
store.stopContextListener()
if (_unlistenToolSlow) { _unlistenToolSlow(); _unlistenToolSlow = null } // B-260616-12
if (_unlistenAutoApproved) { _unlistenAutoApproved(); _unlistenAutoApproved = null } // AE-2025-04
if (_unlistenAiToast) { _unlistenAiToast(); _unlistenAiToast = null } // P1-e-d
// toast timer 清理由 useToast composable 的 onUnmounted 自动管理
})
@@ -503,6 +506,11 @@ onMounted(async () => {
_unlistenAutoApproved = await listen<{ tool: string; dir: string }>('ai-tool-auto-approved-toast', (e) => {
showToast(t('aiChat.autoApprovedToast', { tool: e.payload.tool, dir: e.payload.dir }), 'info')
})
// P1-e-d: 审批失败 toast(useAiApproval.approveToolCall 审批 IPC 未送达经事件总线广播,
// 本组件 listen 弹本地 toast。主窗口/分离窗口各挂一份 AiChat,各自消费)
_unlistenAiToast = await listen<{ msg: string; type: 'info' | 'error' | 'warning' | 'success' }>('ai-toast', (e) => {
showToast(e.payload.msg, e.payload.type)
})
// F-15 阶段2: 注册上下文管理事件监听器(清空/压缩生命周期事件 → toast/刷新)
await initContextEventListeners()
// 恢复生成中态(刷新后/分离窗口接管):
@@ -91,8 +91,13 @@ const emit = defineEmits<{
}>()
const dag = computed<{ nodes: DagNode[]; edges: EdgeDef[] } | null>(() => {
try { return JSON.parse(props.dagJson) }
catch { return null }
try {
const parsed = JSON.parse(props.dagJson)
// 结构校验:dag_json 可能为 {} / 缺 nodes / nodes 非数组(执行记录无 DAG 或异常),解析成功但
// 缺字段会致下方 for..of 抛 "d.nodes is not iterable"。非预期结构 → null 显示空态而非崩页。
if (!parsed || !Array.isArray(parsed.nodes) || !Array.isArray(parsed.edges)) return null
return parsed as { nodes: DagNode[]; edges: EdgeDef[] }
} catch { return null }
})
const nodeTypeLabel: Record<string, string> = {