Commit 253aec06bbf62ff5662e7099ba3e033994eebad9
1 parent
d0a60569
feat(fe-shell): 导航与主页 KPI 静态配置数据 REQ-USR-003
Showing
4 changed files
with
279 additions
and
0 deletions
frontend/src/layouts/AppLayout/navConfig.ts
0 → 100644
| 1 | +// REQ-USR-003: 导航静态配置(全量复刻原型 navSide / navCols,D1/D4)。 | ||
| 2 | +// 仅「用户列表」有真实路由;其余叶子无 routePath = 占位(点击提示「功能开发中」)。 | ||
| 3 | + | ||
| 4 | +export interface NavSideItem { | ||
| 5 | + key: string; | ||
| 6 | + label: string; | ||
| 7 | + active?: boolean; | ||
| 8 | +} | ||
| 9 | + | ||
| 10 | +export interface NavLeaf { | ||
| 11 | + label: string; | ||
| 12 | + routePath?: string; | ||
| 13 | + star?: boolean; | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +export interface NavCol { | ||
| 17 | + title: string; | ||
| 18 | + items: NavLeaf[]; | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +/** 左列 20 个一级模块(复刻原型 navSide;「系统设置」默认 active) */ | ||
| 22 | +export const NAV_SIDE: NavSideItem[] = [ | ||
| 23 | + { key: 'sales', label: '销售管理' }, | ||
| 24 | + { key: 'dcs', label: 'DCS系统' }, | ||
| 25 | + { key: 'prod', label: '产品管理' }, | ||
| 26 | + { key: 'ops', label: '生产运营' }, | ||
| 27 | + { key: 'exec', label: '生产执行' }, | ||
| 28 | + { key: 'mold', label: '模具管理' }, | ||
| 29 | + { key: 'cart', label: '采购管理' }, | ||
| 30 | + { key: 'mat', label: '材料库存' }, | ||
| 31 | + { key: 'fg', label: '成品库存' }, | ||
| 32 | + { key: 'out', label: '外协管理' }, | ||
| 33 | + { key: 'logi', label: '物流管理' }, | ||
| 34 | + { key: 'qa', label: '质量管理' }, | ||
| 35 | + { key: 'fin', label: '财务管理' }, | ||
| 36 | + { key: 'cost1', label: '成本管理(专)' }, | ||
| 37 | + { key: 'cost2', label: '成本管理' }, | ||
| 38 | + { key: 'eq', label: '设备管理' }, | ||
| 39 | + { key: 'hr', label: '人事行政' }, | ||
| 40 | + { key: 'oa', label: 'OA系统' }, | ||
| 41 | + { key: 'base', label: '基础设置' }, | ||
| 42 | + { key: 'sys', label: '系统设置', active: true }, | ||
| 43 | +]; | ||
| 44 | + | ||
| 45 | +/** 右侧 7 列分组(复刻原型 navCols;仅「用户列表」routePath,「用户列表」「系统功能模块设置」带 ★) */ | ||
| 46 | +export const NAV_COLS: NavCol[] = [ | ||
| 47 | + { | ||
| 48 | + title: '期初设置', | ||
| 49 | + items: [ | ||
| 50 | + { label: '客户期初' }, | ||
| 51 | + { label: '供应商期初' }, | ||
| 52 | + { label: '材料期初' }, | ||
| 53 | + { label: '产品期初' }, | ||
| 54 | + { label: '数据导入' }, | ||
| 55 | + { label: '离线导出下载' }, | ||
| 56 | + ], | ||
| 57 | + }, | ||
| 58 | + { | ||
| 59 | + title: '用户管理', | ||
| 60 | + items: [ | ||
| 61 | + { label: '用户列表', routePath: '/usr/users', star: true }, | ||
| 62 | + { label: '系统权限' }, | ||
| 63 | + { label: '系统权限稽查表' }, | ||
| 64 | + { label: '权限组' }, | ||
| 65 | + ], | ||
| 66 | + }, | ||
| 67 | + { | ||
| 68 | + title: '系统参数', | ||
| 69 | + items: [{ label: '系统参数' }, { label: '财务结账' }, { label: '系统常量配置' }], | ||
| 70 | + }, | ||
| 71 | + { | ||
| 72 | + title: '计算方案', | ||
| 73 | + items: [{ label: '方案列表' }, { label: '计算参数' }], | ||
| 74 | + }, | ||
| 75 | + { | ||
| 76 | + title: '日志', | ||
| 77 | + items: [ | ||
| 78 | + { label: '个性化模块' }, | ||
| 79 | + { label: '操作日志' }, | ||
| 80 | + { label: '异常清除KPI任务表' }, | ||
| 81 | + { label: 'MYSQL监听器' }, | ||
| 82 | + ], | ||
| 83 | + }, | ||
| 84 | + { | ||
| 85 | + title: '开发平台', | ||
| 86 | + items: [ | ||
| 87 | + { label: '自定义开发范例' }, | ||
| 88 | + { label: '系统功能模块设置', star: true }, | ||
| 89 | + { label: 'EBC流程清单' }, | ||
| 90 | + { label: '功能模块界面设置' }, | ||
| 91 | + { label: '增删改存业务处理' }, | ||
| 92 | + ], | ||
| 93 | + }, | ||
| 94 | + { | ||
| 95 | + title: 'API对接管理', | ||
| 96 | + items: [ | ||
| 97 | + { label: '调用第三方接口(TOKEN配置)' }, | ||
| 98 | + { label: '调用第三方接口(接口定义)' }, | ||
| 99 | + { label: '被第三方调用(生成token)' }, | ||
| 100 | + { label: '数据同步' }, | ||
| 101 | + { label: '被第三方调用(API定义)' }, | ||
| 102 | + ], | ||
| 103 | + }, | ||
| 104 | +]; |
frontend/src/pages/home/HomePage/dashboardData.ts
0 → 100644
| 1 | +// REQ-USR-003: 主页静态 demo 数据(全量复刻原型内联 kpiRows / 角色树,D1/D2)。 | ||
| 2 | +// 不取后端:KPI 看板、角色/流程树均为前端静态配置。 | ||
| 3 | + | ||
| 4 | +/** KPI 头条统计(复刻原型 .kpi-head) */ | ||
| 5 | +export const KPI_STATS = { todayPending: 37428, openTotal: 56433 } as const; | ||
| 6 | + | ||
| 7 | +export interface GroupItem { | ||
| 8 | + label: string; | ||
| 9 | + count: number; | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +/** 「按角色」分组(复刻原型左侧树第一段;「所有部门」为汇总条) */ | ||
| 13 | +export const ROLE_GROUPS: GroupItem[] = [ | ||
| 14 | + { label: '所有部门', count: 37428 }, | ||
| 15 | + { label: '核价人员', count: 17 }, | ||
| 16 | + { label: '销售人员', count: 0 }, | ||
| 17 | + { label: '印前', count: 11 }, | ||
| 18 | + { label: '客服部', count: 30127 }, | ||
| 19 | + { label: '技术研发部', count: 47 }, | ||
| 20 | + { label: '车间主管', count: 316 }, | ||
| 21 | + { label: '工艺部', count: 6 }, | ||
| 22 | + { label: '物控部', count: 728 }, | ||
| 23 | + { label: '生产计划部', count: 225 }, | ||
| 24 | + { label: '版房', count: 120 }, | ||
| 25 | + { label: '生产车间', count: 596 }, | ||
| 26 | + { label: '工艺技术部', count: 0 }, | ||
| 27 | + { label: '品质管理部', count: 589 }, | ||
| 28 | + { label: '储运部', count: 3496 }, | ||
| 29 | + { label: '通用', count: 0 }, | ||
| 30 | + { label: '外发组', count: 867 }, | ||
| 31 | + { label: '材料仓管', count: 0 }, | ||
| 32 | + { label: '机修组', count: 42 }, | ||
| 33 | + { label: '应收', count: 30 }, | ||
| 34 | + { label: '出纳', count: 211 }, | ||
| 35 | + { label: '应付', count: 0 }, | ||
| 36 | + { label: '客服', count: 0 }, | ||
| 37 | +]; | ||
| 38 | + | ||
| 39 | +/** 「按流程」分组(复刻原型左侧树第二段) */ | ||
| 40 | +export const PROCESS_GROUPS: GroupItem[] = [ | ||
| 41 | + { label: '估价管理流程', count: 17 }, | ||
| 42 | + { label: '设计制作流程', count: 11 }, | ||
| 43 | + { label: '新品研发流程', count: 11 }, | ||
| 44 | + { label: '材料测试流程', count: 51 }, | ||
| 45 | + { label: '订单下达流程', count: 30118 }, | ||
| 46 | +]; | ||
| 47 | + | ||
| 48 | +/** KPI 网格行(字段名与原型 kpiRows 一致,D2) */ | ||
| 49 | +export interface KpiRow { | ||
| 50 | + role: string | null; | ||
| 51 | + item: string; | ||
| 52 | + desc: string; | ||
| 53 | + today: string; | ||
| 54 | + total: string; | ||
| 55 | + sub?: string; | ||
| 56 | + red?: boolean; | ||
| 57 | + navTypeFirst?: boolean; | ||
| 58 | + roleSpan?: number; | ||
| 59 | + subSpan?: number; | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +/** KPI 网格 7 列表头(逐字复刻原型 kpiHeader) */ | ||
| 63 | +export const KPI_HEADERS = [ | ||
| 64 | + '导航类型', | ||
| 65 | + '角色', | ||
| 66 | + 'KPI待处理事项(当前行双击进入)', | ||
| 67 | + 'KPI内容描述及处理结果(点击蓝色查看明细)', | ||
| 68 | + '今日未处理', | ||
| 69 | + '未清总数', | ||
| 70 | + '子流程', | ||
| 71 | +] as const; | ||
| 72 | + | ||
| 73 | +/** 全量复刻原型 kpiRows(17 行) */ | ||
| 74 | +export const KPI_ROWS: KpiRow[] = [ | ||
| 75 | + // group 1: 估价管理流程 — 5 rows, 核价人员 span 4, 销售人员 1 | ||
| 76 | + { role: '核价人员', item: '01/04【新增】新报价单', desc: '报价单明细', today: '-', total: '-', sub: '估价管理流程', navTypeFirst: true, roleSpan: 4, subSpan: 5 }, | ||
| 77 | + { role: null, item: '02/04 审核后报价单->客户确认价格', desc: '报价单明细', today: '16', total: '16', red: true }, | ||
| 78 | + { role: null, item: '03/04 客户不认可->二次确认', desc: '报价单明细', today: '-', total: '-' }, | ||
| 79 | + { role: null, item: '04/04 报价单->销售订单', desc: '销售订单明细', today: '1', total: '1', red: true }, | ||
| 80 | + { role: '销售人员', item: '04/04 报价单->销售订单(标签)', desc: '销售订单明细(标签)', today: '0', total: '0', red: true }, | ||
| 81 | + // group 2: 设计制作流程 — 印前 (2 rows), span 2 | ||
| 82 | + { role: '印前', item: '1/2 新增设计申请单', desc: '设计申请明细', today: '-', total: '-', sub: '设计制作流程', roleSpan: 2, subSpan: 2 }, | ||
| 83 | + { role: null, item: '2/2 设计申请->设计制作', desc: '根据设计申请单进行设计制作,当日16:00前审核的为今日任务,16:00后(含)顺延至次日', today: '11', total: '11', red: true }, | ||
| 84 | + // group 3: 新品研发流程 | ||
| 85 | + { role: '客服部', item: '1/1 研发申请->文件制作', desc: '根据研发申请单,制作电子文件,当日16:00前下达的为今日任务,16:00后(含)顺延至次日', today: '0', total: '12', red: true, sub: '新品研发流程', subSpan: 5 }, | ||
| 86 | + { role: '客服部', item: '1/5 新增研发申请单', desc: '研发申请明细', today: '-', total: '-' }, | ||
| 87 | + { role: '技术研发部', item: '2/5 研发申请>>研发工单', desc: '及时开立研发工单,当日16:00前审核的为今日任务,16:00后(含)顺延至次日', today: '4', total: '4', red: true, roleSpan: 2 }, | ||
| 88 | + { role: null, item: '3/5 研发工单>>完工处理', desc: '计划人员在交货日期前确认工单完工', today: '7', total: '7', red: true }, | ||
| 89 | + { role: '客服部', item: '4/5 研发工单->客户确认', desc: '工单完工后需在7天内和客户确认样品', today: '-', total: '2703' }, | ||
| 90 | + { role: '技术研发部', item: '5/5 客户确认->工艺卡', desc: '根据客户已经确认的研发工单,生成产品工艺卡。当日16:00前确认的为今日任务,16:00后(含)顺延至次日', today: '0', total: '1632', red: true, sub: '', subSpan: 0 }, | ||
| 91 | + // group 4: 材料测试流程 | ||
| 92 | + { role: '车间主管', item: '1/3 工单(测试部门数)->车间反馈', desc: '车间主管在工单完工前对测试材料进行数据反馈', today: '10', total: '115', red: true, sub: '材料测试流程', subSpan: 3 }, | ||
| 93 | + { role: null, item: '2/3 车间反馈->车间补充(多部门)', desc: '补充新材料测试信息,车间反馈次日16:00前的为当日任务,16:00后(含)顺延一日', today: '8', total: '8', red: true, roleSpan: 2 }, | ||
| 94 | + { role: '技术研发部', item: '2/3 车间反馈->工程部反馈(单部门)', desc: '工程部对新材料的测试结果进行反馈,车间反馈次日16:00前的为当日任务,16:00后(含)顺延一日', today: '23', total: '23', red: true }, | ||
| 95 | +]; |
frontend/tests/unit/dashboardData.test.ts
0 → 100644
| 1 | +// REQ-USR-003: 主页静态 demo 数据(复刻原型 kpiRows / 角色树,D1/D2) | ||
| 2 | +import { describe, it, expect } from 'vitest'; | ||
| 3 | +import { | ||
| 4 | + KPI_STATS, | ||
| 5 | + KPI_ROWS, | ||
| 6 | + ROLE_GROUPS, | ||
| 7 | + PROCESS_GROUPS, | ||
| 8 | +} from '../../src/pages/home/HomePage/dashboardData'; | ||
| 9 | + | ||
| 10 | +describe('dashboardData', () => { | ||
| 11 | + it('KPI_STATS matches prototype head bar', () => { | ||
| 12 | + expect(KPI_STATS.todayPending).toBe(37428); | ||
| 13 | + expect(KPI_STATS.openTotal).toBe(56433); | ||
| 14 | + }); | ||
| 15 | + | ||
| 16 | + it('KPI_ROWS first row replicates prototype kpiRows field names', () => { | ||
| 17 | + const first = KPI_ROWS[0]; | ||
| 18 | + expect(first.role).toBe('核价人员'); | ||
| 19 | + expect(first.navTypeFirst).toBe(true); | ||
| 20 | + expect(first.roleSpan).toBe(4); | ||
| 21 | + expect(first.sub).toBe('估价管理流程'); | ||
| 22 | + expect(first.subSpan).toBe(5); | ||
| 23 | + expect(first.item).toBe('01/04【新增】新报价单'); | ||
| 24 | + }); | ||
| 25 | + | ||
| 26 | + it('ROLE_GROUPS includes 所有部门 37428 and 客服部 30127', () => { | ||
| 27 | + const all = ROLE_GROUPS.find((g) => g.label === '所有部门'); | ||
| 28 | + const kf = ROLE_GROUPS.find((g) => g.label === '客服部'); | ||
| 29 | + expect(all?.count).toBe(37428); | ||
| 30 | + expect(kf?.count).toBe(30127); | ||
| 31 | + }); | ||
| 32 | + | ||
| 33 | + it('PROCESS_GROUPS includes 估价管理流程 17 and 订单下达流程 30118', () => { | ||
| 34 | + const est = PROCESS_GROUPS.find((g) => g.label === '估价管理流程'); | ||
| 35 | + const ord = PROCESS_GROUPS.find((g) => g.label === '订单下达流程'); | ||
| 36 | + expect(est?.count).toBe(17); | ||
| 37 | + expect(ord?.count).toBe(30118); | ||
| 38 | + }); | ||
| 39 | +}); |
frontend/tests/unit/navConfig.test.ts
0 → 100644
| 1 | +// REQ-USR-003: 导航静态配置(复刻原型 navSide / navCols,D1/D4) | ||
| 2 | +import { describe, it, expect } from 'vitest'; | ||
| 3 | +import { NAV_SIDE, NAV_COLS } from '../../src/layouts/AppLayout/navConfig'; | ||
| 4 | + | ||
| 5 | +describe('navConfig', () => { | ||
| 6 | + it('NAV_SIDE has 20 items with 系统设置 active', () => { | ||
| 7 | + expect(NAV_SIDE).toHaveLength(20); | ||
| 8 | + const sys = NAV_SIDE.find((s) => s.label === '系统设置'); | ||
| 9 | + expect(sys).toBeDefined(); | ||
| 10 | + expect(sys!.active).toBe(true); | ||
| 11 | + // 仅「系统设置」一项 active | ||
| 12 | + expect(NAV_SIDE.filter((s) => s.active).length).toBe(1); | ||
| 13 | + }); | ||
| 14 | + | ||
| 15 | + it('NAV_COLS has 7 groups with exact titles', () => { | ||
| 16 | + expect(NAV_COLS).toHaveLength(7); | ||
| 17 | + expect(NAV_COLS.map((c) => c.title)).toEqual([ | ||
| 18 | + '期初设置', | ||
| 19 | + '用户管理', | ||
| 20 | + '系统参数', | ||
| 21 | + '计算方案', | ||
| 22 | + '日志', | ||
| 23 | + '开发平台', | ||
| 24 | + 'API对接管理', | ||
| 25 | + ]); | ||
| 26 | + }); | ||
| 27 | + | ||
| 28 | + it('用户列表 leaf has routePath /usr/users and star', () => { | ||
| 29 | + const userMgmt = NAV_COLS.find((c) => c.title === '用户管理')!; | ||
| 30 | + const userList = userMgmt.items.find((it) => it.label === '用户列表')!; | ||
| 31 | + expect(userList.routePath).toBe('/usr/users'); | ||
| 32 | + expect(userList.star).toBe(true); | ||
| 33 | + }); | ||
| 34 | + | ||
| 35 | + it('系统功能模块设置 leaf has star and no routePath (placeholder)', () => { | ||
| 36 | + const devCol = NAV_COLS.find((c) => c.title === '开发平台')!; | ||
| 37 | + const leaf = devCol.items.find((it) => it.label === '系统功能模块设置')!; | ||
| 38 | + expect(leaf.star).toBe(true); | ||
| 39 | + expect(leaf.routePath).toBeUndefined(); | ||
| 40 | + }); | ||
| 41 | +}); |