修复: aichat advance_task渲染显任务名 + 审批防双击 + time.ts销账
- UX-260618-14: advance_task 工具结果/审批卡显任务名替代UUID 前端 ToolCard 取 r.title fallback r.id + TASK_ID_TOOL_ARG 审批卡 task_id→title 回显 + i18n 后端 audit resolve_task_label 查 tasks 表(原误查 projects恒报不存在) + 删 tool_display_hint 短路让模板生效 - UX-260618-16: time.ts formatDate .value 已修(CR-24/25闭环),漏销账补登 - UX-260618-17: ProjectDetail handleApprovalMulti 补 submitting try/finally + 模板联动防双击
This commit is contained in:
@@ -473,9 +473,10 @@ function formatToolResult(tc: AiToolCallInfo): string {
|
||||
: t('aiTool.updated')
|
||||
case 'advance_task':
|
||||
// UX-260618-09: review_rounds>0 显退回累加轮数,=0 回退原文案(首推无噪音)
|
||||
// UX-260618-14: 后端返 TaskRecord(含 title),优先显 title,无则回退 id(防裸 UUID)
|
||||
return typeof r.review_rounds === 'number' && r.review_rounds > 0
|
||||
? t('aiTool.advancedTaskWithRounds', { id: r.id || '', status: r.status || '', n: r.review_rounds })
|
||||
: t('aiTool.advancedTask', { id: r.id || '', status: r.status || '' })
|
||||
? t('aiTool.advancedTaskWithRounds', { title: r.title || r.id || '', status: r.status || '', n: r.review_rounds })
|
||||
: t('aiTool.advancedTask', { title: r.title || r.id || '', status: r.status || '' })
|
||||
case 'delete_task':
|
||||
return r.deleted ? t('aiTool.deleted') : t('aiTool.deleteIneffective')
|
||||
case 'delete_file':
|
||||
@@ -796,6 +797,16 @@ function projectNameById(id: string): string | undefined {
|
||||
?? projectStore.deletedProjects.find(p => p.id === id)?.name
|
||||
}
|
||||
|
||||
/**
|
||||
* 按 id 查任务标题:审批 advance_task/run_workflow 的 task_id 时,把裸 UUID 转标题。
|
||||
* 复用 project store 已加载的 state.tasks(仅当前项目范围),不新增网络请求。
|
||||
* state.tasks 非「全量」(按当前项目/筛选加载),查不到时调用方走裸 id fallback——
|
||||
* 审批卡 task_id 多属当前活动项目,命中率足够,跨项目任务降级显 id 可接受。
|
||||
*/
|
||||
function taskNameById(id: string): string | undefined {
|
||||
return projectStore.tasks.find(t => t.id === id)?.title
|
||||
}
|
||||
|
||||
/** 工具名 → 该工具中代表项目 id 的参数 key(仅项目类工具特化;delete_task 的 id 是任务 id,不在此列) */
|
||||
const PROJECT_ID_TOOL_ARG: Record<string, 'id' | 'project_id'> = {
|
||||
delete_project: 'id',
|
||||
@@ -806,6 +817,15 @@ const PROJECT_ID_TOOL_ARG: Record<string, 'id' | 'project_id'> = {
|
||||
create_task: 'project_id',
|
||||
}
|
||||
|
||||
/**
|
||||
* 工具名 → 该工具中代表任务 id 的参数 key(任务类工具特化)。
|
||||
* advance_task 的任务 id 在 "id" key,run_workflow 在 "task_id" key。
|
||||
*/
|
||||
const TASK_ID_TOOL_ARG: Record<string, 'id' | 'task_id'> = {
|
||||
advance_task: 'id',
|
||||
run_workflow: 'task_id',
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批参数值展示(AR-3):对项目类工具的 id/project_id 特化——优先回显项目名,查不到则显示
|
||||
* 「项目已不存在」提示 + 原 id,避免用户只看到一串裸 id 不知道是什么数据。
|
||||
@@ -821,6 +841,16 @@ function displayArgValue(arg: { key: string; val: unknown }): string {
|
||||
return t('aiTool.projectIdNotFound', { id })
|
||||
}
|
||||
}
|
||||
// UX-260618-14:advance_task/run_workflow 的 task_id → 任务标题(store.tasks 查,无则标 id)
|
||||
const taskArgKey = TASK_ID_TOOL_ARG[props.tc.name]
|
||||
if (taskArgKey && arg.key === taskArgKey) {
|
||||
const id = typeof arg.val === 'string' ? arg.val : ''
|
||||
if (id) {
|
||||
const name = taskNameById(id)
|
||||
if (name) return t('aiTool.taskLabel', { name })
|
||||
return t('aiTool.taskIdNotFound', { id })
|
||||
}
|
||||
}
|
||||
return formatArgValue(arg.val)
|
||||
}
|
||||
|
||||
@@ -889,8 +919,9 @@ function toolResultSummary(tc: AiToolCallInfo): string {
|
||||
? t('aiTool.updatedTaskField', { id: r.id || '', field: r.field || '' })
|
||||
: t('aiTool.updated')
|
||||
case 'advance_task': return typeof r.review_rounds === 'number' && r.review_rounds > 0
|
||||
? t('aiTool.advancedTaskWithRounds', { id: r.id || '', status: r.status || '', n: r.review_rounds })
|
||||
: t('aiTool.advancedTask', { id: r.id || '', status: r.status || '' })
|
||||
// UX-260618-14: 优先显 title(后端返 TaskRecord),无则回退 id,防裸 UUID
|
||||
? t('aiTool.advancedTaskWithRounds', { title: r.title || r.id || '', status: r.status || '', n: r.review_rounds })
|
||||
: t('aiTool.advancedTask', { title: r.title || r.id || '', status: r.status || '' })
|
||||
case 'delete_project':
|
||||
case 'delete_task': return r.deleted ? t('aiTool.deleted') : t('aiTool.deleteIneffective')
|
||||
case 'delete_file': return r.permanent
|
||||
|
||||
@@ -64,9 +64,9 @@ export default {
|
||||
|
||||
// UX-260616-04: formatToolResult covers all tools with human-readable summaries (missing keys)
|
||||
updatedTaskField: 'Task {id} updated field {field}',
|
||||
advancedTask: 'Task {id} advanced to {status}',
|
||||
// UX-260618-09: advance_task return-round accumulation (shown only when >0)
|
||||
advancedTaskWithRounds: 'Task {id} advanced to {status} (returned {n} times)',
|
||||
advancedTask: 'Task「{title}」 advanced to {status}',
|
||||
// UX-260618-09: advance_task return-round accumulation (shown only when >0); UX-260618-14: {title} = task name (TaskRecord), fallback id
|
||||
advancedTaskWithRounds: 'Task「{title}」 advanced to {status} (returned {n} times)',
|
||||
commandOk: 'Command succeeded ({ms} ms)',
|
||||
commandFailed: 'Command failed (exit code {code})',
|
||||
commandOutputLines: '{n} lines of output',
|
||||
@@ -97,6 +97,9 @@ export default {
|
||||
|
||||
projectLabel: '"{name}"',
|
||||
projectIdNotFound: '(project not found, id={id})',
|
||||
// UX-260618-14: advance_task/run_workflow task_id → task title (store.tasks lookup; fallback id)
|
||||
taskLabel: '"{name}"',
|
||||
taskIdNotFound: '(task not in current list, id={id})',
|
||||
|
||||
// AE-2025-05: High-risk approval second confirm (ask once more before approve; misclick cancellable)
|
||||
confirmHighDelete: 'Permanently delete? This action cannot be undone',
|
||||
|
||||
@@ -65,9 +65,9 @@ export default {
|
||||
|
||||
// UX-260616-04:formatToolResult 覆盖全部工具产出人类可读摘要(补缺失 key)
|
||||
updatedTaskField: '任务 {id} 已更新字段 {field}',
|
||||
advancedTask: '任务 {id} 已推进至 {status}',
|
||||
// UX-260618-09:advance_task 退回累加轮数(>0 才显)
|
||||
advancedTaskWithRounds: '任务 {id} 已推进至 {status}(已退回 {n} 次)',
|
||||
advancedTask: '任务「{title}」已推进至 {status}',
|
||||
// UX-260618-09:advance_task 退回累加轮数(>0 才显);UX-260618-14:{title} 显任务名(后端返 TaskRecord),回退 id
|
||||
advancedTaskWithRounds: '任务「{title}」已推进至 {status}(已退回 {n} 次)',
|
||||
commandOk: '命令成功({ms} 毫秒)',
|
||||
commandFailed: '命令失败(退出码 {code})',
|
||||
commandOutputLines: '{n} 行输出',
|
||||
@@ -99,6 +99,9 @@ export default {
|
||||
// 审批参数特化(id/project_id 回显项目名,查不到标注原 id)
|
||||
projectLabel: '「{name}」',
|
||||
projectIdNotFound: '(项目已不存在, id={id})',
|
||||
// UX-260618-14:advance_task/run_workflow 的 task_id 回显任务标题(查 store.tasks,无则标 id)
|
||||
taskLabel: '「{name}」',
|
||||
taskIdNotFound: '(任务不在当前列表, id={id})',
|
||||
|
||||
// AE-2025-05:High 风险审批二次确认文案(批准前再问一次,误点可取消)
|
||||
confirmHighDelete: '确定永久删除?此操作不可恢复',
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
:disabled="multiDecisions.length === 0"
|
||||
:disabled="submitting || multiDecisions.length === 0"
|
||||
@click="handleApprovalMulti"
|
||||
>
|
||||
{{ $t('projectDetail.approvalConfirm', { count: multiDecisions.length }) }}
|
||||
@@ -430,10 +430,15 @@ const multiDecisions = ref<string[]>([])
|
||||
|
||||
async function handleApprovalMulti() {
|
||||
if (multiDecisions.value.length === 0) return
|
||||
// 统一传 decisions 数组,store 按 select_type 分派单/多选
|
||||
await store.approveHumanApproval([...multiDecisions.value])
|
||||
multiDecisions.value = []
|
||||
showApprovalDialog.value = false
|
||||
submitting.value = true
|
||||
try {
|
||||
// 统一传 decisions 数组,store 按 select_type 分派单/多选
|
||||
await store.approveHumanApproval([...multiDecisions.value])
|
||||
multiDecisions.value = []
|
||||
showApprovalDialog.value = false
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// ── 取消审批(调 cancel_workflow_node IPC 置节点 Cancelled)──
|
||||
|
||||
Reference in New Issue
Block a user