//! 项目 & 任务状态映射常量 //! //! 统一各视图(Projects/ProjectDetail/Tasks/Dashboard)的 label / badge / 阶段进度, //! 根治此前三套状态映射互相矛盾、任务文案两处不一致的问题。 // ── 项目状态 ── // 值为 i18n key,实际文案走 $t('projects.status.')(见 src/i18n/{zh-CN,en}/projects.ts) // F-09 对齐:删 in_progress/paused/cancelled(project 维度无数据产生源、无 UI 入口、无消费方), // 保留与后端真实生命周期一致的最小集(planning 常态 + 软删 deleted_at 由 list_deleted 单独处理)。 export const PROJECT_STATUS_LABELS: Record = { planning: 'projects.status.planning', active: 'projects.status.active', completed: 'projects.status.completed', } /** 项目状态 → 卡片 badge 样式 class */ export const PROJECT_STATUS_BADGE_CLASS: Record = { planning: 'stage-design', active: 'stage-coding', completed: 'stage-release', } /** 项目状态 → 阶段/进度信息(详情页 pipeline + Dashboard 进度条共用) */ export interface ProjectStageInfo { /** pipeline 步骤索引 0-4: idea/requirement/coding/testing/release */ stepIndex: number /** 进度百分比 */ progress: number /** Dashboard dot/chip 颜色档: coding/testing/release */ stage: string } export const PROJECT_STAGE_INFO: Record = { planning: { stepIndex: 0, progress: 20, stage: 'planning' }, active: { stepIndex: 2, progress: 55, stage: 'coding' }, completed: { stepIndex: 4, progress: 100, stage: 'release' }, } export function projectStatusLabel(status: string): string { return PROJECT_STATUS_LABELS[status] ?? status } export function projectBadgeClass(status: string): string { return PROJECT_STATUS_BADGE_CLASS[status] ?? 'stage-design' } export function projectStageInfo(status: string): ProjectStageInfo { // F-09:兜底用字面量而非 PROJECT_STAGE_INFO.planning,避免已删键的隐式依赖 return PROJECT_STAGE_INFO[status] ?? { stepIndex: 0, progress: 0, stage: 'planning' } } // ── 任务状态 ── // D-260616-01:前端对齐后端 7 态纯状态机(crates/df-core/src/types.rs TaskStatus) // 删旧 5 态 Git 工作流导向(review_ready/merged/abandoned)。 // 后端 task.rs update_task 写 status 经 TaskStatus::is_valid 拦截,旧 5 态无法落库; // migrations.rs V1 无 seed,create_task 默认 todo → 新 DB 无旧 5 态数据,安全对齐。 // // 值为 i18n key,实际文案走 $t('tasks.status.')(见 src/i18n/{zh-CN,en}/tasks.ts) export const TASK_STATUS_LABELS: Record = { todo: 'tasks.status.todo', in_progress: 'tasks.status.in_progress', in_review: 'tasks.status.in_review', testing: 'tasks.status.testing', done: 'tasks.status.done', blocked: 'tasks.status.blocked', cancelled: 'tasks.status.cancelled', } // class 名对齐既有 css(Tasks/TaskDetail/ProjectDetail 均有 status-todo/progress/review/done/abandoned): // - todo/in_progress/in_review/done 复用既有 class(保持跨视图样式一致,不破坏指派外文件) // - cancelled 复用 status-abandoned(同为 danger 红色,语义一致) // - testing/blocked 新增(Tasks.vue 自身样式补充;TaskDetail/ProjectDetail 遇此值兜底 status-todo 灰色, // 非破坏——仅样式保守,文案经 $t 正常渲染) export const TASK_STATUS_CLASS: Record = { todo: 'status-todo', in_progress: 'status-progress', in_review: 'status-review', testing: 'status-testing', done: 'status-done', blocked: 'status-blocked', cancelled: 'status-abandoned', } // D-260616-01 删旧 5 态前的老 DB 数据兼容映射(老 DB 可能存 completed/review_ready/merged/abandoned) // 新 DB 经 TaskStatus::is_valid 拦截不会有,但老 DB 未迁移清理时兜底显示而非 $t() 报错 const LEGACY_STATUS_MAP: Record = { completed: 'done', review_ready: 'in_review', merged: 'done', abandoned: 'cancelled', } /** 老DB 旧态映射(completed→done / review_ready→in_review 等),新 DB 无此数据 */ function mapLegacyStatus(status: string): string { return LEGACY_STATUS_MAP[status] ?? status } export function taskStatusLabel(status: string): string { return TASK_STATUS_LABELS[mapLegacyStatus(status)] ?? 'tasks.status.todo' } export function taskStatusClass(status: string): string { return TASK_STATUS_CLASS[mapLegacyStatus(status)] ?? 'status-todo' } // ── 任务优先级 ── export const PRIORITY_LABELS: Record = { 0: 'P0', 1: 'P1', 2: 'P2', 3: 'P3' } export const PRIORITY_CLASSES: Record = { 0: 'priority-critical', 1: 'priority-high', 2: 'priority-medium', 3: 'priority-low', } export function priorityLabel(p: number): string { return PRIORITY_LABELS[p] ?? `P${p}` } export function priorityClass(p: number): string { return PRIORITY_CLASSES[p] ?? 'priority-low' }