import type { RoleProgress } from './derive'; export type RiskLevel = 'low' | 'medium' | 'high'; export type DelayStatus = 'normal' | 'warning' | 'delayed'; const DELAY_WARNING_DAYS = 3; export function calcOverallProgress(progress?: RoleProgress[]): number { if (!progress || progress.length === 0) return 0; const sum = progress.reduce((s, p) => s + p.percent, 0); return Math.round(sum / progress.length); } export function calcDelayStatus( status: string, expectedReleaseDate?: string | null, ): DelayStatus { if (status === 'released' || status === 'closed') return 'normal'; if (!expectedReleaseDate) return 'normal'; const now = new Date(); now.setHours(0, 0, 0, 0); const deadline = new Date(expectedReleaseDate); deadline.setHours(0, 0, 0, 0); const diffDays = (deadline.getTime() - now.getTime()) / (1000 * 60 * 60 * 24); if (diffDays < 0) return 'delayed'; if (diffDays <= DELAY_WARNING_DAYS) return 'warning'; return 'normal'; } export function calcRiskLevel( status: string, startDate?: string | null, expectedReleaseDate?: string | null, progress?: RoleProgress[], ): RiskLevel { if (status === 'released' || status === 'closed') return 'low'; if (status === 'paused') return 'medium'; const delayStatus = calcDelayStatus(status, expectedReleaseDate); if (delayStatus === 'delayed') return 'high'; if (!startDate || !expectedReleaseDate) return 'low'; const now = new Date(); now.setHours(0, 0, 0, 0); const start = new Date(startDate); start.setHours(0, 0, 0, 0); const end = new Date(expectedReleaseDate); end.setHours(0, 0, 0, 0); const totalDuration = end.getTime() - start.getTime(); if (totalDuration <= 0) return 'low'; const elapsed = now.getTime() - start.getTime(); const timeProgress = Math.min(100, Math.max(0, (elapsed / totalDuration) * 100)); const actualProgress = calcOverallProgress(progress); const gap = timeProgress - actualProgress; if (gap >= 40) return 'high'; if (gap >= 20 || delayStatus === 'warning') return 'medium'; return 'low'; } export const RISK_LABEL: Record = { low: '低', medium: '中', high: '高', }; export const RISK_COLOR: Record = { low: 'text-emerald-600', medium: 'text-amber-600', high: 'text-red-600', }; export const RISK_DOT: Record = { low: 'bg-emerald-500', medium: 'bg-amber-500', high: 'bg-red-500', }; export const DELAY_LABEL: Record = { normal: '正常', warning: '即将延期', delayed: '已延期', }; export const DELAY_COLOR: Record = { normal: 'bg-emerald-50 text-emerald-700', warning: 'bg-amber-50 text-amber-700', delayed: 'bg-red-50 text-red-700', };