456 lines
15 KiB
TypeScript
456 lines
15 KiB
TypeScript
import dayjs from 'dayjs';
|
||
import type {
|
||
WorkbenchActivityItemSource,
|
||
WorkbenchKpiSource,
|
||
WorkbenchMyWeekWorklogSource,
|
||
WorkbenchProgressBarSource,
|
||
WorkbenchProjectHealthCardSource,
|
||
WorkbenchTeamLoadSource,
|
||
WorkbenchTeamWorklogSource,
|
||
WorkbenchTodoItemSource
|
||
} from './homepage';
|
||
|
||
const now = dayjs();
|
||
const iso = (date: dayjs.Dayjs) => date.format('YYYY-MM-DD HH:mm:ss');
|
||
|
||
export const workbenchKpiMock = {
|
||
todo: { count: 8, diffFromYesterday: 1 },
|
||
task: { count: 14, diffFromYesterday: -1 },
|
||
project: { count: 3, activeCount: 2 },
|
||
requirement: { count: 6, pendingReview: 2 }
|
||
} satisfies WorkbenchKpiSource;
|
||
|
||
export const workbenchTodoMock = [
|
||
{
|
||
id: 'todo-1',
|
||
category: 'task',
|
||
title: '支付回调接口联调遗留问题处理',
|
||
createdTime: iso(now.subtract(7, 'day').hour(9).minute(20)),
|
||
deadline: iso(now.subtract(1, 'day').hour(17).minute(30)),
|
||
source: '收银台 V3 · 后端联调',
|
||
priority: 'high',
|
||
overdue: true,
|
||
routeKey: 'project_list'
|
||
},
|
||
{
|
||
id: 'todo-2',
|
||
category: 'ticket',
|
||
title: '工单 #1018 用户登录异常',
|
||
createdTime: iso(now.subtract(6, 'day').hour(11).minute(0)),
|
||
deadline: iso(now.subtract(2, 'day').hour(10).minute(0)),
|
||
source: '客户支持 · 紧急',
|
||
priority: 'mid',
|
||
overdue: true,
|
||
routeKey: 'ticket'
|
||
},
|
||
{
|
||
id: 'todo-3',
|
||
category: 'approval',
|
||
title: '李四 · 第 21 周周报待审批',
|
||
createdTime: iso(now.subtract(2, 'day').hour(18).minute(20)),
|
||
deadline: null,
|
||
source: '周报 · 产品组',
|
||
priority: 'mid',
|
||
routeKey: 'workbench'
|
||
},
|
||
{
|
||
id: 'todo-4',
|
||
category: 'personal',
|
||
title: '提交昨日工时与本周计划',
|
||
createdTime: iso(now.subtract(4, 'day').hour(8).minute(30)),
|
||
deadline: iso(now.hour(18).minute(0)),
|
||
source: '个人事项 · 工时',
|
||
priority: 'mid',
|
||
routeKey: 'personal-center_my-item'
|
||
},
|
||
{
|
||
id: 'todo-5',
|
||
category: 'task',
|
||
title: '会员等级提示文案最终校对',
|
||
createdTime: iso(now.subtract(3, 'day').hour(10).minute(10)),
|
||
deadline: iso(now.hour(20).minute(0)),
|
||
source: '会员中心 · 文案',
|
||
priority: 'high',
|
||
routeKey: 'project_list'
|
||
},
|
||
{
|
||
id: 'todo-6',
|
||
category: 'ticket',
|
||
title: '工单 #1024 客户反馈待处理',
|
||
createdTime: iso(now.subtract(3, 'day').hour(15).minute(0)),
|
||
deadline: iso(now.add(2, 'day').hour(17).minute(0)),
|
||
source: '王五 · 客户反馈',
|
||
priority: 'mid',
|
||
routeKey: 'ticket'
|
||
},
|
||
{
|
||
id: 'todo-7',
|
||
category: 'personal',
|
||
title: '复盘上周交付遗留并归档',
|
||
createdTime: iso(now.subtract(2, 'day').hour(9).minute(0)),
|
||
deadline: iso(now.add(4, 'day').hour(18).minute(0)),
|
||
source: '个人事项 · 复盘',
|
||
priority: 'low',
|
||
routeKey: 'personal-center_my-item'
|
||
},
|
||
{
|
||
id: 'todo-8',
|
||
category: 'task',
|
||
title: '订单中心结算文档评审',
|
||
createdTime: iso(now.subtract(2, 'day').hour(13).minute(20)),
|
||
deadline: iso(now.add(5, 'day').hour(15).minute(0)),
|
||
source: '订单中心 · 文档',
|
||
priority: 'mid',
|
||
routeKey: 'project_list'
|
||
},
|
||
{
|
||
id: 'todo-9',
|
||
category: 'approval',
|
||
title: '张三 · 5 月加班 12h 申请待审批',
|
||
createdTime: iso(now.subtract(1, 'day').hour(17).minute(0)),
|
||
deadline: null,
|
||
source: '加班申请 · 研发组',
|
||
priority: 'mid',
|
||
routeKey: 'workbench'
|
||
},
|
||
{
|
||
id: 'todo-10',
|
||
category: 'personal',
|
||
title: '安排下周外出培训行程',
|
||
createdTime: iso(now.subtract(1, 'day').hour(19).minute(40)),
|
||
deadline: iso(now.add(10, 'day').hour(12).minute(0)),
|
||
source: '个人事项 · 行程',
|
||
priority: 'low',
|
||
routeKey: 'personal-center_my-item'
|
||
},
|
||
{
|
||
id: 'todo-11',
|
||
category: 'task',
|
||
title: '会员中心首页骨架屏改造',
|
||
createdTime: iso(now.subtract(20, 'hour')),
|
||
deadline: iso(now.add(12, 'day').hour(18).minute(0)),
|
||
source: '会员中心 · 前端',
|
||
priority: 'low',
|
||
routeKey: 'project_list'
|
||
},
|
||
{
|
||
id: 'todo-12',
|
||
category: 'ticket',
|
||
title: '工单 #1031 提示信息文案优化',
|
||
createdTime: iso(now.subtract(8, 'hour')),
|
||
deadline: iso(now.add(14, 'day').hour(17).minute(0)),
|
||
source: '客户支持 · 普通',
|
||
priority: 'low',
|
||
routeKey: 'ticket'
|
||
}
|
||
] satisfies WorkbenchTodoItemSource[];
|
||
|
||
export const workbenchActivityMock = [
|
||
{
|
||
id: 'act-1',
|
||
actor: '张三',
|
||
action: '提交了需求评审申请',
|
||
target: '订单导出 V2',
|
||
targetKind: 'requirement',
|
||
time: iso(now.subtract(10, 'minute'))
|
||
},
|
||
{
|
||
id: 'act-2',
|
||
actor: '李四',
|
||
action: '完成了任务',
|
||
target: '支付回调接口联调',
|
||
targetKind: 'task',
|
||
time: iso(now.subtract(2, 'hour'))
|
||
},
|
||
{
|
||
id: 'act-3',
|
||
actor: '李四',
|
||
action: '在需求中 @ 了你',
|
||
target: '会员等级',
|
||
targetKind: 'requirement',
|
||
time: iso(now.subtract(1, 'day').hour(17).minute(23)),
|
||
mentioned: true
|
||
},
|
||
{
|
||
id: 'act-4',
|
||
actor: '王五',
|
||
action: '提交了工单',
|
||
target: '#1024 · 客户反馈',
|
||
targetKind: 'ticket',
|
||
time: iso(now.subtract(1, 'day').hour(15).minute(8))
|
||
},
|
||
{
|
||
id: 'act-5',
|
||
actor: '赵六',
|
||
action: '把项目状态调整为',
|
||
target: '试运行(订单中心)',
|
||
targetKind: 'project',
|
||
time: iso(now.subtract(2, 'day').hour(10).minute(0))
|
||
},
|
||
{
|
||
id: 'act-6',
|
||
actor: '系统',
|
||
action: '提醒:你有 1 项任务即将逾期',
|
||
target: 'API 返回结构调整评审',
|
||
targetKind: 'requirement',
|
||
time: iso(now.subtract(3, 'day').hour(9).minute(30))
|
||
},
|
||
{
|
||
id: 'act-7',
|
||
actor: '钱七',
|
||
action: '更新了产品资料',
|
||
target: '收银台 V3 · 定位说明',
|
||
targetKind: 'product',
|
||
time: iso(now.subtract(4, 'day').hour(16).minute(45))
|
||
}
|
||
] satisfies WorkbenchActivityItemSource[];
|
||
|
||
const currentWeekStart = now.startOf('isoWeek').format('YYYY-MM-DD');
|
||
const previousWeekStart = now.subtract(1, 'week').startOf('isoWeek').format('YYYY-MM-DD');
|
||
|
||
export const workbenchMyWeekWorklogMock = {
|
||
current: {
|
||
weekStart: currentWeekStart,
|
||
weeklyFilledHours: 5,
|
||
dailyHours: [4, 7, 6, 8, 7.5],
|
||
target: 40,
|
||
distribution: [
|
||
{ key: 'prj-mall-v2', label: '商城 V2 升级', hours: 12.5, kind: 'project', projectId: 'prj-mall-v2' },
|
||
{ key: 'prj-risk', label: '风控引擎接入', hours: 8, kind: 'project', projectId: 'prj-risk' },
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 6, kind: 'project', projectId: 'prj-cashier' },
|
||
{ key: 'prj-order', label: '订单中心', hours: 5, kind: 'project', projectId: 'prj-order' },
|
||
{ key: 'prj-member', label: '会员中心', hours: 3, kind: 'project', projectId: 'prj-member' },
|
||
{ key: 'prj-marketing', label: '营销中台', hours: 2, kind: 'project', projectId: 'prj-marketing' },
|
||
{ key: 'personal', label: '个人事项', hours: 4, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 2, kind: 'other' }
|
||
]
|
||
},
|
||
previous: {
|
||
weekStart: previousWeekStart,
|
||
weeklyFilledHours: 0,
|
||
dailyHours: [8, 8, 7, 8, 7],
|
||
target: 40,
|
||
distribution: [
|
||
{ key: 'prj-mall-v2', label: '商城 V2 升级', hours: 15, kind: 'project', projectId: 'prj-mall-v2' },
|
||
{ key: 'prj-risk', label: '风控引擎接入', hours: 9, kind: 'project', projectId: 'prj-risk' },
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 7, kind: 'project', projectId: 'prj-cashier' },
|
||
{ key: 'personal', label: '个人事项', hours: 5, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 2, kind: 'other' }
|
||
]
|
||
}
|
||
} satisfies WorkbenchMyWeekWorklogSource;
|
||
|
||
// 团队工时口径约定:「团队 = 当前用户所在团队,含自己」。
|
||
// 后端 /workbench/team-worklog 接口返回的 members 必须包含当前用户自己——
|
||
// 这样没有下级的人(普通员工)切到「团队工时」tab 也至少有自己这一条数据,
|
||
// 不会出现空白态。约定 members[0] = 当前用户,UI 用「(我)」后缀标识。
|
||
export const workbenchTeamWorklogMock = {
|
||
current: {
|
||
weekStart: currentWeekStart,
|
||
expectedHoursPerMember: 40,
|
||
members: [
|
||
{
|
||
memberId: 'u-1',
|
||
memberName: '张三(我)',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 22, kind: 'project' },
|
||
{ key: 'prj-order', label: '订单中心', hours: 10, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 4, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 2, kind: 'other' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-2',
|
||
memberName: '李四',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 18, kind: 'project' },
|
||
{ key: 'prj-member', label: '会员中心', hours: 20, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 3, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 1, kind: 'other' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-3',
|
||
memberName: '王五',
|
||
items: [
|
||
{ key: 'prj-member', label: '会员中心', hours: 14, kind: 'project' },
|
||
{ key: 'prj-order', label: '订单中心', hours: 12, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 2, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 2, kind: 'other' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-4',
|
||
memberName: '赵六',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 24, kind: 'project' },
|
||
{ key: 'prj-order', label: '订单中心', hours: 18, kind: 'project' },
|
||
{ key: 'prj-member', label: '会员中心', hours: 4, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 2, kind: 'personal' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-5',
|
||
memberName: '钱七',
|
||
items: [
|
||
{ key: 'prj-order', label: '订单中心', hours: 14, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 6, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 5, kind: 'other' }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
previous: {
|
||
weekStart: previousWeekStart,
|
||
expectedHoursPerMember: 40,
|
||
members: [
|
||
{
|
||
memberId: 'u-1',
|
||
memberName: '张三(我)',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 26, kind: 'project' },
|
||
{ key: 'prj-order', label: '订单中心', hours: 8, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 3, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 3, kind: 'other' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-2',
|
||
memberName: '李四',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 15, kind: 'project' },
|
||
{ key: 'prj-member', label: '会员中心', hours: 22, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 4, kind: 'personal' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-3',
|
||
memberName: '王五',
|
||
items: [
|
||
{ key: 'prj-member', label: '会员中心', hours: 16, kind: 'project' },
|
||
{ key: 'prj-order', label: '订单中心', hours: 10, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 5, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 3, kind: 'other' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-4',
|
||
memberName: '赵六',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', hours: 20, kind: 'project' },
|
||
{ key: 'prj-order', label: '订单中心', hours: 16, kind: 'project' },
|
||
{ key: 'prj-member', label: '会员中心', hours: 6, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 3, kind: 'personal' }
|
||
]
|
||
},
|
||
{
|
||
memberId: 'u-5',
|
||
memberName: '钱七',
|
||
items: [
|
||
{ key: 'prj-order', label: '订单中心', hours: 16, kind: 'project' },
|
||
{ key: 'personal', label: '个人事项', hours: 4, kind: 'personal' },
|
||
{ key: 'other', label: '其他', hours: 4, kind: 'other' }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
} satisfies { current: WorkbenchTeamWorklogSource; previous: WorkbenchTeamWorklogSource };
|
||
|
||
// 项目 key 与 workbenchTeamWorklogMock 对齐,保证跨 widget 项目色一致
|
||
export const workbenchTeamLoadMock = {
|
||
weekStart: now.startOf('isoWeek').format('YYYY-MM-DD'),
|
||
members: [
|
||
// 高负载:进行中 7 或 临期+逾期 ≥ 2
|
||
{
|
||
memberId: 'u-1',
|
||
memberName: '张三',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', kind: 'project', count: 4 },
|
||
{ key: 'prj-order', label: '订单中心', kind: 'project', count: 2 },
|
||
{ key: 'personal', label: '个人事项', kind: 'personal', count: 1 }
|
||
],
|
||
dueSoon: 2,
|
||
overdue: 1
|
||
},
|
||
{
|
||
memberId: 'u-4',
|
||
memberName: '赵六',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', kind: 'project', count: 2 },
|
||
{ key: 'prj-order', label: '订单中心', kind: 'project', count: 2 },
|
||
{ key: 'prj-member', label: '会员中心', kind: 'project', count: 1 }
|
||
],
|
||
dueSoon: 1,
|
||
overdue: 2
|
||
},
|
||
// 中负载:进行中 ≥ 4 或 临期+逾期 ≥ 1
|
||
{
|
||
memberId: 'u-2',
|
||
memberName: '李四',
|
||
items: [
|
||
{ key: 'prj-cashier', label: '收银台 V3', kind: 'project', count: 2 },
|
||
{ key: 'prj-member', label: '会员中心', kind: 'project', count: 2 }
|
||
],
|
||
dueSoon: 1,
|
||
overdue: 0
|
||
},
|
||
{
|
||
memberId: 'u-3',
|
||
memberName: '王五',
|
||
items: [
|
||
{ key: 'prj-member', label: '会员中心', kind: 'project', count: 2 },
|
||
{ key: 'prj-order', label: '订单中心', kind: 'project', count: 1 }
|
||
],
|
||
dueSoon: 1,
|
||
overdue: 0
|
||
},
|
||
// 正常
|
||
{
|
||
memberId: 'u-5',
|
||
memberName: '钱七',
|
||
items: [
|
||
{ key: 'prj-order', label: '订单中心', kind: 'project', count: 1 },
|
||
{ key: 'personal', label: '个人事项', kind: 'personal', count: 1 }
|
||
],
|
||
dueSoon: 0,
|
||
overdue: 0
|
||
}
|
||
]
|
||
} satisfies WorkbenchTeamLoadSource;
|
||
|
||
export const workbenchProjectHealthMock = [
|
||
{
|
||
projectId: 'prj-1',
|
||
projectName: '收银台 V3',
|
||
code: 'CASHIER-V3',
|
||
health: 'yellow',
|
||
riskCount: 2,
|
||
overdueTasks: 3,
|
||
backlogRequirements: 2
|
||
},
|
||
{
|
||
projectId: 'prj-2',
|
||
projectName: '会员中心',
|
||
code: 'MEMBER',
|
||
health: 'green',
|
||
riskCount: 0,
|
||
overdueTasks: 0,
|
||
backlogRequirements: 1
|
||
},
|
||
{
|
||
projectId: 'prj-3',
|
||
projectName: '订单中心',
|
||
code: 'ORDER',
|
||
health: 'red',
|
||
riskCount: 4,
|
||
overdueTasks: 5,
|
||
backlogRequirements: 6
|
||
}
|
||
] satisfies WorkbenchProjectHealthCardSource[];
|
||
|
||
export const workbenchProgressChartMock = [
|
||
{ projectId: 'prj-1', projectName: '收银台 V3', weekCompletionRate: 78 },
|
||
{ projectId: 'prj-2', projectName: '会员中心', weekCompletionRate: 62 },
|
||
{ projectId: 'prj-3', projectName: '订单中心', weekCompletionRate: 45 }
|
||
] satisfies WorkbenchProgressBarSource[];
|