修复: gen_stream判重+重试分类+状态机最短路径+既有测试修复
This commit is contained in:
@@ -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' },
|
||||
],
|
||||
}
|
||||
|
||||
// ── 任务优先级 ──
|
||||
|
||||
Reference in New Issue
Block a user