feat(projects): 工作台部分组件调成真实数据

This commit is contained in:
2026-06-04 11:26:51 +08:00
parent acef4418d8
commit 39458386ae
33 changed files with 1033 additions and 1169 deletions

View File

@@ -10,8 +10,6 @@ export type WorkbenchTodoDeadlineFilter = 'overdue' | 'today' | 'week' | null;
export type WorkbenchTodoPriority = 'high' | 'mid' | 'low';
export type WorkbenchProjectStatus = 'active' | 'preview' | 'paused';
export interface WorkbenchKpiSource {
/** 待办 */
todo: {
@@ -96,28 +94,17 @@ export interface WorkbenchActivityItem extends Omit<WorkbenchActivityItemSource,
tone: 'sky' | 'emerald' | 'amber' | 'rose' | 'violet';
}
export interface WorkbenchProjectItemSource {
/** 「我参与的项目」展示项(由 Api.Project.MyParticipatedProjectItem 衍生) */
export interface WorkbenchParticipatedProjectView {
id: string;
name: string;
code: string;
status: WorkbenchProjectStatus;
/** 我的角色 */
myRole: string;
/** 进度百分比 0-100 */
progress: number;
/** 我负责的任务数 */
myTaskCount: number;
/** 我负责的待处理任务数 */
myPendingTaskCount: number;
/** 最近活动时间ISO */
lastActiveTime: string;
}
export interface WorkbenchProjectItem extends Omit<WorkbenchProjectItemSource, 'lastActiveTime'> {
statusLabel: string;
code: string | null;
statusName: string | null;
statusTone: 'sky' | 'emerald' | 'amber';
myRole: string | null;
progress: number;
lastActiveLabel: string;
myTaskCount: number;
myPendingTaskCount: number;
}
const todoCategoryMeta: Record<
@@ -144,11 +131,12 @@ const activityToneMap: Record<WorkbenchActivityItemSource['targetKind'], Workben
product: 'rose'
};
const projectStatusMeta: Record<WorkbenchProjectStatus, { label: string; tone: WorkbenchProjectItem['statusTone'] }> = {
active: { label: '进行中', tone: 'emerald' },
preview: { label: '试运行', tone: 'sky' },
paused: { label: '已暂停', tone: 'amber' }
};
/** 列表只含进行中项目;按已知状态编码上色,未知回退 sky */
function resolveParticipatedProjectTone(statusCode: string): 'sky' | 'emerald' | 'amber' {
if (statusCode === 'active') return 'emerald';
if (statusCode === 'paused') return 'amber';
return 'sky';
}
function clampPercent(value: number) {
if (!Number.isFinite(value)) return 0;
@@ -325,61 +313,68 @@ export function buildWorkbenchActivityItems(source: readonly WorkbenchActivityIt
}));
}
export function buildWorkbenchProjectItems(source: readonly WorkbenchProjectItemSource[]): WorkbenchProjectItem[] {
return source.map(item => {
const meta = projectStatusMeta[item.status];
return {
...item,
statusLabel: meta.label,
statusTone: meta.tone,
progress: clampPercent(item.progress),
lastActiveLabel: formatRelative(item.lastActiveTime)
} satisfies WorkbenchProjectItem;
});
export function buildWorkbenchParticipatedProjects(
source: readonly Api.Project.MyParticipatedProjectItem[]
): WorkbenchParticipatedProjectView[] {
return source.map(item => ({
id: item.id,
name: item.name,
code: item.code,
statusName: item.statusName,
statusTone: resolveParticipatedProjectTone(item.statusCode),
myRole: item.myRole,
progress: clampPercent(item.progress),
myTaskCount: item.myTaskCount,
myPendingTaskCount: item.myPendingTaskCount
}));
}
export interface WorkbenchOwnedProjectMilestone {
id: string;
title: string;
timeLabel: string;
tone: 'amber' | 'slate';
/** 「我负责的项目」成员负载展示项 */
export interface WorkbenchOwnedProjectMemberView {
userId: string;
userName: string | null;
/** 该成员在本项目下进行中任务数 */
activeTaskCount: number;
}
export interface WorkbenchOwnedProjectMember {
name: string;
/** 负载 0-100百分比 */
load: number;
level: 'ok' | 'warn' | 'over';
}
export interface WorkbenchOwnedProjectItemSource {
/** 「我负责的项目」展示项(由 Api.Project.MyOwnedProjectItem 衍生) */
export interface WorkbenchOwnedProjectView {
id: string;
name: string;
code: string;
/** 进度 0-100 */
code: string | null;
progress: number;
myRole: string | null;
executionCount: number;
taskCount: number;
memberCount: number;
overdueCount: number;
/** 距离计划结束剩余天数(负数表示已逾期) */
remainingDays: number;
/** 我在该项目中的角色 */
myRole: string;
milestones: WorkbenchOwnedProjectMilestone[];
members: WorkbenchOwnedProjectMember[];
memberCount: number;
/** 计划结束日期 YYYY-MM-DD可空 */
plannedEndDate: string | null;
/** 距计划结束剩余天数(负=已逾期plannedEndDate 为空时 null */
remainingDays: number | null;
members: WorkbenchOwnedProjectMemberView[];
}
export interface WorkbenchOwnedProjectItem extends WorkbenchOwnedProjectItemSource {
progress: number;
}
export function buildWorkbenchOwnedProjectItems(
source: readonly WorkbenchOwnedProjectItemSource[]
): WorkbenchOwnedProjectItem[] {
export function buildWorkbenchOwnedProjects(
source: readonly Api.Project.MyOwnedProjectItem[]
): WorkbenchOwnedProjectView[] {
return source.map(item => ({
...item,
progress: clampPercent(item.progress)
id: item.id,
name: item.name,
code: item.code,
progress: clampPercent(item.progress),
myRole: item.myRole,
executionCount: item.executionCount,
taskCount: item.taskCount,
overdueCount: item.overdueCount,
memberCount: item.memberCount,
plannedEndDate: item.plannedEndDate,
remainingDays: getRemainingDays(item.plannedEndDate),
members: item.members.map(member => ({
userId: member.userId,
userName: member.userName,
activeTaskCount: member.activeTaskCount
}))
}));
}
@@ -759,38 +754,13 @@ export function buildWorkbenchProgressBars(source: readonly WorkbenchProgressBar
return source.map(s => ({ ...s, weekCompletionRate: Math.min(100, Math.max(0, Math.round(s.weekCompletionRate))) }));
}
export interface WorkbenchMyExecutionItemSource {
id: string;
executionName: string;
/** 关联项目 */
projectId: string;
projectName: string;
/** 执行状态编码projectExecution 域pending / active / paused / completed / cancelled */
statusCode: string;
/** 状态名(后端字典返回) */
statusName: string;
/** 优先级编码(取 RDMS_REQ_PRIORITY_DICT_CODE 字典) */
priority: string;
/** 计划起止 */
plannedStartDate: string | null;
plannedEndDate: string | null;
/** 实际起止 */
actualStartDate: string | null;
actualEndDate: string | null;
/** 进度0-100 整数) */
progressRate: number;
/** 关联项目需求 ID可选 */
projectRequirementId?: string;
/** 关联项目需求名称(可选) */
projectRequirementName?: string;
}
export type WorkbenchMyExecutionItem = WorkbenchMyExecutionItemSource;
/** 过滤掉已完成 / 已取消 / 进度满 100 的执行(默认不在工作台呈现) */
export function buildWorkbenchMyExecutionItems(
source: readonly WorkbenchMyExecutionItemSource[]
): WorkbenchMyExecutionItem[] {
/**
* 前端兜底过滤:剔除已完成 / 已取消 / 进度满 100 的执行(默认不在工作台呈现)。
* 后端接口已按此口径过滤,此处为双保险;泛型保证接口返回类型可复用。
*/
export function buildWorkbenchMyExecutionItems<T extends { statusCode: string; progressRate: number }>(
source: readonly T[]
): T[] {
return source.filter(item => {
if (item.statusCode === 'completed' || item.statusCode === 'cancelled') return false;
if (item.progressRate >= 100) return false;