diff --git a/apps/web/app/versions/[id]/page.tsx b/apps/web/app/versions/[id]/page.tsx index bf09f4f..0a26db7 100644 --- a/apps/web/app/versions/[id]/page.tsx +++ b/apps/web/app/versions/[id]/page.tsx @@ -393,15 +393,24 @@ export default function VersionDetailPage() { // 调研阶段 const researchPlans = versionPlans.filter((p) => p.type === 'research'); - const researchCal = calcCalendar(researchPlans.map((p) => p.startTime), researchPlans.filter((p) => p.status === 'completed').map((p) => p.endTime)); + const researchCal = calcCalendar( + researchPlans.filter((p) => p.actualStartAt).map((p) => p.actualStartAt!), + researchPlans.filter((p) => p.completedAt).map((p) => p.completedAt!), + ); // 产品方案阶段 const productPlans = versionPlans.filter((p) => p.type === 'product'); - const productCal = calcCalendar(productPlans.map((p) => p.startTime), productPlans.filter((p) => p.status === 'completed').map((p) => p.endTime)); + const productCal = calcCalendar( + productPlans.filter((p) => p.actualStartAt).map((p) => p.actualStartAt!), + productPlans.filter((p) => p.completedAt).map((p) => p.completedAt!), + ); // UI设计阶段 const uiPlans = versionPlans.filter((p) => p.type === 'ui'); - const uiCal = calcCalendar(uiPlans.map((p) => p.startTime), uiPlans.filter((p) => p.status === 'completed').map((p) => p.endTime)); + const uiCal = calcCalendar( + uiPlans.filter((p) => p.actualStartAt).map((p) => p.actualStartAt!), + uiPlans.filter((p) => p.completedAt).map((p) => p.completedAt!), + ); // 开发阶段 const devCal = calcCalendar( @@ -434,9 +443,8 @@ export default function VersionDetailPage() { // 调研/产品/UI 用 startTime→endTime 计算 versionPlans.forEach((p) => { - if (!p.owner || !p.startTime) return; - const end = p.status === 'completed' ? p.endTime : undefined; - const hours = calcActualHoursByDates(p.startTime.slice(0, 10), end?.slice(0, 10)); + if (!p.owner || !p.actualStartAt) return; + const hours = calcActualHoursByDates(p.actualStartAt, p.completedAt); addHours(p.owner, p.type === 'research' ? 'research' : p.type === 'product' ? 'product' : 'ui', hours); }); versionDevTasks.forEach((t) => { diff --git a/apps/web/lib/version-plan.ts b/apps/web/lib/version-plan.ts index d18dea3..b64b809 100644 --- a/apps/web/lib/version-plan.ts +++ b/apps/web/lib/version-plan.ts @@ -24,6 +24,7 @@ export interface VersionPlan { resultFileData?: string; remark?: string; overdueReason?: string; + actualStartAt?: string; createdAt: string; completedAt?: string; addedBy: string; diff --git a/apps/web/stores/useVersionPlanStore.ts b/apps/web/stores/useVersionPlanStore.ts index 2f757c7..891b26a 100644 --- a/apps/web/stores/useVersionPlanStore.ts +++ b/apps/web/stores/useVersionPlanStore.ts @@ -43,7 +43,18 @@ export const useVersionPlanStore = create((set, get) => ({ }, updatePlan: (id, data) => { - const plans = get().plans.map((p) => p.id === id ? { ...p, ...data } : p); + const now = new Date().toISOString(); + const plans = get().plans.map((p) => { + if (p.id !== id) return p; + const patch = { ...data }; + if (patch.status === 'in_progress' && !p.actualStartAt) { + (patch as any).actualStartAt = now; + } + if (patch.status === 'completed' && !p.completedAt) { + (patch as any).completedAt = now; + } + return { ...p, ...patch }; + }); set({ plans }); saveLocal(plans); },