修复: gen_stream判重+重试分类+状态机最短路径+既有测试修复

This commit is contained in:
lxy
2026-08-12 00:29:06 +08:00
parent 9407f821b9
commit d31a27512c
36 changed files with 2614 additions and 264 deletions
+69 -7
View File
@@ -88,6 +88,7 @@ export const TASK_STATUS_LABELS: Record<string, string> = {
done: 'tasks.status.done',
blocked: 'tasks.status.blocked',
cancelled: 'tasks.status.cancelled',
deferred: 'tasks.status.deferred',
}
// class 名对齐既有 css(Tasks/TaskDetail/ProjectDetail 均有 status-todo/progress/review/done/abandoned):
@@ -103,6 +104,7 @@ export const TASK_STATUS_CLASS: Record<string, string> = {
done: 'status-done',
blocked: 'status-blocked',
cancelled: 'status-abandoned',
deferred: 'status-deferred',
}
// D-260616-01 删旧 5 态前的老 DB 数据兼容映射(老 DB 可能存 completed/review_ready/merged/abandoned)
@@ -128,16 +130,76 @@ export function taskStatusClass(status: string): string {
}
// WK-8:任务状态机合法流转目标(源状态 → 可达目标态,对齐 TaskDetail.vue ADVANCE_MAP 的 target 集)。
// 列表快捷菜单据此过滤,避免直接置终态/非法跳转(done/cancelled 为终态,无推进目标);
// 列表快捷菜单据此过滤,避免直接置终态/非法跳转(done 为唯一终态,无推进目标;cancelled 可恢复);
// 新建/手动改状态仍走后端 TaskStatus::is_valid 兜底校验。
export const TASK_STATUS_TRANSITIONS: Record<string, string[]> = {
todo: ['in_progress', 'cancelled'],
in_progress: ['in_review', 'blocked', 'cancelled'],
in_review: ['testing', 'in_progress', 'blocked', 'cancelled'],
testing: ['done', 'in_review', 'blocked', 'cancelled'],
blocked: ['in_progress', 'cancelled'],
todo: ['in_progress', 'cancelled', 'deferred'],
in_progress: ['in_review', 'blocked', 'cancelled', 'deferred'],
in_review: ['testing', 'in_progress', 'blocked', 'cancelled', 'deferred'],
testing: ['done', 'in_review', 'blocked', 'cancelled', 'deferred'],
blocked: ['in_progress', 'cancelled', 'deferred'],
deferred: ['todo', 'cancelled'],
cancelled: ['todo'],
done: [],
cancelled: [],
}
// 状态语义排序(推进主链在前 → 暂停态 → 历史旁支),供状态多选 chips / 快捷菜单 / 看板列统一使用。
// 与后端 ALL_STATES / TASK_STATUS_TRANSITIONS 为同源集合,仅决定展示顺序。
export const TASK_STATUS_ORDER = [
'todo',
'in_progress',
'in_review',
'testing',
'done',
'blocked',
'deferred',
'cancelled',
] as const
/** 推进按钮映射(与 TASK_STATUS_TRANSITIONS 同源,附带 label i18n key + variant 样式)。 */
export interface AdvanceAction {
target: string
label: string
variant: string
}
export const ADVANCE_MAP: Record<string, AdvanceAction[]> = {
todo: [
{ target: 'in_progress', label: 'taskDetail.advance.toInProgress', variant: 'btn-primary' },
{ target: 'deferred', label: 'taskDetail.advance.defer', variant: 'btn-ghost' },
{ target: 'cancelled', label: 'taskDetail.advance.cancel', variant: 'btn-danger' },
],
in_progress: [
{ target: 'in_review', label: 'taskDetail.advance.toInReview', variant: 'btn-primary' },
{ target: 'blocked', label: 'taskDetail.advance.block', variant: 'btn-ghost' },
{ target: 'deferred', label: 'taskDetail.advance.defer', variant: 'btn-ghost' },
{ target: 'cancelled', label: 'taskDetail.advance.cancel', variant: 'btn-danger' },
],
in_review: [
{ target: 'testing', label: 'taskDetail.advance.toTesting', variant: 'btn-primary' },
{ target: 'in_progress', label: 'taskDetail.advance.sendBack', variant: 'btn-ghost' },
{ target: 'blocked', label: 'taskDetail.advance.block', variant: 'btn-ghost' },
{ target: 'deferred', label: 'taskDetail.advance.defer', variant: 'btn-ghost' },
{ target: 'cancelled', label: 'taskDetail.advance.cancel', variant: 'btn-danger' },
],
testing: [
{ target: 'done', label: 'taskDetail.advance.toDone', variant: 'btn-primary' },
{ target: 'in_review', label: 'taskDetail.advance.sendBackToReview', variant: 'btn-ghost' },
{ target: 'blocked', label: 'taskDetail.advance.block', variant: 'btn-ghost' },
{ target: 'deferred', label: 'taskDetail.advance.defer', variant: 'btn-ghost' },
{ target: 'cancelled', label: 'taskDetail.advance.cancel', variant: 'btn-danger' },
],
blocked: [
{ target: 'in_progress', label: 'taskDetail.advance.resume', variant: 'btn-primary' },
{ target: 'deferred', label: 'taskDetail.advance.defer', variant: 'btn-ghost' },
{ target: 'cancelled', label: 'taskDetail.advance.cancel', variant: 'btn-danger' },
],
deferred: [
{ target: 'todo', label: 'taskDetail.advance.resume', variant: 'btn-primary' },
{ target: 'cancelled', label: 'taskDetail.advance.cancel', variant: 'btn-danger' },
],
cancelled: [
{ target: 'todo', label: 'taskDetail.advance.resume', variant: 'btn-primary' },
],
}
// ── 任务优先级 ──