- 新增基础设施:useOSSUpload Hook、SSEContext Provider、taskStageMapper 工具 - 达人端4页面:任务列表/详情/脚本上传/视频上传对接真实 API - 代理商端3页面:工作台/审核队列/审核详情对接真实 API - 品牌方端4页面:项目列表/创建项目/项目详情/Brief配置对接真实 API - 保留 USE_MOCK 开关,mock 模式下使用类型安全的 mock 数据 - 所有页面添加 loading 骨架屏、SSE 实时更新、错误处理 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
187 lines
6.1 KiB
TypeScript
187 lines
6.1 KiB
TypeScript
import type { TaskResponse, TaskStage, TaskStatus } from '@/types/task'
|
|
|
|
export type StepStatus = 'pending' | 'current' | 'done' | 'error'
|
|
|
|
export interface StageSteps {
|
|
submit: StepStatus
|
|
ai: StepStatus
|
|
agency: StepStatus
|
|
brand: StepStatus
|
|
}
|
|
|
|
export interface TaskUIState {
|
|
scriptStage: StageSteps
|
|
videoStage: StageSteps
|
|
currentPhase: 'script' | 'video' | 'completed'
|
|
buttonText: string
|
|
buttonType: 'primary' | 'warning' | 'success' | 'disabled'
|
|
scriptColor: string
|
|
videoColor: string
|
|
statusLabel: string
|
|
filterCategory: 'pending' | 'reviewing' | 'rejected' | 'completed'
|
|
}
|
|
|
|
const STAGE_ORDER: TaskStage[] = [
|
|
'script_upload', 'script_ai_review', 'script_agency_review', 'script_brand_review',
|
|
'video_upload', 'video_ai_review', 'video_agency_review', 'video_brand_review',
|
|
'completed', 'rejected',
|
|
]
|
|
|
|
function statusToStep(status: TaskStatus | undefined | null): StepStatus {
|
|
if (!status || status === 'pending') return 'pending'
|
|
if (status === 'processing') return 'current'
|
|
if (status === 'passed' || status === 'force_passed') return 'done'
|
|
if (status === 'rejected') return 'error'
|
|
return 'pending'
|
|
}
|
|
|
|
export function mapTaskToUI(task: TaskResponse): TaskUIState {
|
|
const stage = task.stage
|
|
const stageIndex = STAGE_ORDER.indexOf(stage)
|
|
|
|
// 脚本阶段
|
|
const scriptStage: StageSteps = {
|
|
submit: stageIndex >= 0 ? 'done' : 'pending',
|
|
ai: 'pending',
|
|
agency: 'pending',
|
|
brand: 'pending',
|
|
}
|
|
|
|
// 视频阶段
|
|
const videoStage: StageSteps = {
|
|
submit: 'pending',
|
|
ai: 'pending',
|
|
agency: 'pending',
|
|
brand: 'pending',
|
|
}
|
|
|
|
// 根据 stage 设置进度
|
|
if (stage === 'script_upload') {
|
|
scriptStage.submit = 'current'
|
|
} else if (stage === 'script_ai_review') {
|
|
scriptStage.submit = 'done'
|
|
scriptStage.ai = task.script_ai_result ? 'done' : 'current'
|
|
} else if (stage === 'script_agency_review') {
|
|
scriptStage.submit = 'done'
|
|
scriptStage.ai = 'done'
|
|
scriptStage.agency = statusToStep(task.script_agency_status)
|
|
if (scriptStage.agency === 'pending') scriptStage.agency = 'current'
|
|
} else if (stage === 'script_brand_review') {
|
|
scriptStage.submit = 'done'
|
|
scriptStage.ai = 'done'
|
|
scriptStage.agency = 'done'
|
|
scriptStage.brand = statusToStep(task.script_brand_status)
|
|
if (scriptStage.brand === 'pending') scriptStage.brand = 'current'
|
|
} else if (stageIndex >= 4) {
|
|
// 已过脚本阶段
|
|
scriptStage.submit = 'done'
|
|
scriptStage.ai = 'done'
|
|
scriptStage.agency = 'done'
|
|
scriptStage.brand = 'done'
|
|
}
|
|
|
|
// 处理脚本被驳回的情况
|
|
if (task.script_agency_status === 'rejected') {
|
|
scriptStage.agency = 'error'
|
|
}
|
|
if (task.script_brand_status === 'rejected') {
|
|
scriptStage.brand = 'error'
|
|
}
|
|
|
|
// 视频阶段
|
|
if (stage === 'video_upload') {
|
|
videoStage.submit = 'current'
|
|
} else if (stage === 'video_ai_review') {
|
|
videoStage.submit = 'done'
|
|
videoStage.ai = task.video_ai_result ? 'done' : 'current'
|
|
} else if (stage === 'video_agency_review') {
|
|
videoStage.submit = 'done'
|
|
videoStage.ai = 'done'
|
|
videoStage.agency = statusToStep(task.video_agency_status)
|
|
if (videoStage.agency === 'pending') videoStage.agency = 'current'
|
|
} else if (stage === 'video_brand_review') {
|
|
videoStage.submit = 'done'
|
|
videoStage.ai = 'done'
|
|
videoStage.agency = 'done'
|
|
videoStage.brand = statusToStep(task.video_brand_status)
|
|
if (videoStage.brand === 'pending') videoStage.brand = 'current'
|
|
} else if (stage === 'completed') {
|
|
videoStage.submit = 'done'
|
|
videoStage.ai = 'done'
|
|
videoStage.agency = 'done'
|
|
videoStage.brand = 'done'
|
|
}
|
|
|
|
// 处理视频被驳回的情况
|
|
if (task.video_agency_status === 'rejected') {
|
|
videoStage.agency = 'error'
|
|
}
|
|
if (task.video_brand_status === 'rejected') {
|
|
videoStage.brand = 'error'
|
|
}
|
|
|
|
// 当前阶段
|
|
let currentPhase: 'script' | 'video' | 'completed' = 'script'
|
|
if (stageIndex >= 4 && stageIndex < 8) currentPhase = 'video'
|
|
if (stage === 'completed') currentPhase = 'completed'
|
|
|
|
// 按钮文案和类型
|
|
let buttonText = '查看详情'
|
|
let buttonType: 'primary' | 'warning' | 'success' | 'disabled' = 'primary'
|
|
|
|
if (stage === 'script_upload') {
|
|
buttonText = '上传脚本'
|
|
buttonType = 'primary'
|
|
} else if (stage === 'video_upload') {
|
|
buttonText = '上传视频'
|
|
buttonType = 'primary'
|
|
} else if (stage === 'completed') {
|
|
buttonText = '已完成'
|
|
buttonType = 'success'
|
|
} else if (stage === 'rejected') {
|
|
buttonText = '重新提交'
|
|
buttonType = 'warning'
|
|
} else if (stage.includes('review')) {
|
|
buttonText = '审核中'
|
|
buttonType = 'disabled'
|
|
}
|
|
|
|
// 颜色
|
|
const scriptColor = scriptStage.agency === 'error' || scriptStage.brand === 'error'
|
|
? 'red' : scriptStage.brand === 'done' ? 'green' : 'blue'
|
|
const videoColor = videoStage.agency === 'error' || videoStage.brand === 'error'
|
|
? 'red' : videoStage.brand === 'done' ? 'green' : 'blue'
|
|
|
|
// 状态标签
|
|
let statusLabel = '进行中'
|
|
if (stage === 'script_upload' || stage === 'video_upload') statusLabel = '待上传'
|
|
else if (stage.includes('ai_review')) statusLabel = 'AI 审核中'
|
|
else if (stage.includes('agency_review')) statusLabel = '代理商审核中'
|
|
else if (stage.includes('brand_review')) statusLabel = '品牌方审核中'
|
|
else if (stage === 'completed') statusLabel = '已完成'
|
|
else if (stage === 'rejected') statusLabel = '已驳回'
|
|
|
|
// 筛选分类
|
|
let filterCategory: 'pending' | 'reviewing' | 'rejected' | 'completed' = 'reviewing'
|
|
if (stage === 'script_upload' || stage === 'video_upload') filterCategory = 'pending'
|
|
else if (stage === 'completed') filterCategory = 'completed'
|
|
else if (stage === 'rejected') filterCategory = 'rejected'
|
|
// 处理驳回后重新提交的情况
|
|
if (task.script_agency_status === 'rejected' || task.script_brand_status === 'rejected' ||
|
|
task.video_agency_status === 'rejected' || task.video_brand_status === 'rejected') {
|
|
if (stage !== 'completed') filterCategory = 'rejected'
|
|
}
|
|
|
|
return {
|
|
scriptStage,
|
|
videoStage,
|
|
currentPhase,
|
|
buttonText,
|
|
buttonType,
|
|
scriptColor,
|
|
videoColor,
|
|
statusLabel,
|
|
filterCategory,
|
|
}
|
|
}
|