Compare commits

...

112 Commits

Author SHA1 Message Date
sheng
e60c004b3c feat: 新增多模块功能并完善功能清单
Some checks are pending
Release pipeline / publish (push) Waiting to run
Release pipeline / Always run job (push) Waiting to run
1. 新增BOM物料清单、班组管理、班次管理、排班日历、监控设置页面及对应路由
2. 新增相关业务API接口
3. 完善多语言国际化配置
4. 更新功能迁移状态清单,完成所有功能迁移
5. 新增各模块测试用例文档
2026-06-23 10:39:42 +08:00
sheng
8ef94ecf2e 迁移排班日历功能
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 23:39:45 +08:00
sheng
e8e79fcb3f 迁移班次管理功能 2026-06-22 23:32:58 +08:00
sheng
c670488c80 迁移班组管理功能 2026-06-22 23:23:06 +08:00
sheng
cf90981c5d 迁移BOM物料清单功能 2026-06-22 23:10:00 +08:00
sheng
964cf0b6ad 迁移监控设置功能 2026-06-22 23:00:27 +08:00
sheng
8ee13f322f Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 22:46:57 +08:00
sheng
7cf7caf31f 新增工艺流程参数与补偿配置
Some checks failed
Release pipeline / Always run job (push) Has been cancelled
Release pipeline / publish (push) Has been cancelled
2026-06-22 22:44:45 +08:00
sheng
795d4d3b58 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 19:49:35 +08:00
sheng
c1e8626289 迁移质量管理UChart报表
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 19:33:09 +08:00
sheng
dcc706308b 迁移质量管理CChart报表 2026-06-22 19:32:47 +08:00
sheng
f40ff30943 迁移质量管理NPChart报表 2026-06-22 19:32:25 +08:00
sheng
5d1fbcc508 迁移质量管理PChart报表 2026-06-22 19:32:03 +08:00
sheng
5a4001ddf7 迁移质量管理DPMO报表 2026-06-22 19:31:42 +08:00
sheng
9af7dbf668 迁移质量管理CPK报表 2026-06-22 19:31:20 +08:00
sheng
d984ea6107 迁移质量管理MAMS报表 2026-06-22 19:30:58 +08:00
sheng
f817714c56 迁移质量管理MAMR报表 2026-06-22 19:30:36 +08:00
sheng
f625f3063d 迁移质量管理MA报表 2026-06-22 19:30:15 +08:00
sheng
9c54df9600 迁移质量管理CUSUM报表 2026-06-22 19:29:53 +08:00
sheng
7c48d0b7c7 迁移质量管理EWMA报表 2026-06-22 19:29:32 +08:00
sheng
ffead080ad 迁移质量管理Levey-Jennings报表 2026-06-22 19:29:10 +08:00
sheng
2739415e35 迁移质量管理I-MR报表 2026-06-22 19:28:49 +08:00
sheng
54ba033db6 迁移质量管理XBar-S报表 2026-06-22 19:28:28 +08:00
sheng
9f349d325a 迁移质量管理XBar-R报表 2026-06-22 19:28:05 +08:00
sheng
cc7e06fdb1 迁移质量管理SPC渲染条件配置 2026-06-22 19:27:43 +08:00
sheng
15105bc5c7 迁移质量管理抽样方案配置 2026-06-22 19:27:19 +08:00
sheng
a9c88eb264 迁移质量管理检验项目 2026-06-22 19:26:52 +08:00
sheng
7125bc4884 迁移质量管理检测方案维护 2026-06-22 19:26:29 +08:00
sheng
19f8f18f85 迁移质量管理接收质量限 2026-06-22 19:26:07 +08:00
sheng
9675227702 迁移质量管理检验标准 2026-06-22 19:25:45 +08:00
sheng
e1111fe6df 迁移质量管理检验单管理 2026-06-22 19:25:23 +08:00
sheng
e9faea739a 迁移质量管理首巡检报表 2026-06-22 19:25:01 +08:00
sheng
be119060f0 迁移质量管理首巡检录入 2026-06-22 19:24:39 +08:00
sheng
1e2945d4a3 迁移质量管理首巡检项目配置 2026-06-22 19:24:18 +08:00
sheng
bf493321cb 迁移质量管理检验类别管理 2026-06-22 19:23:56 +08:00
sheng
92de685b9d Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 19:04:37 +08:00
sheng
2690204ec5 按组件规范重构设备模型页面
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 19:03:44 +08:00
sheng
700da7c42a Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 18:47:03 +08:00
sheng
8eaa5f90ca 修正设备维修日志迁移状态
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 18:26:25 +08:00
sheng
25bd394f96 迁移设备损耗品更换日志模块 2026-06-22 18:25:25 +08:00
sheng
80ef16f3e5 迁移设备损耗品寿命管理模块 2026-06-22 18:25:04 +08:00
sheng
86313d309f 迁移设备损耗品项目模块 2026-06-22 18:24:42 +08:00
sheng
6a664277a5 迁移设备损耗品类别模块 2026-06-22 18:24:21 +08:00
sheng
19050966b4 迁移设备维修日志模块 2026-06-22 18:24:00 +08:00
sheng
c58525b284 迁移设备维修管理模块 2026-06-22 18:23:39 +08:00
sheng
bf1365c1ea 迁移设备保养日志模块 2026-06-22 18:20:51 +08:00
sheng
8d1be42ce2 迁移设备保养详情模块 2026-06-22 18:19:57 +08:00
sheng
0740f82083 迁移设备保养项目模块 2026-06-22 18:19:35 +08:00
sheng
4714bbabc5 迁移设备点检日志模块 2026-06-22 18:19:14 +08:00
sheng
8e5127ea88 迁移设备点检记录模块 2026-06-22 18:18:52 +08:00
sheng
f2ffac4a06 迁移设备点检项目模块 2026-06-22 18:16:26 +08:00
sheng
41bbe3bf62 迁移设备信息模块 2026-06-22 18:12:51 +08:00
sheng
3412ae93a3 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 17:55:56 +08:00
sheng
6bb98edca5 chore(package): 更新node版本和js-cookie依赖
将node引擎要求调整为>=20.19.0,升级js-cookie到3.0.7版本,同步更新volta配置的node版本
2026-06-22 17:55:50 +08:00
sheng
c07f95a45e 迁移鹰眼模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 17:51:29 +08:00
sheng
973c780bf6 迁移电池详情报表模块 2026-06-22 17:44:16 +08:00
sheng
6768eb9ead 迁移设备履历报表模块 2026-06-22 17:40:40 +08:00
sheng
a1716b0069 迁移电池追溯模块 2026-06-22 17:36:22 +08:00
sheng
15526ca6e4 迁移托盘追溯模块 2026-06-22 17:32:32 +08:00
sheng
d582f9779a Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 17:30:56 +08:00
sheng
2bd0e49bb6 fix: 修复依赖版本和接口路径错误
1. 将sass版本从^1.54.5改为固定1.54.5并更新lock文件
2. 修正团队管理页面的用户接口导入路径
2026-06-22 17:30:53 +08:00
sheng
264474eced 迁移电池曲线模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 17:29:23 +08:00
sheng
0c6c4dc93c Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 17:24:20 +08:00
sheng
fe45390997 迁移正向追溯模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 17:22:00 +08:00
sheng
a1e79dcdcf Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 17:00:18 +08:00
sheng
3c4a665dc3 修复反向追溯图谱迁移问题
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-22 16:57:37 +08:00
sheng
94fcb85e5b Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 16:35:23 +08:00
sheng
7987d9a085 迁移反向追溯模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- 新增数据中台反向追溯 V2 页面

- 新增反向追溯查询导出接口、旧路径路由和中英文文案

- 更新迁移任务列表并补充人工功能测试清单
2026-06-22 16:33:18 +08:00
sheng
5fa4043c69 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 16:27:16 +08:00
sheng
e3fd31e33d 迁移电池复投管理模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- 新增计划与生产电池复投管理 V2 页面

- 新增复投验证接口、旧路径路由和中英文文案

- 更新迁移任务列表并补充人工功能测试清单
2026-06-22 16:26:05 +08:00
sheng
d7aee0f93a Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 16:17:23 +08:00
sheng
9863bf1113 迁移物料监控模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- 新增计划与生产物料监控 V2 页面

- 新增 WIP 物料监控接口、旧路径路由和中英文文案

- 更新迁移任务列表中的物料监控状态
2026-06-22 16:12:59 +08:00
sheng
cffbe39e99 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 16:08:08 +08:00
sheng
6bb2d1285c 迁移托盘登录模块
Some checks failed
Release pipeline / Always run job (push) Has been cancelled
Release pipeline / publish (push) Has been cancelled
- 新增计划与生产托盘登录 V2 页面

- 新增托盘登录接口、旧路径路由和中英文文案

- 更新迁移任务列表中的托盘登录状态
2026-06-22 16:01:21 +08:00
sheng
37daca561d Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 15:51:53 +08:00
sheng
eb31da72e0 迁移设备监控模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- 新增计划与生产设备监控 V2 页面

- 新增设备监控接口、路由和中英文文案

- 更新迁移任务列表中的设备监控状态
2026-06-22 15:50:19 +08:00
sheng
d66a934f06 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 15:29:58 +08:00
sheng
b942d24f2c 迁移预警中心模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- 新增计划与生产预警中心 V2 页面

- 新增预警中心接口、路由和中英文文案

- 更新迁移任务列表中的预警中心状态
2026-06-22 15:24:59 +08:00
sheng
12abbd51a8 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 15:10:23 +08:00
sheng
8ef087676f feat: migrate process execution module
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- add V2 process execution page for planning production monitoring

- add process execution API, route, and i18n entries

- update migration task list status for process execution
2026-06-22 15:07:38 +08:00
sheng
ed087a1c83 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 15:00:05 +08:00
sheng
45c2ea6e63 feat: migrate tray management module
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- add V2 tray management page for planning production monitoring

- add tray management API, route, and i18n entries

- update migration task list status for tray management
2026-06-22 14:58:04 +08:00
sheng
05c98e30c0 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-22 14:27:28 +08:00
sheng
248557a293 feat(production-master-data): 新增班组管理功能模块
1. 新增班组管理路由配置,添加对应页面访问路径
2. 新建班组管理API接口文件,封装增删改查、导入导出等接口
3. 补充中英文多语言文案,适配页面所有交互文本
4. 新增班组管理页面组件,包含搜索、列表、新增/编辑、成员管理、导入导出全功能
5. 更新功能测试文档,补充35条班组管理测试用例并更新用例统计
6. 更新系统功能清单对照表,新增班组管理模块条目
2026-06-22 14:27:18 +08:00
sheng
b44e031e74 feat: migrate planning batch management modules
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- migrate batch list, tray tracking, and batch defect report pages to V2

- add planning production APIs, workerman helper, routes, and i18n entries

- add markdown migration task list generated from the Webman function matrix
2026-06-22 14:13:01 +08:00
sheng
3f546564cc feat(production-master-data): 新增工艺流程管理完整模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
- 添加工艺流程、流程卡工序的全套CRUD及复制接口
- 新增工艺流程列表页与流程卡详情页的路由和页面组件
- 补充产品、工序分类、工序子类的全量查询接口
- 优化弹窗表单组件,支持字段禁用与focus/blur/change事件回调
- 修复工序单元页面的国际化调用和权限配置问题
- 补充中英文多语言国际化文案
- 新增该模块的功能测试文档
2026-06-04 17:07:15 +08:00
b6c362d906 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
2026-06-02 16:00:24 +08:00
76b480ece5 feat(production-master-data): add SPC采集配置功能
实现SPC数据采集配置页面,包含路由配置、API接口、多语言文案以及完整的增删改查功能,附带功能测试文档
2026-06-02 15:59:58 +08:00
sheng
76f9657fe9 style: 调整函数声明的空格格式,统一代码风格
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
对所有函数声明添加前后空格,保持代码排版一致性,提升可读性
2026-06-02 15:17:51 +08:00
e0d2c7c886 fix(pnpm): 修复@achrinza/node-ipc的安全版本问题
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
通过pnpm overrides将@achrinza/node-ipc强制升级到>=9.2.7版本,更新lockfile中的依赖版本记录。
2026-06-02 15:10:45 +08:00
sheng
df11ca0db6 docs: 更新项目环境搭建文档并添加volta配置
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
1. 补充Windows下Volta安装后的生效方式说明
2. 完善不同环境下Node版本安装指引
3. 新增volta命令无法识别的问题排查方案
4. 在package.json中添加volta的node版本配置
2026-06-02 14:42:33 +08:00
sheng
8b587163df chore: 配置项目开发环境并重构接口路由前缀
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
1.  添加 .node-version 和 .npmrc 配置文件,使用 Volta 锁定 Node.js 18.16.0 版本,强制使用 pnpm 作为包管理器
2.  更新 package.json,添加 packageManager 和 engines 字段限制依赖安装版本,替换 npm 脚本为 pnpm
3.  重构设备管理模块的接口 BASE 路径和路由路径,统一命名为 device_model/device_category
4.  完善 README.md,新增环境要求、安装启动流程、常用命令和目录结构说明
2026-06-02 14:26:17 +08:00
sheng
f1e73f3319 Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2 2026-06-02 14:05:32 +08:00
sheng
ddc715e17c feat(production-master-data): add 异常不良管理功能
1. 新增设备类别API接口封装
2. 新增异常不良管理的CRUD、导入导出API
3. 添加异常不良管理页面路由与多语言配置
4. 新增文件工具类支持Excel读写下载
5. 实现完整的异常不良管理页面与导入弹窗
6. 新增功能测试流程文档
7. 安装xlsx依赖支持Excel操作
2026-06-02 14:05:15 +08:00
hui
87edf1c76f Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2
Some checks failed
Release pipeline / Always run job (push) Has been cancelled
Release pipeline / publish (push) Has been cancelled
2026-06-02 13:56:00 +08:00
hui
9100f65325 feat(设备类别管理功能模块): 2026-06-02 13:54:55 +08:00
sheng
a0192d9567 feat(production-master-data): 新增生产主数据模块下物料与工序相关功能
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
1. 新增物料单位、物料类别、物料信息管理的API与页面
2. 新增工序单元管理的API、页面与弹窗组件
3. 新增可选参数管理组件与相关API
4. 补充对应国际化多语言配置
5. 新增生产主数据模块路由配置
6. 新增计量单位功能测试流程文档
2026-06-02 11:25:26 +08:00
sheng
99b9bc8a5b feat(production-master-data): 新增产线、工艺流程类别、产品管理模块
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
1. 新增工厂区域全量查询API
2. 新增产线管理API、页面、路由与多语言配置
3. 新增工艺流程类别管理API、页面、路由与多语言配置
4. 新增产品管理API、页面、路由与多语言配置
5. 修复MenuTree组件slot-scope语法兼容问题
6. 追加对应功能的测试文档与版本记录
2026-06-01 17:35:20 +08:00
sheng
c9498c444b fix(api): 完善401错误处理逻辑
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
统一处理登录态过期场景,清除token并跳转登录页
2026-06-01 11:02:59 +08:00
sheng
20a821ba32 feat: 完成系统管理模块功能迭代
新增用户、菜单、日志、问题帮助等业务模块,优化角色权限分配功能,新增依赖包与全局组件
2026-05-29 18:12:54 +08:00
sheng
a61036e5dc feat: 新增角色管理模块,优化API与交互体验
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
1.  新增角色管理后台页面、路由与国际化文案
2.  重构API请求错误处理逻辑,统一拦截业务与HTTP错误
3.  新增确认弹窗组合式函数,区分取消与请求错误场景
4.  完善表格按钮权限与显示控制逻辑
5.  更新API参数规范与文档说明
6.  修复部分页面分页数据解析问题
2026-05-28 19:16:05 +08:00
sheng
ba43de8f4b chore: remove unused traditional Chinese and Japanese locale files
删除了不再使用的繁体中文和日语语言本地化文件,清理冗余的国际化资源。
2026-05-28 16:19:23 +08:00
sheng
96fe85b3be docs: 更新文档并新增业务模块路由配置
1. 重命名README中的文档链接为中文名称
2. 新增数据中台、质量管理、系统设置、设备管理、计划与生产5个业务路由模块
3. 新增CRUD页面迁移、Sass废弃修复、布局组件迁移、国际化规范、登录页面搬迁、变更日志等文档
2026-05-28 16:15:57 +08:00
sheng
3149ffb932 feat: 新增模块首页、国际化适配与菜单重载功能
1. 为菜单数据新增remark字段并设置默认值
2. 全量替换硬编码文本为国际化多语言支持
3. 新增生产配置模块首页组件与路由
4. 新增菜单重载action,支持语言切换后重载菜单
5. 补充简体中文、英文、日文、繁体中文语言包
2026-05-28 15:47:19 +08:00
sheng
05bfa95bfe feat(d2-icon): add custom icon font library
新增了自定义图标字体库,包含多个业务场景图标,并在d2-icon组件中引入该图标库样式文件
2026-05-28 15:45:04 +08:00
sheng
4539bec3a4 refactor(page-table, page-dialog-form): 实现国际化自动响应,移除提前翻译逻辑
1. 为page-table和page-dialog-form添加内部$t翻译逻辑,支持语言切换自动更新
2. 移除data()中提前翻译的k()辅助函数,改为直接传入i18n key
3. 更新文档说明最新的i18n使用规范,新增迁移指南文档
4. 修复工厂区域页面的国际化调用方式,统一使用this.key()传参
2026-05-28 11:30:08 +08:00
sheng
48cfebd008 refactor: 移除组件内置i18n翻译,改为调用方自行处理
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
1. 调整菜单路由路径与API基础路径匹配生产配置更名
2. 优化page-table和page-dialog-form组件,移除内置的$t翻译逻辑,由调用方传入已翻译的文本
3. 为无menu_id的菜单项生成默认空路径
2026-05-27 18:37:37 +08:00
sheng
2cc8329695 refactor: remove old demo pages and static menu logic
1. 删除大量旧的示例页面、组件示例和静态菜单配置
2. 新增菜单扁平数组转树形结构工具函数
3. 重构菜单加载逻辑,改为从后端动态获取并格式化
4. 新增全局权限检查方法和自定义权限指令
5. 优化侧边栏菜单路由跳转逻辑,自动跳转第一个有权限的子页面
6. 移除路由中对旧demo模块的引用
2026-05-27 18:07:48 +08:00
sheng
0f3b5d4371 refactor(login): 重构登录页面,适配国际化并简化功能
1.  将页面文本替换为国际化翻译
2.  移除验证码、快速登录等冗余功能
3.  更新logo资源路径与表单校验逻辑
4.  优化页面样式与代码结构
2026-05-27 16:42:19 +08:00
sheng
000b87eb92 feat: 新增登录注销功能,调整接口与配置
1.  新增项目logo文件
2.  调整API基础地址与开发代理配置
3.  添加多语言登录相关文案
4.  新增登录注销API接口
5.  重构请求与账号登录注销逻辑
6.  更新文档与菜单store状态
2026-05-27 16:42:03 +08:00
sheng
8a4511dc36 docs: add i18n spec and login migration docs, fix router trailing char
1. 新增国际化规范文档 `i18n-rules.md`,详细说明项目国际化的规范、key 命名、使用方式等
2. 新增登录页面搬迁文档 `login-page-migration.md`,记录登录页搬迁的步骤、依赖和验证清单
3. 修复生产主数据路由文件中多余的尾随字符
2026-05-27 14:38:53 +08:00
sheng
3eaea3116d feat: 新增工厂区域管理页面,修复Sass废弃警告
Some checks failed
Release pipeline / publish (push) Has been cancelled
Release pipeline / Always run job (push) Has been cancelled
1. 新增生产配置-工厂模型-工厂区域完整CRUD页面
2. 新增通用表格、弹窗表单、i18n工具组件
3. 升级sass-loader并修复Sass废弃警告
4. 添加文档记录Sass迁移修复细节
2026-05-26 18:32:57 +08:00
361 changed files with 72964 additions and 45645 deletions

2
.env
View File

@@ -4,7 +4,7 @@
VUE_APP_TITLE=D2Admin VUE_APP_TITLE=D2Admin
# 网络请求公用地址 # 网络请求公用地址
VUE_APP_API=/api/ VUE_APP_API=/background/v1/
# 仓库地址 # 仓库地址
VUE_APP_REPO=https://github.com/d2-projects/d2-admin VUE_APP_REPO=https://github.com/d2-projects/d2-admin

View File

@@ -2,3 +2,6 @@
# 页面 title 前缀 # 页面 title 前缀
VUE_APP_TITLE=D2Admin Dev VUE_APP_TITLE=D2Admin Dev
# 后台接口地址(代理目标)
VUE_APP_BASE_URL=http://127.0.0.1:8787/background/

1
.node-version Normal file
View File

@@ -0,0 +1 @@
18.16.0

8
.npmrc Normal file
View File

@@ -0,0 +1,8 @@
# pnpm 配置
# 强制通过 pnpm 安装,禁止使用 npm / yarn
engine-strict=true
# 使用 lockfile 锁定依赖版本
lockfile=true
# 依赖提升模式(兼容旧项目)
shamefully-hoist=true
# 允许在 package.json 中通过 packageManager 字段指定包管理器版本

493
README.md
View File

@@ -1,192 +1,357 @@
![banner](https://raw.githubusercontent.com/d2-projects/d2-admin/master/docs/image/banner.png) # MES-UI
<p align="center"> 基于 [D2 Admin](https://github.com/d2-projects/d2-admin)Vue 2.7 + Element UI的企业级 MES 中后台前端项目。
<a href="https://github.com/d2-projects/d2-admin/stargazers" target="_blank"><img src="https://img.shields.io/github/stars/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/network/members" target="_blank"><img src="https://img.shields.io/github/forks/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/issues" target="_blank"><img src="https://img.shields.io/github/issues/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/issues?q=is%3Aissue+is%3Aclosed" target="_blank"><img src="https://img.shields.io/github/issues-closed/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/pulls" target="_blank"><img src="https://img.shields.io/github/issues-pr/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/pulls?q=is%3Apr+is%3Aclosed" target="_blank"><img src="https://img.shields.io/github/issues-pr-closed/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin" target="_blank"><img src="https://img.shields.io/github/last-commit/d2-projects/d2-admin.svg"></a>
</p>
<p align="center">
<a href="https://github.com/d2-projects/d2-admin" target="_blank"><img src="https://visitor-badge.glitch.me/badge?page_id=d2-projects.d2-admin"></a>
<a href="https://github.com/d2-projects/d2-admin/releases" target="_blank"><img src="https://img.shields.io/github/release/d2-projects/d2-admin.svg"></a>
<a href="https://deepscan.io/dashboard#view=project&tid=8014&pid=10161&bid=136697"><img src="https://deepscan.io/api/teams/8014/projects/10161/branches/136697/badge/grade.svg" alt="DeepScan grade"></a>
</p>
[D2Admin](https://github.com/d2-projects/d2-admin) is a fully open source and free enterprise back-end product front-end integration solution, using the latest front-end technology stack, javascript files loading of local first screen less than 60kb, has prepared most of the project preparations, and with a lot of sample code to help the management system agile development. ---
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/d2-projects/d2-admin) ## 环境要求
[中文](https://github.com/d2-projects/d2-admin/blob/master/README.zh.md) | **English** 本项目通过 **[Volta](https://volta.sh/)** 和 **[pnpm](https://pnpm.io/)** 锁定开发环境版本,确保团队成员使用完全一致的 Node.js 和包管理器版本。
## Preview | 工具 | 锁定版本 | 作用 |
![Deploy preview](https://github.com/d2-projects/d2-admin/workflows/Deploy%20preview/badge.svg)
[![Netlify Status](https://api.netlify.com/api/v1/badges/a5dd4bbd-da3f-4145-98a9-8012577bdcf5/deploy-status)](https://app.netlify.com/sites/d2-admin/deploys)
The following access addresses are built and deployed by the latest master branch code at the same time. The access effect is completely consistent. Please select the appropriate access link according to your own network situation.
| server | link | server |
| --- | --- | --- | | --- | --- | --- |
| d2.pub | [Link](https://d2.pub/d2-admin/preview) | China server | | **Node.js** | `18.16.0` | JavaScript 运行时(`.node-version` 文件) |
| github | [Link](https://d2-projects.github.io/d2-admin) | GitHub pages | | **pnpm** | `10.33.0` | 包管理器(`package.json``packageManager` 字段) |
| netlify | [Link](https://d2-admin.netlify.com) | Netlify CDN |
## Document > 配置文件说明:
> - `.node-version` → Volta 读取,自动切换 Node.js 版本
> - `package.json` → `engines` 字段限制版本范围,`packageManager` 字段锁定 pnpm 版本
> - `.npmrc` → `engine-strict=true` 强制使用锁定版本,不满足则安装失败
[document on https://d2.pub](https://d2.pub/doc/d2-admin/) ---
## Features ## 从零开始安装到启动
* Build with vue-cli3 ### 第一步:安装 Volta如果尚未安装
* First screen loading waiting animation
* Five themes
* Built-in UEditor rich text editor
* Detailed documentation
* Login and logout
* Separate routing and menu settings
* Foldable sidebar
* Multi-national language
* Rich text editor
* Markdown editor
* full screen
* Fontawesome icon library
* Icon selector
* Automatically register SVG icon
* Simulation data
* Clipboard package
* Chart library
* Time and date calculation tool
* Import Excel ( xlsx + csv )
* Data export Excel ( xlsx + csv )
* Data export text
* Digital animation
* Drag and drop the size of the block layout
* Grid layout for drag and resize and position
* Out-of-the-box page layout components
* Load and parse markdown files
* GitHub style markdown display component
* markdown internal code highlighting
* Expanded Baidu cloud link resolution and optimized display for markdown
* Right click menu component
* Custom scrollbars and scrolling controls
* Common style extraction, convenient theme customization
* Support temporary menu configuration
* System function display module `1.1.4 +`
* Multi-tab mode `1.1.4 +`
* Beautify the scroll bar `1.1.4 +`
* json view `1.1.4 +`
* cookie wrapper `1.1.5 +`
* Multi-tab global control API `1.1.5 +`
* Menu Global Control API `1.1.5 +`
* Multi-tab page close control support right-click menu `1.1.10 +`
* Modular global state management `1.2.0 +`
* Multiple data persistence methods: distinguish users, distinguish routes, page data snapshot function `1.2.0 +`
* Support for menu system that jumps out of external links `1.2.0 +`
* Support menu svg icon `1.3.0 +`
* Logging and error catching `1.3.0 +`
* Global menu search `1.3.0 +`
* Custom login redirect `1.3.0 +`
* Switch global base component size `1.4.0 +`
* Page loading progress bar `1.4.1 +`
* Adaptive top menu bar `1.4.7 +`
* Support for merging cells when exporting xslx `1.5.4 +`
* Multiple tabs support drag and drop sorting `1.8.0 +`
* load only local JavaScript code less than 60kb on the homepage `1.8.0 +`
* Built in build file volume checking tool `1.8.0 +`
* Example of multi page `1.23.0 +`
* Split chunks `1.23.0 +`
## Other synchronous repositories Volta 会根据 `.node-version` 自动安装并切换到项目所需的 Node.js 版本。
| type | link | **WindowsPowerShell**
| --- | --- |
| gitee | [https://gitee.com/d2-projects/d2-admin](https://gitee.com/d2-projects/d2-admin) |
| coding | [https://d2-projects.coding.net/p/d2-projects/d/d2-admin/git](https://d2-projects.coding.net/p/d2-projects/d/d2-admin/git) |
## Other versions ```powershell
winget install Volta.Volta
| Name | HomePage | Preview | Introduction |
| --- | --- | --- | --- |
| Starter template | [Link](https://github.com/d2-projects/d2-admin-start-kit) | [Link](https://d2.pub/d2-admin-start-kit/preview) | The simplest version |
## Open source backend implementation
> The backend is contributed by the open source community. The latest version of D2Admin is not guaranteed. Please contact its open source author for related usage issues.
| Name | technology | HomePage | Preview | Introduction |
| --- | --- | --- | --- | --- |
| django-vue-admin-pro | Django | [Link](https://github.com/dvadmin-pro/django-vue-admin-pro) | [Link](http://demo.pro.django-vue-admin.com) | Django + Jwt + D2Admin |
| boot-admin | SpringBoot | [Link](https://github.com/hb0730/boot-admin) | [Link](http://admin.hb0730.com/) | Management system based on SpringBoot |
| FlaskPermission | Flask | [Link](https://github.com/huguodong/flask-permission) | [Link](http://47.97.218.139:9999) | Permission management based on Flask |
| CareyShop | ThinkPHP5 | [Link](https://github.com/dnyz520/careyshop-admin) | [Link](https://demo.careyshop.cn/admin/) | High Performance Mall Framework System for CareyShop |
| jiiiiiin-security | Spring Boot | [Link](https://github.com/Jiiiiiin/jiiiiiin-security) | [Link](https://github.com/Jiiiiiin/jiiiiiin-security) | Content management infrastructure projects |
| Taroco | Spring Cloud | [Link](https://github.com/liuht777/Taroco) | [Link](http://111.231.192.110/) | Complete microservice enterprise solution |
| Aooms | Spring Cloud | [Link](https://gitee.com/cyb-javaer/Aooms) | [Link](https://www.yuboon.com/Aooms) | Extremely fast microservice development, not just as simple as JFinal |
| GOA | Beego | [Link](https://github.com/Qsnh/goa) | [Link](http://goaio.vip/) | Online question answering system based on Beego + Vue |
| CMDB | Django | [Link](https://github.com/CJFJack/django_vue_cmdb) | [Link](https://mp.weixin.qq.com/s?__biz=MzU1OTYzODA4Mw==&mid=2247484250&idx=1&sn=981024ac0580d8a3eba95742bd32b268) | authority system with dynamic menu |
## Community projects
> These projects are contributed by the open source community and are not guaranteed to use the latest version of D2Admin. Please contact their open source authors for related usage questions.
| Name | HomePage | Preview | Introduction |
| --- | --- | --- | --- |
| d2-admin-xiya-go-cms | [Link](https://github.com/d2-projects/d2-admin-xiya-go-cms) | [Link](https://d2.pub/d2-admin-xiya-go-cms/preview) | D2Admin + authority system + dynamic router |
| d2-advance | [Link](https://github.com/d2-projects/d2-advance) | [Link](https://d2.pub/d2-advance/preview) | Technical exploration inspired by D2Admin |
| d2-crud-plus | [Link](https://github.com/greper/d2-crud-plus) | [Link](http://qiniu.veryreader.com/D2CrudPlusExample/index.html) | Easy development of crud function |
| d2-crud | [Link](https://github.com/d2-projects/d2-crud) | [Link]() | Encapsulation of common operations in tables |
| d2-admin-pm | [Link](https://github.com/wjkang/d2-admin-pm) | [Link](http://jaycewu.coding.me/d2-admin-pm) | RBAC privilege management solution based on D2Admin |
| LanBlog | [Link](https://github.com/sinksmell/LanBlog) | [Link](http://47.101.222.133/) | Vue + Beego restful api personal blog system |
| d2-admin-start-kit-plus | [Link](https://github.com/hank-cp/d2-admin-start-kit-plus) | [Link](https://github.com/hank-cp/d2-admin-start-kit-plus) | D2Admin Start kit modular version |
| d2-ribbons | [Link](https://github.com/d2-projects/d2-ribbons) | [Link](https://github.com/d2-projects/d2-ribbons) | Open source project logo Library |
## Badge
If your open source project is based on D2Admin development, please add the following badge to your README:
<a href="https://github.com/d2-projects/d2-admin" target="_blank">
<img src="https://raw.githubusercontent.com/d2-projects/d2-admin/master/docs/image/d2-admin@2x.png" width="200">
</a>
Copy the following code into the README to:
``` html
<a href="https://github.com/d2-projects/d2-admin" target="_blank"><img src="https://raw.githubusercontent.com/d2-projects/d2-admin/master/docs/image/d2-admin@2x.png" width="200"></a>
``` ```
At the same time, you can report your project to us. We will place the excellent project in D2Admin and help you publicize it. > `winget` 安装完成后,**当前终端窗口不会自动加载 Volta**。选择以下任一方式生效:
>
> **方式一(关闭重开):** 关掉当前终端,重新打开一个 PowerShell / VS Code 终端。
>
> **方式二(不重启立即生效):** 在当前终端执行:
> ```powershell
> $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User")
> ```
>
> 生效后验证:
> ```powershell
> volta --version # 应输出版本号(如 2.0.2
> ```
## Contributor **macOS / Linux**
* [@FairyEver](https://github.com/FairyEver) ```bash
* [@sunhaoxiang](https://github.com/sunhaoxiang) curl https://get.volta.sh | bash
* [@Aysnine](https://github.com/Aysnine) # 重新加载 shell 配置
* [@luchaohai](https://github.com/luchaohai) source ~/.bashrc # 或 source ~/.zshrc
* [@han-feng](https://github.com/han-feng) volta --version
* [@rongxingsun](https://github.com/rongxingsun) ```
* [@dnyz520](https://github.com/dnyz520)
## Become a sponsor > 更多安装方式请参考 [Volta 官方文档](https://docs.volta.sh/guide/getting-started)。
[Sponsor me on afdian.net](https://afdian.net/@fairyever) ### 第二步:启用 pnpmVolta 内置支持,无需额外安装)
## Sponsor ```bash
# Volta 会根据 package.json 中的 packageManager 字段
# 自动安装并使用 pnpm@10.33.0
volta install pnpm@10.33.0
**cochlea** | **Baron** | **苦行僧** | **吴地安宁** | **KingDong** | **sunyongmofang** # 验证版本
pnpm --version # 应输出 10.33.0
```
## Visitor > 如果没有 Volta也可以手动安装 pnpm
> ```bash
> npm install -g pnpm@10.33.0
> ```
![Total visitor](https://visitor-badge.glitch.me/badge?page_id=d2-projects.d2-admin) ### 第三步:克隆项目并安装依赖
> Total visitor since 2019.08.27 ```bash
# 克隆仓库
git clone <仓库地址>
cd mes-ui
## Star history # Volta 检测到 .node-version 后,自动下载并安装 Node.js 18.16.0
# 如果你本机没有这个版本Volta 会提示 "Fetching node@18.16.0" —— 等它完成即可
node --version # 应输出 v18.16.0
[![Stargazers over time](https://starchart.cc/d2-projects/d2-admin.svg)](https://starchart.cc/d2-projects/d2-admin) # 安装依赖
pnpm install
```
## License > **没有安装 Node 18.16.0 怎么办?**
> **Volta 用户**:无需手动操作。进入项目目录时 Volta 会自动检测 `.node-version`,如果本机缺这个版本,它会**自动下载安装**,你只需等待几秒终端提示完成即可。
> **nvm 用户**:执行 `nvm install 18.16.0 && nvm use 18.16.0`。
> **手动安装**:去 [nodejs.org](https://nodejs.org/) 下载 Node.js 18.16.0 安装包。
>
> 装完后建议运行 `node --version` 确认输出 `v18.16.0`,否则 `pnpm install` 会因为 `engine-strict=true` 直接报错拒绝安装。
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fd2-projects%2Fd2-admin.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fd2-projects%2Fd2-admin?ref=badge_large) ### 第四步:配置环境变量
在项目根目录创建 `.env.development.local` 文件(此文件已在 `.gitignore` 中,不会提交):
```bash
# 后台 API 地址
VUE_APP_API=http://你的后台服务器地址/
```
### 第五步:启动开发服务器
```bash
pnpm serve
```
浏览器会自动打开 `http://localhost:8080`(或终端提示的实际端口)。
---
## 常用命令速查
| 命令 | 说明 |
| --- | --- |
| `pnpm serve` | 启动开发服务器(自动打开浏览器) |
| `pnpm build` | 生产环境构建 |
| `pnpm build:preview` | 预发布环境构建 |
| `pnpm lint` | ESLint 代码检查并自动修复 |
| `pnpm test:unit` | 运行单元测试 |
| `pnpm install` | 安装依赖 |
| `pnpm add <包名>` | 添加新依赖(**禁止使用 npm install** |
| `pnpm remove <包名>` | 移除依赖 |
---
## 版本锁定机制
### Node.js 版本锁定Volta
```
项目根目录
├── .node-version → 18.16.0Volta 自动读取切换)
```
- Volta 进入项目目录时自动将 Node.js 切换为 `18.16.0`
- 如果该版本未安装Volta 会自动下载并安装
- 传统方案nvm也兼容`nvm use` 读取 `.nvmrc`,本项目同时提供 `.node-version` 供 Volta 使用
### pnpm 版本锁定
```
package.json
├── packageManager → pnpm@10.33.0Corepack / Volta 识别)
├── engines.pnpm → >=10.33.0 <11npm/pnpm install 时校验)
```
```ini
# .npmrc
engine-strict=true # 版本不满足 → 安装直接报错
```
### 依赖版本锁定
```
pnpm-lock.yaml → 锁定所有依赖的精确版本(等价于 npm 的 package-lock.json
```
> `pnpm-lock.yaml` **必须提交到 Git**,保证所有环境安装的依赖版本完全一致。
---
## 项目目录结构
```
mes-ui/
├── .github/ # GitHub 相关配置
├── docs/ # 项目文档
├── public/ # 静态资源(不经过 webpack 处理)
├── src/ # PC 端业务源码
│ ├── api/ # 接口请求层(按业务模块拆分)
│ │ ├── _service.js # axios 请求服务实例
│ │ └── production-master-data/ # 生产主数据模块 API
│ ├── assets/ # 静态资源(经 webpack 处理,含 SCSS / SVG
│ ├── components/ # 公共组件
│ │ ├── page-table/ # CRUD 表格便捷组合体
│ │ └── page-dialog-form/ # 新增/编辑弹框组件
│ ├── composables/ # 可复用逻辑函数
│ │ ├── useTableColumns.js # 列定义工厂
│ │ ├── useTableButtons.js # 按钮定义工厂
│ │ └── useI18n.js # i18n Mixin 工厂
│ ├── layout/ # 页面布局header-aside
│ ├── libs/ # 工具函数
│ ├── locales/ # 国际化语言包zh-chs / en
│ ├── router/ # 路由配置modules/ 按业务模块拆分)
│ ├── store/ # Vuex 状态管理
│ ├── utils/ # 通用工具文件下载、Excel 读取等)
│ └── views/ # 业务页面(按模块三级目录组织)
│ ├── production-master-data/ # 生产主数据
│ ├── system-administration/ # 系统管理
│ ├── equipment-management/ # 设备管理
│ ├── quality-management/ # 质量管控
│ ├── planning-production/ # 计划生产
│ └── data-platform/ # 数据平台
├── src.mobile/ # 移动端业务源码
├── .browserslistrc # 浏览器兼容配置
├── .editorconfig # 编辑器统一配置
├── .env / .env.development / .env.preview # 环境变量
├── .eslintignore / .eslintrc.js # ESLint 配置
├── .gitignore # Git 忽略配置
├── .node-version # Volta Node.js 版本锁定18.16.0
├── .npmrc # pnpm 配置(版本强校验)
├── .postcssrc.js # PostCSS 配置
├── babel.config.js # Babel 配置
├── jest.config.js # Jest 单元测试配置
├── jsconfig.json # VS Code 路径别名提示
├── package.json # 项目依赖与脚本
├── pnpm-lock.yaml # pnpm 依赖锁定文件(必须提交)
├── vue.config.js # Vue CLI 构建配置
└── README.md # 项目说明(本文件)
```
---
## 项目文档
| 文档 | 说明 |
| --- | --- |
| [表格组件使用说明](./docs/表格组件使用说明.md) | `page-table` + `page-dialog-form` 完整使用手册 |
| [国际化规则](./docs/国际化规则.md) | i18n 使用规范与迁移指南 |
| [迁移提示词](./docs/迁移提示词.md) | 旧页面迁移到新方案的规则文档 |
| [SCT基础表格重构设计](./docs/SCT基础表格重构设计.md) | 旧 `sct-base-table` → 新架构设计文档 |
| [变更日志](./docs/变更日志.md) | 项目变更日志 |
---
## 关键目录说明
### `src/components/` — 公共组件
| 组件 | 作用 |
| --- | --- |
| `page-table` | CRUD 表格组合体(按钮栏 + 表格 + 分页 + 高度自适应 + 帮助按钮) |
| `page-dialog-form` | 新增/编辑弹框(表单渲染 + 校验 + i18n 自动翻译) |
| `d2-container` | 页面容器(卡片、全屏、透明等多种布局变体) |
| `d2-container-frame` | iframe 嵌套外部页面容器 |
> `page-table` 和 `page-dialog-form` 是本项目核心组件,详细用法见 [表格组件使用说明](./docs/表格组件使用说明.md)。
### `src/composables/` — 逻辑复用层
| 文件 | 作用 |
| --- | --- |
| `useTableColumns.js` | 列定义工厂,消除手动分配 `idx`,约定 `prop: '_actions'` 为操作列 |
| `useTableButtons.js` | 按钮工厂,一键生成工具栏 + 行内按钮,自动注入权限过滤 |
| `useI18n.js` | i18n Mixin 工厂,通过 `i18nMixin(prefix)` 注入 `key()` / `ckey()` |
| `useConfirmHandle.js` | 确认操作 Mixin封装 `$confirm` + API 调用 |
### `src/router/modules/` — 路由模块
按业务一级模块拆分examples:
| 文件 | 路由前缀 | 对应模块 |
| --- | --- | --- |
| `production-master-data.js` | `/production_configuration` | 生产主数据 |
| `system-administration.js` | `/system_settings` | 系统管理 |
| `equipment-management.js` | `/equipment_management` | 设备管理 |
| `quality-management.js` | `/quality_management` | 质量管控 |
| `planning-production.js` | `/planning_production` | 计划生产 |
| `data-platform.js` | `/data_platform` | 数据平台 |
### `src/api/` — 接口请求层
按业务模块父目录存放,命名规则:`{模块名}.js`。例如:
- `production-master-data/device-category.js` → 设备类型
- `production-master-data/factory-area.js` → 工厂区域
---
## 构建配置文件
| 文件 | 作用 |
| --- | --- |
| `vue.config.js` | Vue CLI 构建配置多页入口、CDN、webpack 插件、主题色替换、SVG sprites、路径别名 |
| `babel.config.js` | Babel 转译配置 |
| `.postcssrc.js` | PostCSS 自动前缀等配置 |
| `.eslintrc.js` | ESLint 代码规范 |
| `jest.config.js` | 单元测试框架配置 |
| `jsconfig.json` | VS Code 路径别名智能提示(`@``src/` |
| `.browserslistrc` | 目标浏览器范围 |
| `.editorconfig` | 编辑器缩进/换行风格统一 |
---
## 环境变量
| 文件 | 说明 |
| --- | --- |
| `.env` | 所有环境通用变量 |
| `.env.development` | 开发环境变量 |
| `.env.development.local` | 本地开发环境变量(不提交 Git需自行创建 |
| `.env.preview` | 预发布环境变量 |
---
## 常见问题
### Q1`pnpm install` 报错 "Unsupported engine"
> 意思:本机 Node.js 或 pnpm 版本不在项目规定范围内install 被阻断。
**先排查版本:**
```bash
node --version # 项目要求 >=18.16.0 <19
pnpm --version # 项目要求 >=10.33.0 <11
```
**谁把版本不对:**
| 情景 | 解决办法 |
| --- | --- |
| **用 Volta**(推荐) | `volta install node@18.16.0` + `volta install pnpm@10.33.0`,进入项目目录自动生效 |
| **用 nvm** | `nvm install 18.16.0 && nvm use 18.16.0`,再 `npm install -g pnpm@10.33.0` |
| **手动安装** | 去 [nodejs.org](https://nodejs.org/) 下载 18.16.0,再 `npm install -g pnpm@10.33.0` |
| **已有正确版本但切换不生效** | 重新打开终端,确保 `volta` / `nvm` 已正确加载 |
> 版本验证通过后,重新执行 `pnpm install`。
### Q2启动后页面报跨域错误
`.env.development.local` 中确认 `VUE_APP_API` 指向正确的后台地址,且后台已开启 CORS。
### Q3端口被占用
默认端口为 `8080`。如需修改,在 `.env.development.local` 中添加:
```bash
PORT=8081
```
### Q4`volta` 命令无法识别 / "无法将 volta 项识别为 cmdlet"
> 原因:`winget install Volta.Volta` 不会自动刷新当前终端的 PATH 缓存。
**解决办法二选一:**
```powershell
# 方案 A关掉当前终端重新打开一个推荐最简单
# 方案 B在当前终端执行以下命令立即生效免重启
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User")
```
> 生效后 `volta --version` 应输出版本号。
### Q5依赖安装慢
pnpm 默认使用 npm registry。如需加速可配置镜像
```bash
pnpm config set registry https://registry.npmmirror.com
```

View File

@@ -1,205 +0,0 @@
![banner](https://raw.githubusercontent.com/FairyEver/d2-admin/master/docs/image/banner.png)
<p align="center">
<a href="https://github.com/d2-projects/d2-admin/stargazers" target="_blank"><img src="https://img.shields.io/github/stars/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/network/members" target="_blank"><img src="https://img.shields.io/github/forks/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/issues" target="_blank"><img src="https://img.shields.io/github/issues/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/issues?q=is%3Aissue+is%3Aclosed" target="_blank"><img src="https://img.shields.io/github/issues-closed/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/pulls" target="_blank"><img src="https://img.shields.io/github/issues-pr/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin/pulls?q=is%3Apr+is%3Aclosed" target="_blank"><img src="https://img.shields.io/github/issues-pr-closed/d2-projects/d2-admin.svg"></a>
<a href="https://github.com/d2-projects/d2-admin" target="_blank"><img src="https://img.shields.io/github/last-commit/d2-projects/d2-admin.svg"></a>
</p>
<p align="center">
<a href="https://github.com/d2-projects/d2-admin" target="_blank"><img src="https://visitor-badge.glitch.me/badge?page_id=d2-projects.d2-admin"></a>
<a href="https://github.com/d2-projects/d2-admin/releases" target="_blank"><img src="https://img.shields.io/github/release/d2-projects/d2-admin.svg"></a>
<a href="https://deepscan.io/dashboard#view=project&tid=8014&pid=10161&bid=136697"><img src="https://deepscan.io/api/teams/8014/projects/10161/branches/136697/badge/grade.svg" alt="DeepScan grade"></a>
</p>
[D2Admin](https://github.com/d2-projects/d2-admin) 是一个完全 **开源免费** 的企业中后台产品前端集成方案,使用最新的前端技术栈,小于 60kb 的本地首屏 js 加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助力管理系统敏捷开发。
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/d2-projects/d2-admin)
**中文** | [English](https://github.com/d2-projects/d2-admin)
## 预览
![Deploy preview](https://github.com/d2-projects/d2-admin/workflows/Deploy%20preview/badge.svg)
[![Netlify Status](https://api.netlify.com/api/v1/badges/a5dd4bbd-da3f-4145-98a9-8012577bdcf5/deploy-status)](https://app.netlify.com/sites/d2-admin/deploys)
下列访问地址均由最新的 master 分支代码同时构建部署,访问效果完全一致,请根据自身网络情况选择合适的访问链接。
| 位置 | 链接 | 部署位置 |
| --- | --- | --- |
| d2.pub | [preview](https://d2.pub/d2-admin/preview) | 中国服务器 |
| github | [preview](https://d2-projects.github.io/d2-admin) | GitHub pages |
| netlify | [preview](https://d2-admin.netlify.com) | Netlify CDN |
## 文档
[在 https://d2.pub 上的本项目文档](https://d2.pub/doc/d2-admin/)
## 功能
* 使用 vue-cli3 构建
* 首屏加载等待动画
* 五款主题
* 内置 UEditor 富文本编辑器
* 详细的文档
* 登录和注销
* 分离的路由和菜单设置
* 可折叠侧边栏
* 多国语
* 富文本编辑器
* Markdown 编辑器
* 全屏
* Fontawesome 图标库
* 图标选择器
* 自动注册 SVG 图标
* 模拟数据
* 剪贴板封装
* 图表库
* 时间日期计算工具
* 导入 Excel xlsx + csv
* 数据导出 Excel xlsx + csv
* 数据导出文本
* 数字动画
* 可拖拽调整大小的区块布局
* 可拖拽调整大小和位置的网格布局
* 开箱即用的页面布局组件
* 加载并解析 markdown 文件
* GitHub 样式的 markdown 显示组件
* markdown 内代码高亮
* 为 markdown 扩展了百度云链接解析和优化显示
* 右键菜单组件
* 自定义滚动条和滚动控制
* 公用样式抽离,方便的主题定制
* 支持临时菜单配置
* 系统功能展示模块 `1.1.4 +`
* 多标签页模式 `1.1.4 +`
* 美化滚动条 `1.1.4 +`
* json view `1.1.4 +`
* cookie 封装 `1.1.5 +`
* 多标签页全局控制 API `1.1.5 +`
* 菜单全局控制 API `1.1.5 +`
* 多标签页关闭控制支持右键菜单 `1.1.10 +`
* 模块化全局状态管理 `1.2.0 +`
* 多种数据持久化方式:区分用户,区分路由,页面数据快照功能 `1.2.0 +`
* 支持跳出外部链接的菜单系统 `1.2.0 +`
* 支持菜单 svg 图标 `1.3.0 +`
* 日志记录和错误捕捉 `1.3.0 +`
* 全局菜单搜索 `1.3.0 +`
* 自定义登录重定向 `1.3.0 +`
* 切换全局基础组件尺寸 `1.4.0 +`
* 页面载入进度条 `1.4.1 +`
* 自适应的顶部菜单栏 `1.4.7 +`
* 数据导出 xslx 时支持合并单元格 `1.5.4 +`
* 多标签页支持拖拽排序 `1.8.0 +`
* 优化生产环境构建,首页只加载小于 60kb 的本地 js 代码 `1.8.0 +`
* 内置了构建文件体积检查工具 `1.8.0 +`
* 构建多页面示例 `1.23.0 +`
* 分包优化 `1.23.0 +`
## 其它同步仓库
| 位置 | 链接 |
| --- | --- |
| 码云 | [https://gitee.com/d2-projects/d2-admin](https://gitee.com/d2-projects/d2-admin) |
| coding | [https://d2-projects.coding.net/p/d2-projects/d/d2-admin/git](https://d2-projects.coding.net/p/d2-projects/d/d2-admin/git) |
> 如果您在 github 仓库下载很慢,可以尝试使用我们的码云仓库克隆代码
## 其它版本
| 名称 | 主页 | 预览 | 介绍 |
| --- | --- | --- | --- |
| 简化版模板 | [Github](https://github.com/d2-projects/d2-admin-start-kit) | [预览](https://d2.pub/d2-admin-start-kit/preview) | 无 |
## 开源后端实现
> 后端由开源社区贡献,不保证使用 D2Admin 最新版本,相关使用问题请联系其开源作者。
| 名称 | 技术 | 主页 | 预览 | 介绍 |
| --- | --- | --- | --- | --- |
| django-vue-admin-pro | Django | [Github](https://github.com/dvadmin-pro/django-vue-admin-pro) | [预览](http://demo.pro.django-vue-admin.com) | Django + Jwt + D2Admin |
| boot-admin | SpringBoot | [Github](https://github.com/hb0730/boot-admin) | [预览](http://admin.hb0730.com/) | 基于 SpringBoot 前后端分离的后台管理系统 |
| FlaskPermission | Flask | [Github](https://github.com/huguodong/flask-permission) | [预览](http://47.97.218.139:9999) | 基于 Python Flask 的权限管理 |
| CareyShop | ThinkPHP5 | [Github](https://github.com/dnyz520/careyshop-admin) | [预览](https://demo.careyshop.cn/admin/#/index) | 适用于 CareyShop 的高性能商城框架系统 |
| jiiiiiin-security | Spring Boot | [Github](https://github.com/Jiiiiiin/jiiiiiin-security) | [预览](https://github.com/Jiiiiiin/jiiiiiin-security) | 前后端分离的内容管理基础项目,注重用户权限管理功能 |
| Taroco | Spring Cloud | [Github](https://github.com/liuht777/Taroco) | [预览](http://111.231.192.110/) | 整套微服务企业级解决方案 |
| Aooms | Spring Cloud | [码云](https://gitee.com/cyb-javaer/Aooms) | [预览](https://www.yuboon.com/Aooms) | 极速微服务开发不止像JFinal一样简单 |
| GOA | Beego | [Github](https://github.com/Qsnh/goa) | [预览](http://goaio.vip/) | 基于 Beego + Vue 开发的在线问答系统 |
| CMDB | Django | [Github](https://github.com/CJFJack/django_vue_cmdb) | [预览](https://mp.weixin.qq.com/s?__biz=MzU1OTYzODA4Mw==&mid=2247484250&idx=1&sn=981024ac0580d8a3eba95742bd32b268) | 分用户加载不同菜单和权限 |
## 社区项目
> 这些项目由开源社区贡献,不保证使用 D2Admin 最新版本,相关使用问题请联系其开源作者。
| 名称 | 主页 | 预览 | 介绍 |
| --- | --- | --- | --- |
| d2-admin-xiya-go-cms | [Github](https://github.com/d2-projects/d2-admin-xiya-go-cms) | [预览](https://d2.pub/d2-admin-xiya-go-cms/preview) | D2Admin + 权限系统 + 动态路由 |
| d2-advance | [Github](https://github.com/d2-projects/d2-advance) | [预览](https://d2.pub/d2-advance/preview) | 由 D2Admin 启发的技术探索 |
| d2-crud-plus | [Github](https://github.com/greper/d2-crud-plus) | [预览](http://qiniu.veryreader.com/D2CrudPlusExample/index.html) | 简化d2-crud配置快速开发crud功能 |
| d2-crud | [Github](https://github.com/d2-projects/d2-crud) | [预览]() | 表格常用操作封装 |
| d2-admin-pm | [Github](https://github.com/wjkang/d2-admin-pm) | [预览](http://jaycewu.coding.me/d2-admin-pm) | 基于 D2Admin 的 RBAC 权限管理解决方案 |
| LanBlog | [Github](https://github.com/sinksmell/LanBlog) | [预览](http://47.101.222.133/) | Vue + Beego restful api 开发的懒人博客 |
| d2-admin-start-kit-plus | [Github](https://github.com/hank-cp/d2-admin-start-kit-plus) | [预览](https://github.com/hank-cp/d2-admin-start-kit-plus) | D2Admin 简化版模块化版本 |
| d2-ribbons | [Github](https://github.com/d2-projects/d2-ribbons) | [预览](https://github.com/d2-projects/d2-ribbons) | 开源项目徽标库 |
## 加入我们
D2Admin 是完全开源免费的项目,旨在帮助开发者更方便地进行管理系统开发,同时也提供 QQ 交流群和微信群,前后端的朋友可以相互答疑,项目组成员全部在内,所有 D2 相关项目使用问题欢迎在群内提问。
* QQ 1 群 `806395827`
* QQ 2 群 `592981556`
![join](https://raw.githubusercontent.com/FairyEver/d2-admin/master/docs/image/join@2x.png)
## 徽章
如果您的开源项目基于 D2Admin 开发,请在您的 README 添加下面的徽章:
<a href="https://github.com/d2-projects/d2-admin" target="_blank">
<img src="https://raw.githubusercontent.com/FairyEver/d2-admin/master/docs/image/d2-admin@2x.png" width="200">
</a>
复制下面代码加入到 README 中即可:
``` html
<a href="https://github.com/d2-projects/d2-admin" target="_blank"><img src="https://raw.githubusercontent.com/FairyEver/d2-admin/master/docs/image/d2-admin@2x.png" width="200"></a>
```
同时您可以将您的项目汇报给我们,优秀项目我们会放置在 D2Admin 相关位置并帮助您宣传。
## 贡献
* [@FairyEver](https://github.com/FairyEver)
* [@sunhaoxiang](https://github.com/sunhaoxiang)
* [@Aysnine](https://github.com/Aysnine)
* [@luchaohai](https://github.com/luchaohai)
* [@han-feng](https://github.com/han-feng)
* [@rongxingsun](https://github.com/rongxingsun)
* [@dnyz520](https://github.com/dnyz520)
## 成为赞助者
[在 "爱发电" 上赞助我](https://afdian.net/@fairyever)
## 赞助
**cochlea** | **Baron** | **苦行僧** | **吴地安宁** | **KingDong** | **sunyongmofang**
## 访问统计
![](https://visitor-badge.glitch.me/badge?page_id=d2-projects.d2-admin)
> 自 2019-08-27 起
## Star 历史
[![Stargazers over time](https://starchart.cc/d2-projects/d2-admin.svg)](https://starchart.cc/d2-projects/d2-admin)
## License
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fd2-projects%2Fd2-admin.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fd2-projects%2Fd2-admin?ref=badge_large)
![](https://raw.githubusercontent.com/FairyEver/d2-admin/master/docs/image/give-a-star@2x.png)

File diff suppressed because it is too large Load Diff

146
docs/Sass废弃修复.md Normal file
View File

@@ -0,0 +1,146 @@
# Sass 废弃警告修复记录
> 项目运行 `pnpm serve` 时Dart Sass 输出了多类废弃 API 警告。本文档记录问题现象、根因及修复方案。
---
## 1. `legacy-js-api` — Sass Loader 旧 JS API 警告
### 问题现象
```
Deprecation Warning [legacy-js-api]: The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
```
### 根因
`sass-loader` 旧版本默认通过旧版 JS API 调用 Dart Sass。Dart Sass 计划在 2.0 中移除该 API。
### 修复
**文件:`package.json`**
`sass-loader` 升级到 `10.5.2`v10 最后一个稳定版,兼容 Webpack 4该版本支持 `silenceDeprecations` 选项。
```diff
- "sass-loader": "^10.3.1",
+ "sass-loader": "~10.5.2",
```
**文件:`vue.config.js`**
`css.loaderOptions.sass` 中添加 `silenceDeprecations` 配置。
```js
sass: {
additionalData: '@use "@/assets/style/public.scss" as *;',
sassOptions: {
silenceDeprecations: ['legacy-js-api', 'import']
}
},
```
---
## 2. `import` — Sass `@import` 废弃警告
### 问题现象
```
DEPRECATION WARNING [import]: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
1 │ @import '~@/assets/style/unit/color.scss';
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src\assets\style\public.scss 1:9 @use
```
### 根因
`public.scss` 通过 `@import '~@/assets/style/unit/color.scss'` 引入颜色变量文件。Dart Sass 正在推动从 `@import` 迁移到 `@use` / `@forward` 模块系统。
### 为何不改成 `@use`
`@import` 使用了 Webpack 专有的 `~` 前缀做模块路径解析(`~@/assets/...``@use` 对此机制支持不稳定,直接替换可能导致构建失败。
### 修复
在上述 `silenceDeprecations` 数组中追加 `'import'`,静默该警告。
---
## 3. `global-builtin` — 全局内置函数 `nth()` 废弃警告
### 问题现象
```
Deprecation Warning [global-builtin]: Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0.
Use list.nth instead.
42 │ .#{$prefix}-m-#{nth($sizes, $index)} { margin: #{nth($sizes, $index)}px !important; }
│ ^^^^^^^^^^^^^^^^^^^
src\assets\style\public-class.scss 42:19 @import
src\App.vue 3:9 root stylesheet
```
### 根因
Dart Sass 正在将全局内置函数迁移到命名空间模块。`nth()` 属于 `sass:list` 模块,不应再作为全局函数直接调用。
### 修复(从源码根治)
**文件:`src/assets/style/public-class.scss`**
**步骤 1** — 文件顶部引入 `sass:list` 模块:
```diff
+ @use 'sass:list';
@import 'public';
```
**步骤 2** — 将 `@for` 循环中所有 `nth()` 替换为 `list.nth()`
```diff
@for $index from 1 to 6 {
- .#{$prefix}-m-#{nth($sizes, $index)} { margin: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-mt-#{nth($sizes, $index)} { margin-top: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-mr-#{nth($sizes, $index)} { margin-right: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-mb-#{nth($sizes, $index)} { margin-bottom: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-ml-#{nth($sizes, $index)} { margin-left: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-p-#{nth($sizes, $index)} { padding: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-pt-#{nth($sizes, $index)} { padding-top: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-pr-#{nth($sizes, $index)} { padding-right: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-pb-#{nth($sizes, $index)} { padding-bottom: #{nth($sizes, $index)}px !important; }
- .#{$prefix}-pl-#{nth($sizes, $index)} { padding-left: #{nth($sizes, $index)}px !important; }
+ .#{$prefix}-m-#{list.nth($sizes, $index)} { margin: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-mt-#{list.nth($sizes, $index)} { margin-top: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-mr-#{list.nth($sizes, $index)} { margin-right: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-mb-#{list.nth($sizes, $index)} { margin-bottom: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-ml-#{list.nth($sizes, $index)} { margin-left: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-p-#{list.nth($sizes, $index)} { padding: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-pt-#{list.nth($sizes, $index)} { padding-top: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-pr-#{list.nth($sizes, $index)} { padding-right: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-pb-#{list.nth($sizes, $index)} { padding-bottom: #{list.nth($sizes, $index)}px !important; }
+ .#{$prefix}-pl-#{list.nth($sizes, $index)} { padding-left: #{list.nth($sizes, $index)}px !important; }
}
```
---
## 涉及文件汇总
| 文件 | 修改内容 |
|------|---------|
| `package.json` | `sass-loader` 版本 `^10.3.1``~10.5.2` |
| `vue.config.js` | 添加 `sassOptions.silenceDeprecations` 配置 |
| `src/assets/style/public-class.scss` | 引入 `sass:list` 模块,`nth()``list.nth()` |
---
## 后续建议
- 当项目未来升级到 Vue CLI 5 / Webpack 5 时,可考虑将 `public.scss` 中的 `@import` 改为 `@use`(届时 `~` 前缀路径的兼容方案需要重新评估)。
- `silenceDeprecations` 中的 `'import'` 为临时静默方案,待 `@import` 改造完成后移除。

View File

@@ -0,0 +1,20 @@
# 功能测试任务列表 - BOM物料清单
> 路由:`/production_configuration/matetial_model/bom`
| 序号 | 测试项 | 操作步骤 | 预期结果 | 结果 |
|---|---|---|---|---|
| 1 | 页面入口 | 从菜单进入“BOM物料清单”或直接访问路由 | 页面正常打开,表格展示 BOM 编码、名称、产品型号、状态、创建人、创建时间和备注 | ☐ |
| 2 | 条件查询 | 输入 BOM 编码、名称或选择产品型号后点击“查询” | 列表按条件刷新,分页回到第一页 | ☐ |
| 3 | 重置查询 | 点击“重置” | 查询条件清空,列表恢复默认数据 | ☐ |
| 4 | 新增校验 | 点击“新增”,不填写编码、名称或产品型号直接确认 | 表单提示必填校验,不提交请求 | ☐ |
| 5 | 新增 BOM | 填写 BOM 编码、名称、产品型号、状态和备注后确认 | 弹窗关闭,提示操作成功,列表出现新增 BOM | ☐ |
| 6 | 编辑 BOM | 点击“编辑”,修改名称、状态或备注后确认 | 表单回显旧值,保存后列表展示新值 | ☐ |
| 7 | 删除 BOM | 点击“删除”并确认 | 提示操作成功,记录被删除,分页刷新正确 | ☐ |
| 8 | 打开 BOM 关系 | 点击“设置BOM” | 全屏关系弹窗打开,左侧显示工序单元,右侧显示当前工序 IN/OUT 关系 | ☐ |
| 9 | 切换工序 | 在左侧选择不同工序单元 | IN/OUT 列表按工序刷新 | ☐ |
| 10 | 添加 IN 物料 | 在 IN 区域点击“新增”,选择一个或多个物料后确认 | 物料加入 IN 列表,重复物料提示不可重复选择 | ☐ |
| 11 | 编辑 IN 投入数量 | 修改 IN 列表的投入数量并移出输入框 | 数量保存成功,刷新后仍保持新值 | ☐ |
| 12 | 添加 OUT 物料限制 | 在 OUT 区域尝试选择多个物料或已有 OUT 后继续新增 | 系统提示 OUT 结构只允许 1 个半成品 | ☐ |
| 13 | 删除 BOM 关系 | 勾选 IN/OUT 关系后点击删除,或点击行内删除 | 关系删除成功,列表刷新 | ☐ |
| 14 | 权限按钮 | 使用缺少新增/编辑/删除/设置BOM权限的账号进入页面 | 对应按钮不显示或不可操作 | ☐ |

View File

@@ -0,0 +1,648 @@
# SPC采集配置功能测试流程文档
> **测试对象**:生产配置 → SPC采集模型 → SPC采集配置Data Collection Configuration
> **迁移日期**2026-06-02
> **对应页面**[`src/views/production-master-data/spc-configuration/data-collection-configuration/index.vue`](file:///c:/code/compony/mes-ui-d2/src/views/production-master-data/spc-configuration/data-collection-configuration/index.vue)
> **API 文件**[`src/api/production-master-data/data-collection-configuration.js`](file:///c:/code/compony/mes-ui-d2/src/api/production-master-data/data-collection-configuration.js)
> **路由路径**`/production_configuration/spc_configuration/binding_scada_node`(旧值暂留,后续批量替换)
> **i18n 前缀**`page.production_master_data.spc_configuration.data_collection_configuration`
---
## 一、测试环境配置
| 配置项 | 要求 |
|--------|------|
| 浏览器 | Chrome 最新版、Edge 最新版(兼容 IE 11+ |
| 屏幕分辨率 | ≥ 1920×1080 |
| Node.js | ≥ 16.x |
| 包管理器 | pnpm ≥ 7.x |
| 后端服务 | Webman 已启动,且 SPC采集配置相关 API 可正常访问(`production_configuration/spc_configuration/binding_scada_node/*` |
| 测试账号 | 具有「生产配置 → SPC采集模型 → SPC采集配置」菜单权限的管理员账号含 create / edit / delete 权限) |
| 测试数据 | 准备至少 5 条测试用 SPC采集配置采集编码唯一覆盖不同采集类型实时、周期、触发、不同状态启用、禁用 |
| SCADA节点依赖 | 系统中至少配置 1 个可用的 SCADA 节点,便于绑定 |
| 语言切换 | 先测中文(简体中文),再切到英文验证 i18n 是否正常 |
| 权限分配 | 系统管理 → 菜单管理中确认 SPC采集配置按钮权限新增、编辑、删除已正确配置 |
---
## 二、测试前置条件
1. 后端服务Webman已启动`production_configuration/spc_configuration/binding_scada_node/` 模块的 API 可正常访问
2. 前端项目已执行 `pnpm install``pnpm dev` 正常启动,可访问登录页
3. 使用具有「生产配置 → SPC采集模型 → SPC采集配置」菜单权限的管理员账号登录
4. 侧边栏菜单 **生产配置 → SPC采集模型** 下可见 **SPC采集配置** 子菜单
5. 浏览器控制台无 Vue 警告或 i18n key 缺失报错
6. 确认 `src/locales/zh-chs.json``src/locales/en.json` 中存在 `page.production_master_data.spc_configuration.data_collection_configuration` 配置
7. 数据库中 SPC采集配置表为空或仅有少量测试数据便于验证
8. 系统中至少存在 1 个已配置的 SCADA 节点
---
## 三、功能测试用例
### 3.1 页面加载与数据展示
#### TC-SCC-001菜单导航与页面加载
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 登录系统 2. 点击侧边栏菜单「生产配置 → SPC采集模型 → SPC采集配置」 |
| **预期结果** | 页面正常加载URL 显示 `/production_configuration/spc_configuration/binding_scada_node`页面顶部显示搜索栏采集编码、采集名称、SCADA节点、状态、查询、重置按钮中部显示 SPC采集配置 列表表格;底部分页组件显示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-002列表表格列头与数据展示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看 SPC采集配置 列表的表头列与各行数据 |
| **预期结果** | 表格列依次为序号、采集编码、采集名称、SCADA节点、采集类型、采集间隔(秒)、状态tag 标签展示)、备注、操作;操作列包含「编辑」「删除」两个按钮(带图标);当数据为空时显示空数据占位提示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-003状态列 Tag 展示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看列表中状态列的不同取值 |
| **预期结果** | 启用状态显示绿色 tagsuccess 类型),禁用状态显示红色 tagdanger 类型) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-004工具栏按钮显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看表格上方的工具栏 |
| **预期结果** | 显示蓝色「新增」按钮(含加号图标),右上角显示问号「帮助」按钮(点击跳转 `/help/data-collection-configuration` |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-005表格自适应高度
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 加载页面后查看表格高度 2. 缩小/放大浏览器窗口 3. 折叠/展开侧边栏 |
| **预期结果** | 表格高度自动填满 d2-container 剩余空间,窗口变化时无空白或滚动条异常 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.2 搜索功能
#### TC-SCC-006按采集编码精确搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「采集编码」输入框输入完整的采集编码(如 `SCC_001` 2. 点击「查询」按钮 |
| **预期结果** | 表格仅显示编码匹配的数据行;分页总数更新为匹配条数;输入框右侧 X 按钮可清空内容 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-007按采集编码模糊搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「采集编码」输入框输入编码的片段(如 `SCC_` 2. 点击「查询」按钮 |
| **预期结果** | 表格显示所有编码包含 `SCC_` 的数据行 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-008按采集名称搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「采集名称」输入框输入关键字(如「温度」) 2. 点击「查询」按钮 |
| **预期结果** | 表格仅显示名称包含关键字的 SPC采集配置 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-009按 SCADA 节点搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「SCADA节点」输入框输入节点关键字 2. 点击「查询」按钮 |
| **预期结果** | 表格仅显示 SCADA 节点字段匹配的数据行 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-010按状态筛选
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「状态」下拉中选择「启用」 2. 点击「查询」按钮 |
| **预期结果** | 表格仅显示状态为启用的数据行;下拉中可选择「启用」「禁用」或留空(全部) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-011组合条件搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 同时输入「采集编码」「采集名称」「SCADA节点」「状态」搜索条件 2. 点击「查询」按钮 |
| **预期结果** | 表格显示同时满足所有条件的数据行AND 关系) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-012回车键触发搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在搜索输入框中输入关键字 2. 按下键盘回车键 |
| **预期结果** | 等同于点击「查询」按钮,表格按搜索条件刷新 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-013重置搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 输入搜索条件并点击「查询」 2. 点击「重置」按钮 |
| **预期结果** | 搜索输入框和状态下拉清空,表格恢复显示全部 SPC采集配置 数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-014搜索无结果
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 输入不存在的编码或名称 2. 点击「查询」 |
| **预期结果** | 表格显示空数据占位提示,分页总数显示 0 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.3 分页功能
#### TC-SCC-015分页默认显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 加载页面后查看分页组件 |
| **预期结果** | 分页默认显示第 1 页,每页 10 条记录,总条数显示当前数据库 SPC采集配置 总数 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-016切换每页条数
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在分页组件的「每页显示」下拉中切换为 20、50、100 2. 观察表格变化 |
| **预期结果** | 表格按新条数加载数据,分页组件正确显示总页数 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-017翻页功能
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 准备至少 25 条测试数据 2. 点击「下一页」「上一页」「首页」「末页」按钮 3. 输入页码跳转 |
| **预期结果** | 表格按页加载数据,翻页流畅无报错 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.4 新增 SPC采集配置
#### TC-SCC-018打开新增弹框
| 项目 | 内容 |
|------|------|
| **测试步骤** | 点击表格上方「新增」按钮 |
| **预期结果** | 弹出新增 SPC采集配置 对话框,标题显示"新增SPC采集配置"包含采集编码、采集名称、SCADA节点、采集类型、采集间隔(秒)、状态、备注共 7 个表单项;「确定」「取消」按钮位于底部;弹框宽度约 50% |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-019新增表单必填校验 - 采集编码
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 不填写「采集编码」直接点击「确定」 |
| **预期结果** | 「采集编码」输入框下方显示红色校验提示"请输入采集编码" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-020新增表单必填校验 - 采集名称
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 不填写「采集名称」直接点击「确定」 |
| **预期结果** | 「采集名称」输入框下方显示红色校验提示"请输入采集名称" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-021新增表单必填校验 - SCADA 节点
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 不填写「SCADA节点」直接点击「确定」 |
| **预期结果** | 「SCADA节点」输入框下方显示红色校验提示"请输入SCADA节点" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-022新增表单必填校验 - 采集类型
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 不选择「采集类型」直接点击「确定」 |
| **预期结果** | 「采集类型」下拉框下方显示红色校验提示"请选择采集类型" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-023新增表单必填校验 - 状态
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 清空「状态」下拉框 3. 点击「确定」 |
| **预期结果** | 「状态」下拉框下方显示红色校验提示"请选择状态" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-024新增成功 - 实时采集类型
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 采集编码输入 `SCC_TEST_001` 3. 采集名称输入「温度实时采集」 4. SCADA节点输入 `SCADA_NODE_01` 5. 采集类型选择「实时」 6. 采集间隔输入 `1` 7. 状态选择「启用」 8. 备注输入「测试用」 9. 点击「确定」 |
| **预期结果** | 弹框关闭,页面右上角显示绿色成功提示"操作成功";表格自动刷新并显示新增的 SPC采集配置 行 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-025新增成功 - 周期采集类型
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 采集编码输入 `SCC_TEST_002` 3. 采集名称输入「压力周期采集」 4. SCADA节点输入 `SCADA_NODE_02` 5. 采集类型选择「周期」 6. 采集间隔输入 `60` 7. 状态选择「启用」 8. 备注留空 9. 点击「确定」 |
| **预期结果** | 新增成功,备注字段允许为空,表格中可见新增行(采集类型显示为"周期",采集间隔 60 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-026新增成功 - 触发采集类型
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 采集编码输入 `SCC_TEST_003` 3. 采集名称输入「流量触发采集」 4. SCADA节点输入 `SCADA_NODE_03` 5. 采集类型选择「触发」 6. 状态选择「禁用」 7. 点击「确定」 |
| **预期结果** | 新增成功,表格中状态列 tag 显示为红色(禁用) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-027新增 - 编码长度校验
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 在采集编码输入框输入超过 100 个字符 3. 失焦后观察 |
| **预期结果** | 输入框下方显示校验提示"长度在 1 到 100 个字符" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-028新增 - 编码重复
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 输入已存在的 SPC采集配置 编码 3. 点击「确定」 |
| **预期结果** | 提示后端返回的"编码已存在"等错误信息,新增失败,弹框不关闭 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-029取消新增
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 填写部分内容 3. 点击「取消」按钮 |
| **预期结果** | 弹框关闭,表格数据无变化,无任何提示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-030新增 - 备注多行输入
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 在备注框中输入多行文字(超过 2 行) 3. 观察文本框是否自动扩展 |
| **预期结果** | 备注为 textarea 类型,输入多行内容后自动扩展(最少 2 行,最多 6 行) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.5 编辑 SPC采集配置
#### TC-SCC-031打开编辑弹框
| 项目 | 内容 |
|------|------|
| **测试步骤** | 点击某一 SPC采集配置 行操作列的「编辑」按钮 |
| **预期结果** | 弹出编辑 SPC采集配置 对话框,标题显示"编辑SPC采集配置"采集编码、采集名称、SCADA节点、采集类型、采集间隔(秒)、状态、备注共 7 个字段正确回填该行的数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-032编辑成功 - 修改名称
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框(选择名称为"温度实时采集"的行) 2. 修改采集名称为"温度实时采集-改" 3. 点击「确定」 |
| **预期结果** | 弹框关闭,提示"操作成功",表格对应行的名称列更新为新值 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-033编辑成功 - 修改状态
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框(选择状态为启用的行) 2. 修改状态为「禁用」 3. 点击「确定」 |
| **预期结果** | 弹框关闭,提示"操作成功",表格对应行的状态 tag 由绿色变为红色 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-034编辑成功 - 修改采集间隔
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框 2. 修改采集间隔为 `120` 3. 点击「确定」 |
| **预期结果** | 弹框关闭,提示"操作成功",表格对应行的采集间隔列更新为 `120` |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-035编辑后清空必填项 - 采集名称
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框 2. 清空「采集名称」输入框 3. 点击「确定」 |
| **预期结果** | 「采集名称」下方显示红色校验提示,无法提交 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-036编辑后清空必填项 - SCADA 节点
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框 2. 清空「SCADA节点」输入框 3. 点击「确定」 |
| **预期结果** | 「SCADA节点」下方显示红色校验提示无法提交 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-037取消编辑
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框 2. 修改部分字段 3. 点击「取消」按钮 |
| **预期结果** | 弹框关闭,表格数据无变化,无任何提示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.6 删除 SPC采集配置
#### TC-SCC-038删除确认弹框
| 项目 | 内容 |
|------|------|
| **测试步骤** | 点击某一 SPC采集配置 行操作列的「删除」按钮 |
| **预期结果** | 弹出确认对话框,标题显示"提示",内容为"确定要删除该SPC采集配置吗?",按钮为"确定""取消" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-039取消删除
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 点击「删除」按钮 2. 在确认弹框中点击「取消」 |
| **预期结果** | 确认弹框关闭,表格数据无变化,无任何提示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-040删除成功
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 点击「删除」按钮 2. 在确认弹框中点击「确定」 |
| **预期结果** | 确认弹框关闭,提示"操作成功",表格对应行被移除;分页组件总数减 1如删除的是当前页最后一行则自动跳到上一页 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-041删除最后一行后页码修正
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 确保当前页只有 1 条数据 2. 删除该行 |
| **预期结果** | 删除成功后自动跳转到上一页(如当前已是第 1 页则停留在第 1 页),不会出现空页或无数据错误 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.7 国际化i18n
#### TC-SCC-042中文显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 系统语言切换为简体中文,查看 SPC采集配置 页面 |
| **预期结果** | 所有列头、表单 label、按钮、提示、状态枚举均显示中文采集编码、采集名称、SCADA节点、采集类型、采集间隔(秒)、状态、备注、新增、编辑、删除、确定、取消、提示、操作成功、实时、周期、触发、启用、禁用 等) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-043英文显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 系统语言切换为英文,查看 SPC采集配置 页面 |
| **预期结果** | 所有列头、表单 label、按钮、提示、状态枚举均显示英文Collection Code、Collection Name、SCADA Node、Collection Type、Interval (s)、Status、Remark、Add、Edit、Delete、Confirm、Cancel、Tip、Operation succeeded、Real-time、Periodic、Trigger、Enable、Disable 等) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-044弹框 i18n 自动响应
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在中文状态下打开新增弹框 2. 不关闭弹框,将语言切换为英文 3. 观察弹框标题、按钮文字、表单 label 是否自动翻译为英文 |
| **预期结果** | 弹框中的所有文案(包括 title、label、placeholder、按钮文字、校验提示跟随语言切换自动更新为对应英文无需关闭重开 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-045缺失 key 校验
| 项目 | 内容 |
|------|------|
| **测试步骤** | 打开浏览器开发者工具,切换页面、打开弹框、切换语言 |
| **预期结果** | 控制台无 i18n key 缺失警告(如 `[vue-i18n] Value of key 'xxx' is not a string` |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.8 权限控制
#### TC-SCC-046无 create 权限时隐藏新增按钮
| 项目 | 内容 |
|------|------|
| **测试步骤** | 使用没有 `create` 权限的账号登录,访问 SPC采集配置 页面 |
| **预期结果** | 工具栏不显示「新增」按钮 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-047无 edit 权限时隐藏编辑按钮
| 项目 | 内容 |
|------|------|
| **测试步骤** | 使用没有 `edit` 权限的账号登录,访问 SPC采集配置 页面 |
| **预期结果** | 行内操作列不显示「编辑」按钮 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-048无 delete 权限时隐藏删除按钮
| 项目 | 内容 |
|------|------|
| **测试步骤** | 使用没有 `delete` 权限的账号登录,访问 SPC采集配置 页面 |
| **预期结果** | 行内操作列不显示「删除」按钮 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.9 错误处理
#### TC-SCC-049网络异常 - 列表加载失败
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 关闭后端服务或断开网络 2. 刷新 SPC采集配置 页面 |
| **预期结果** | 表格 loading 状态结束,显示空数据占位;页面顶部弹出红色错误提示(来自全局拦截器);表格不卡死 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-SCC-050网络异常 - 提交失败
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 填写完整数据 3. 在点击「确定」之前断开网络 4. 点击「确定」 |
| **预期结果** | 弹框不关闭loading 状态结束;弹出红色错误提示;用户可修改后重试 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
---
## 四、测试结果汇总
| 用例编号 | 测试项 | 结果 | 问题摘要 |
|:--------:|--------|:----:|---------|
| TC-SCC-001 | 菜单导航与页面加载 | ⬜ | |
| TC-SCC-002 | 列表表格列头与数据展示 | ⬜ | |
| TC-SCC-003 | 状态列 Tag 展示 | ⬜ | |
| TC-SCC-004 | 工具栏按钮显示 | ⬜ | |
| TC-SCC-005 | 表格自适应高度 | ⬜ | |
| TC-SCC-006 | 按采集编码精确搜索 | ⬜ | |
| TC-SCC-007 | 按采集编码模糊搜索 | ⬜ | |
| TC-SCC-008 | 按采集名称搜索 | ⬜ | |
| TC-SCC-009 | 按 SCADA 节点搜索 | ⬜ | |
| TC-SCC-010 | 按状态筛选 | ⬜ | |
| TC-SCC-011 | 组合条件搜索 | ⬜ | |
| TC-SCC-012 | 回车键触发搜索 | ⬜ | |
| TC-SCC-013 | 重置搜索 | ⬜ | |
| TC-SCC-014 | 搜索无结果 | ⬜ | |
| TC-SCC-015 | 分页默认显示 | ⬜ | |
| TC-SCC-016 | 切换每页条数 | ⬜ | |
| TC-SCC-017 | 翻页功能 | ⬜ | |
| TC-SCC-018 | 打开新增弹框 | ⬜ | |
| TC-SCC-019 | 新增表单必填校验 - 采集编码 | ⬜ | |
| TC-SCC-020 | 新增表单必填校验 - 采集名称 | ⬜ | |
| TC-SCC-021 | 新增表单必填校验 - SCADA 节点 | ⬜ | |
| TC-SCC-022 | 新增表单必填校验 - 采集类型 | ⬜ | |
| TC-SCC-023 | 新增表单必填校验 - 状态 | ⬜ | |
| TC-SCC-024 | 新增成功 - 实时采集类型 | ⬜ | |
| TC-SCC-025 | 新增成功 - 周期采集类型 | ⬜ | |
| TC-SCC-026 | 新增成功 - 触发采集类型 | ⬜ | |
| TC-SCC-027 | 新增 - 编码长度校验 | ⬜ | |
| TC-SCC-028 | 新增 - 编码重复 | ⬜ | |
| TC-SCC-029 | 取消新增 | ⬜ | |
| TC-SCC-030 | 新增 - 备注多行输入 | ⬜ | |
| TC-SCC-031 | 打开编辑弹框 | ⬜ | |
| TC-SCC-032 | 编辑成功 - 修改名称 | ⬜ | |
| TC-SCC-033 | 编辑成功 - 修改状态 | ⬜ | |
| TC-SCC-034 | 编辑成功 - 修改采集间隔 | ⬜ | |
| TC-SCC-035 | 编辑后清空必填项 - 采集名称 | ⬜ | |
| TC-SCC-036 | 编辑后清空必填项 - SCADA 节点 | ⬜ | |
| TC-SCC-037 | 取消编辑 | ⬜ | |
| TC-SCC-038 | 删除确认弹框 | ⬜ | |
| TC-SCC-039 | 取消删除 | ⬜ | |
| TC-SCC-040 | 删除成功 | ⬜ | |
| TC-SCC-041 | 删除最后一行后页码修正 | ⬜ | |
| TC-SCC-042 | 中文显示 | ⬜ | |
| TC-SCC-043 | 英文显示 | ⬜ | |
| TC-SCC-044 | 弹框 i18n 自动响应 | ⬜ | |
| TC-SCC-045 | 缺失 key 校验 | ⬜ | |
| TC-SCC-046 | 无 create 权限时隐藏新增按钮 | ⬜ | |
| TC-SCC-047 | 无 edit 权限时隐藏编辑按钮 | ⬜ | |
| TC-SCC-048 | 无 delete 权限时隐藏删除按钮 | ⬜ | |
| TC-SCC-049 | 网络异常 - 列表加载失败 | ⬜ | |
| TC-SCC-050 | 网络异常 - 提交失败 | ⬜ | |
---
## 五、问题记录
| 序号 | 用例编号 | 问题描述 | 复现步骤 | 严重程度 | 截图 | 处理状态 | 责任人 |
|:----:|:--------:|---------|---------|:--------:|:----:|:--------:|--------|
| 1 | | | | | | | |
| 2 | | | | | | | |
| 3 | | | | | | | |
---
## 六、测试结论
| 项目 | 描述 |
|------|------|
| 测试用例总数 | 50 |
| 通过用例数 | |
| 未通过用例数 | |
| 通过率 | |
| 是否达到上线标准 | ⬜ 是 / ⬜ 否 |
| 备注 | |
**测试人员**________________
**测试日期**________________
**审核人员**________________
**审核日期**________________

View File

@@ -0,0 +1,40 @@
# 功能测试 - 反向追溯
> 模块:数据中台 / 基础追溯 / 反向追溯 (Backward Traceability)
> 路由:`/data_middleground/basic_traceability/reverse_direction_traceability`
## 测试前置条件
- 测试账号具备访问“反向追溯”的菜单权限。
- 准备至少 2 个电池条码:
- 一个存在完整反向追溯关系图的电池条码。
- 一个不存在追溯数据或数据为空的电池条码。
- 后端接口 `data_middleground/basic_traceability/reverse_direction_traceability/get_data``export_tree` 可正常访问。
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 从菜单进入“反向追溯”,或直接访问 `/data_middleground/basic_traceability/reverse_direction_traceability` | 页面正常打开,显示电池条码输入框、查询、导出、重置按钮和空态区域 |
| 2 | 空输入查询 | 不输入电池条码,点击“查询” | 页面提示请输入电池条码,不发起有效查询 |
| 3 | 有效条码查询 | 输入存在追溯数据的电池条码,点击“查询” | 页面通过 relation-graph 展示追溯图谱,节点包含物料名称、编码、批次、工序、时间、设备等信息 |
| 4 | 无数据条码查询 | 输入不存在追溯数据的电池条码,点击“查询” | 页面保持空态或显示无节点,不出现脚本错误 |
| 5 | 横向/纵向切换 | 查询出数据后,切换“横向图谱”和“纵向图谱” | 追溯节点展示方向切换,页面不丢失数据 |
| 6 | 图谱拖拽与缩放 | 查询出数据后,在图谱空白区域拖拽,并使用鼠标滚轮缩放 | 图谱内容可以平移和缩放,节点不会被页面容器裁切 |
| 7 | 节点内容完整性 | 查看包含较多字段的节点,滚动节点内容区域 | 节点卡片外框完整显示,字段内容可在节点内部滚动查看 |
| 8 | 物料编码定位 | 查询出数据后,输入某个节点的物料编码,点击定位确认 | 匹配节点高亮并居中聚焦到可视区域 |
| 9 | 物料批次定位 | 输入某个节点的物料批次,点击定位确认 | 匹配节点高亮并居中聚焦到可视区域 |
| 10 | 工序单元定位 | 输入某个制成品节点的工序单元编码,点击定位确认 | 匹配节点高亮并居中聚焦到可视区域;不存在时提示未找到匹配节点 |
| 11 | 导出前校验 | 未输入电池条码时点击“导出” | 页面提示请输入电池条码 |
| 12 | 查询前导出 | 输入电池条码但未查询出追溯树,点击“导出” | 页面提示请先查询追溯数据后再导出 |
| 13 | 正常导出 | 查询出追溯树后点击“导出” | 调用导出接口,浏览器开始下载或打开导出文件 |
| 14 | 重置功能 | 查询出追溯树后点击“重置” | 输入框、追溯树、定位输入和高亮状态全部清空 |
| 15 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、节点字段和提示文案随语言切换显示 |
## 回归关注点
- 接口返回 `relation_graph.nodes``relation_graph.lines` 为空时页面不能报错。
- 图谱必须使用 `relation-graph` 渲染,支持拖拽、缩放和定位聚焦。
- 节点字段较多时,节点卡片外框不应被裁切,内容应可在卡片内部滚动查看。
- 导出接口参数中的 `tree_list` 应为当前追溯树节点数组 JSON。
- 路由参数携带 `battery_id` 时,页面应能自动查询对应追溯数据。

View File

@@ -0,0 +1,31 @@
# 功能测试 - 托盘追溯
> 模块:数据中台 / 基础追溯 / 托盘追溯 (Tray Traceability)
> 路由:`/data_middleground/produce/traceability/tray`
## 测试前置条件
- 测试账号具备访问“托盘追溯”和“电池追溯”的菜单权限。
- 准备至少 1 个存在电池明细和工序时间线的托盘号。
- 后端接口 `tray``traydetail``batteryactive` 可正常访问。
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 进入“托盘追溯”页面 | 页面显示托盘号输入框、查询、重置按钮和托盘列表 |
| 2 | 托盘查询 | 输入有效托盘号并查询 | 表格展示托盘、批次、LOT、激活状态、投入电池数和时间信息 |
| 3 | 空数据查询 | 输入无数据托盘号并查询 | 表格显示空态,页面不报错 |
| 4 | 打开电池明细 | 点击某行“电池明细” | 打开全屏抽屉,展示左侧工序时间线和右侧电池明细表 |
| 5 | 明细搜索 | 在抽屉内输入电池条码关键字 | 明细表按电池条码过滤 |
| 6 | 取消激活校验 | 不选择电池,点击取消电池激活 | 页面提示请至少选择一个电池 |
| 7 | 取消激活 | 选择一个或多个电池后点击取消电池激活 | 调用取消激活接口,成功后刷新明细 |
| 8 | 跳转电池追溯 | 点击明细中的电池条码 | 跳转到电池追溯页面并携带 battery_id 查询参数 |
| 9 | 重置功能 | 查询后点击重置 | 托盘号、列表和分页状态清空 |
| 10 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、表格列和抽屉文案随语言切换显示 |
## 回归关注点
- 电池明细过滤需要排除空电池条码和 0。
- 取消激活接口参数 `batterData` 必须是已选择电池数组的 JSON 字符串。
- 电池条码跳转需保留 `battery_id` 查询参数。

View File

@@ -0,0 +1,14 @@
# 功能测试任务列表 - 排班日历
> 路由:`/system_settings/organization/production_shift_calender`
| 序号 | 测试项 | 操作步骤 | 预期结果 | 结果 |
|---|---|---|---|---|
| 1 | 页面入口 | 从菜单进入“排班日历” | 页面正常打开,展示当前月份日历 | ☐ |
| 2 | 初始数据加载 | 打开页面后观察日历单元格 | 系统请求当前日历可视范围的排班数据,并在日期下显示班次计划标签 | ☐ |
| 3 | 休息日展示 | 查看包含休息日的日期 | 休息日以灰色标签显示“休” | ☐ |
| 4 | 工作日展示 | 查看包含排班的日期 | 日期下展示班次计划标签 | ☐ |
| 5 | 明细悬浮 | 鼠标悬浮工作日班次计划标签 | 弹出层展示班次名称、开始/结束时间、绑定班组和跨天标识 | ☐ |
| 6 | 跨月切换 | 点击日历上一月/下一月 | 日历切换月份并重新加载新可视范围数据 | ☐ |
| 7 | 选择日期 | 点击任意日期 | 日期高亮状态正常,不影响排班数据显示 | ☐ |
| 8 | 空数据展示 | 切换到无排班数据的月份 | 日历正常显示,无错误提示或残留旧数据 | ☐ |

View File

@@ -0,0 +1,33 @@
# 功能测试 - 正向追溯
> 模块:数据中台 / 基础追溯 / 正向追溯 (Forward Traceability)
> 路由:`/data_middleground/basic_traceability/positive_direction_traceability`
## 测试前置条件
- 测试账号具备访问“正向追溯”和“反向追溯”的菜单权限。
- 准备至少一组可查询到数据的物料编码和物料批次。
- 准备至少一个可查询到数据的半成品码。
- 后端接口 `data_middleground/basic_traceability/positive_direction_traceability/list``export_task` 可正常访问。
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 从菜单进入“正向追溯”,或直接访问路由 | 页面正常打开,显示物料编码、物料批次、半成品码筛选项和查询、导出、重置按钮 |
| 2 | 初始查询 | 进入页面后等待默认查询完成 | 表格正常渲染,空数据时显示空态,不出现脚本错误 |
| 3 | 物料编码校验 | 只输入物料编码,不输入物料批次,点击查询 | 页面提示请输入物料批次,不发起有效查询 |
| 4 | 物料批次查询 | 输入物料编码和物料批次,点击查询 | 表格展示匹配数据,包含电池条码、批次号、物料、设备、工序和完成时间 |
| 5 | 半成品码查询 | 输入半成品码,点击查询 | 表格展示匹配数据或空态,页面不报错 |
| 6 | 分页切换 | 查询出多条数据后切换分页 | 当前页数据正确变化,总数显示正确 |
| 7 | 跳转反向追溯 | 点击某行“反向追溯” | 跳转到反向追溯页面,并携带当前行电池条码自动查询 |
| 8 | 导出前校验 | 不输入任何筛选条件时点击导出 | 页面提示请选择筛选条件 |
| 9 | 创建导出任务 | 输入筛选条件后点击导出并确认 | 调用导出任务接口,提示创建下载任务成功,并跳转任务页面 |
| 10 | 重置功能 | 输入筛选条件并查询后点击重置 | 筛选项清空,分页回到第一页并重新加载数据 |
| 11 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、表格列名和提示文案随语言切换显示 |
## 回归关注点
- 物料编码存在时必须同时输入物料批次。
- 导出任务必须携带当前筛选条件、总数和 `action=download`
- 反向追溯跳转必须使用行数据中的 `battery_id`

View File

@@ -0,0 +1,19 @@
# 功能测试任务列表 - 班次管理
> 路由:`/system_settings/organization/production_shift_management`
| 序号 | 测试项 | 操作步骤 | 预期结果 | 结果 |
|---|---|---|---|---|
| 1 | 页面入口 | 从菜单进入“班次管理” | 页面正常打开,展示班次计划名称、编码、起止时间、状态、创建/更新时间 | ☐ |
| 2 | 条件查询 | 输入计划名称、编码或创建时间后查询 | 列表按条件刷新 | ☐ |
| 3 | 新增校验 | 点击新增,不填名称、编码或时间范围直接确认 | 显示必填校验 | ☐ |
| 4 | 新增班次计划 | 填写计划信息、选择班组、添加班次明细后确认 | 保存成功,列表出现新计划 | ☐ |
| 5 | 班组绑定唯一性 | 两条班次明细绑定同一个班组 | 第二次绑定被阻止并提示 | ☐ |
| 6 | 明细必填校验 | 添加班次明细但缺少名称、开始时间或结束时间 | 提示对应行缺失字段 | ☐ |
| 7 | 编辑班次计划 | 点击编辑,修改状态、休息日、明细后确认 | 保存成功,重新打开可回显新数据 | ☐ |
| 8 | 单条删除 | 点击删除并确认 | 计划删除成功 | ☐ |
| 9 | 批量删除 | 勾选多条计划后批量删除 | 所选计划删除成功 | ☐ |
| 10 | 导入模板 | 点击导入后下载模板 | 浏览器下载班次计划导入模板 | ☐ |
| 11 | 导入数据 | 选择合法 xls/xlsx 文件并确认导入 | 预览展示后提交成功,列表刷新 | ☐ |
| 12 | 导出任务 | 点击导出并确认 | 提示下载任务创建成功 | ☐ |
| 13 | 权限按钮 | 使用缺少权限账号进入页面 | 对应新增/编辑/删除/导入/导出按钮隐藏或不可操作 | ☐ |

View File

@@ -0,0 +1,19 @@
# 功能测试任务列表 - 班组管理
> 路由:`/system_settings/organization/production_team_manage`
| 序号 | 测试项 | 操作步骤 | 预期结果 | 结果 |
|---|---|---|---|---|
| 1 | 页面入口 | 从菜单进入“班组管理” | 页面正常打开,展示班组名称、所属厂区、所属产线、创建/更新时间 | ☐ |
| 2 | 条件查询 | 输入班组名称、选择厂区/产线或创建时间后查询 | 列表按条件刷新 | ☐ |
| 3 | 新增校验 | 点击新增,不填班组名称、厂区或产线直接确认 | 显示必填校验,不提交 | ☐ |
| 4 | 新增班组 | 填写班组信息,添加成员并设置班组长后确认 | 提示操作成功,列表出现新班组 | ☐ |
| 5 | 班组长唯一性 | 添加多个成员并尝试设置两个班组长 | 第二个班组长被拦截,提示只允许一个班组长 | ☐ |
| 6 | 编辑班组 | 点击编辑,修改成员或班组信息后确认 | 保存成功,重新打开可看到新数据 | ☐ |
| 7 | 删除成员 | 编辑已有班组,删除已有成员 | 成员删除成功,列表刷新 | ☐ |
| 8 | 单条删除 | 点击行内删除并确认 | 班组删除成功 | ☐ |
| 9 | 批量删除 | 勾选多条数据后点击批量删除并确认 | 所选班组删除成功 | ☐ |
| 10 | 导入模板 | 点击导入后下载模板 | 浏览器下载班组导入模板 | ☐ |
| 11 | 导入数据 | 选择合法 xls/xlsx 文件并确认导入 | 预览数据正确,提交后提示成功并刷新列表 | ☐ |
| 12 | 导出任务 | 点击导出并确认 | 提示下载任务创建成功 | ☐ |
| 13 | 权限按钮 | 使用缺少权限账号进入页面 | 对应新增/编辑/删除/导入/导出按钮隐藏或不可操作 | ☐ |

View File

@@ -0,0 +1,36 @@
# 功能测试 - 电池复投管理
> 模块:计划与生产 / 生产监控 / 电池复投管理 (Rework Management)
> 路由:`/planning_production/produce/monitor/set_battery_rebatch`
## 测试前置条件
- 测试账号具备访问“电池复投管理”的菜单权限。
- 准备至少 3 个可用于验证的电池条码,其中包含:
- 允许复投的电池条码。
- 不允许复投或不存在的电池条码。
- 已激活和未激活状态各一条。
- 后端 Workerman 服务可用,接口 `production_configuration/workerman/send` 可正常响应。
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 从菜单进入“电池复投管理”页面,或直接访问 `/planning_production/produce/monitor/set_battery_rebatch` | 页面正常打开,显示电池条码输入框、验证数据、重置、复投激活按钮和空表格 |
| 2 | 单个电池验证 | 在电池条码输入框输入一条有效电池条码,点击“验证数据” | 表格展示该电池的批次、托盘、流水号、激活状态、档位、上一工序和当前工序 |
| 3 | 多电池粘贴验证 | 在输入框输入多个条码,使用逗号、空格或换行分隔,点击“验证数据” | 系统可自动规范化输入并返回多行电池数据 |
| 4 | 多电池弹窗输入 | 点击输入框右侧导入按钮,在弹窗中每行输入一个电池条码,点击“确定”后再点击“验证数据” | 输入框自动填入逗号分隔条码,表格展示对应验证数据 |
| 5 | 空输入校验 | 清空电池条码,点击“验证数据” | 页面提示“请输入电池条码数据”,不发起有效验证 |
| 6 | 重置功能 | 输入条码并验证出表格数据后,点击“重置” | 输入框、表格数据和已选行清空 |
| 7 | 全部复投激活 | 验证出多条可复投电池数据,不勾选表格行,点击“复投激活”并确认 | 请求提交表格内全部电池条码,成功后提示复投激活操作成功 |
| 8 | 选中行复投激活 | 验证出多条电池数据,勾选其中一部分,点击“复投激活”并确认 | 仅提交被勾选的电池条码,成功后提示复投激活操作成功 |
| 9 | 未验证直接复投 | 输入电池条码但不点击“验证数据”,直接点击“复投激活” | 页面提示需要先验证电池数据,不提交 Workerman 复投请求 |
| 10 | 复投取消 | 验证出表格数据,点击“复投激活”,在确认框点击取消 | 不提交复投请求,页面数据保持不变 |
| 11 | 后端失败提示 | 使用后端会返回失败的电池数据执行复投 | 页面显示后端错误信息或“复投激活失败”提示 |
| 12 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、表格列和提示文案随语言切换显示 |
## 回归关注点
- 验证接口返回空数据时,表格应显示空态且页面不报错。
- 表格行勾选后再重置,已选状态应同步清空。
- 复投激活接口调用参数中的 `action` 应为 `set_battery_rebatch``battery_ids` 应与测试输入或勾选行一致。

View File

@@ -0,0 +1,31 @@
# 功能测试 - 电池曲线
> 模块:数据中台 / 基础追溯 / 电池曲线 (Battery Curve)
> 路由:`/data_middleground/produce/traceability/curve`
## 测试前置条件
- 测试账号具备访问“电池曲线”的菜单权限。
- 准备至少 1 个存在曲线记录的电池条码。
- 后端接口 `planning_production/produce/traceability/batterytraceability``curveread``export` 可正常访问。
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 从菜单进入“电池曲线”,或直接访问路由 | 页面正常打开,显示电池条码输入框、查询、重置按钮、左侧记录区和右侧图表区 |
| 2 | 有效条码查询 | 输入存在曲线记录的电池条码,点击查询 | 左侧展示批次、工序、上传时间记录,默认选中第一条记录 |
| 3 | 曲线渲染 | 查询成功后查看右侧图表 | 图表显示电流、电压、容量三组数据,支持 tooltip、图例和图片保存 |
| 4 | 记录切换 | 点击左侧不同曲线记录 | 右侧设备编码、电池通道和曲线数据随选中记录刷新 |
| 5 | 图表缩放 | 在图表上使用鼠标滚轮或触控板缩放 | 曲线支持局部缩放,不影响页面布局 |
| 6 | 整盘曲线 | 选中带有 URL 的记录,点击“查看整盘曲线” | 浏览器跳转或打开整盘曲线页面 |
| 7 | 导出所有数据 | 选中记录后点击“导出所有数据” | 调用导出接口并触发文件下载或新窗口打开 |
| 8 | 无数据查询 | 输入不存在曲线记录的条码并查询 | 左侧显示暂无曲线记录,右侧图表清空,页面不报错 |
| 9 | 重置功能 | 查询后点击重置 | 输入框、记录列表、选中记录和图表数据清空 |
| 10 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、字段和图表标题随语言切换显示 |
## 回归关注点
- 曲线读取必须使用选中记录的 `id`
- 后端返回空数组时图表应清空,不应抛出异常。
- 导出链接需要兼容相对路径和完整 URL。

View File

@@ -0,0 +1,23 @@
# 功能测试 - 电池详情报表
> 模块:数据中台 / 生产报表 / 电池详情报表 (Battery Detail Report)
> 路由:`/data_middleground/produce/report/battery-detail`
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 进入电池详情报表页面 | 页面显示工艺流程、批次、工序、托盘、时间筛选项 |
| 2 | 工艺选择 | 选择工艺流程 | 批次和工序下拉数据按工艺刷新 |
| 3 | 批次必填校验 | 不选批次点击查询 | 页面提示请选择批次 |
| 4 | 查询报表 | 选择批次和筛选条件后查询 | 表格按动态表头展示电池详情数据 |
| 5 | 分页切换 | 查询出多页数据后切换分页 | 当前页数据刷新,总数正确 |
| 6 | 导出任务 | 选择批次后点击导出并确认 | 创建导出任务成功并跳转任务页面 |
| 7 | 重置功能 | 点击重置 | 筛选项、动态表头、表格和分页清空 |
| 8 | 国际化检查 | 切换中英文语言 | 页面文案随语言切换 |
## 回归关注点
- 查询前必须先获取动态表头。
- 导出任务 action 必须为 `download`
- 后端返回嵌套表头时需要展开为可展示列。

View File

@@ -0,0 +1,31 @@
# 功能测试 - 电池追溯
> 模块:数据中台 / 基础追溯 / 电池追溯 (Battery Traceability)
> 路由:`/data_middleground/produce/traceability/battery`
## 测试前置条件
- 测试账号具备访问“电池追溯”的菜单权限。
- 准备至少 1 个存在工序过程数据的电池条码。
- 准备 1 个已激活电池和 1 个 NG 且未激活电池,用于验证操作按钮。
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 进入“电池追溯”页面 | 页面显示电池条码输入框、查询、重置按钮和列表区域 |
| 2 | 电池查询 | 输入有效电池条码并查询 | 表格展示批次、托盘、LOT、激活状态、GOOD/NG、等级、不良信息、当前工序 |
| 3 | URL 参数查询 | 访问路由并携带 `?battery_id=xxx` | 页面自动按该电池条码查询 |
| 4 | 打开电池详情 | 点击某行“电池详情” | 弹出全屏详情,左侧展示工序列表,右侧展示默认工序数据 |
| 5 | 切换工序 | 在详情中点击不同工序 | 右侧工序数据按选中工序刷新 |
| 6 | 工序数据搜索 | 在详情中输入项目名称关键字 | 工序数据表按项目名称过滤 |
| 7 | 取消激活 | 对已激活电池点击取消激活并确认 | 调用取消激活接口,行状态更新为停止 |
| 8 | 复投激活 | 对 NG 且未激活电池点击复投激活并确认 | 调用 Workerman 复投接口,成功后刷新该电池数据 |
| 9 | 重置功能 | 查询后点击重置 | 电池条码、列表和分页状态清空 |
| 10 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、表格列和弹窗文案随语言切换显示 |
## 回归关注点
- 工序详情接口必须携带当前行的批次、电池条码、托盘、LOT 和工序信息。
- 取消激活接口参数 `batterData` 必须是数组 JSON。
- 复投激活必须发送 `set_battery_rebatch` action。

View File

@@ -0,0 +1,15 @@
# 功能测试任务列表 - 监控设置
> 路由:`/system_settings/system_monitoring/setting`
| 序号 | 测试项 | 操作步骤 | 预期结果 | 结果 |
|---|---|---|---|---|
| 1 | 页面入口 | 从菜单进入“监控设置”,或直接访问路由 | 页面正常打开表格展示监控编码、名称、IP、端口、版本和预警阈值字段 | ☐ |
| 2 | 条件查询 | 输入监控编码或监控名称后点击“查询” | 列表按条件刷新,分页回到第一页 | ☐ |
| 3 | 重置查询 | 输入查询条件后点击“重置” | 查询条件清空,列表恢复默认数据 | ☐ |
| 4 | 新增必填校验 | 点击“新增”不填写编码、名称、IP 或端口直接确认 | 表单提示对应必填校验,不提交请求 | ☐ |
| 5 | 新增监控配置 | 填写编码、名称、IP、端口、刷新间隔、CPU/磁盘/内存阈值和 Python 版本后确认 | 弹窗关闭,提示操作成功,列表出现新增记录 | ☐ |
| 6 | 编辑监控配置 | 点击某条记录“编辑”,修改名称或阈值后确认 | 弹窗回显旧值,保存后列表展示新值 | ☐ |
| 7 | 删除取消 | 点击“删除”后在确认框选择取消 | 数据不删除,列表保持不变 | ☐ |
| 8 | 删除确认 | 点击“删除”后确认 | 提示操作成功,记录从列表移除,分页数量正确刷新 | ☐ |
| 9 | 权限按钮 | 使用无新增/编辑/删除权限的账号进入页面 | 对应按钮不显示或不可操作 | ☐ |

View File

@@ -0,0 +1,9 @@
# 设备保养日志功能测试任务列表
- [ ] 进入 `设备模型 / 设备保养 / 设备保养日志`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,10 @@
# 设备保养详情功能测试任务列表
- [ ] 进入 `设备模型 / 设备保养 / 设备保养详情`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,10 @@
# 设备保养项目功能测试任务列表
- [ ] 进入 `设备模型 / 设备保养 / 设备保养项目`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,11 @@
# 设备信息功能测试任务列表
- [ ] 进入 `设备模型 / 设备信息 / 设备信息`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 如当前账号有导出权限,点击导出可创建导出任务。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,22 @@
# 功能测试 - 设备履历报表
> 模块:数据中台 / 生产报表 / 设备履历报表 (Equipment History Report)
> 路由:`/data_middleground/produce/report/equipment-history`
## 测试任务列表
| 序号 | 测试项 | 操作步骤 | 预期结果 |
|---:|---|---|---|
| 1 | 页面入口 | 进入设备履历报表页面 | 页面显示设备编码、状态、时间范围筛选项和列表 |
| 2 | 设备编码查询 | 输入有效设备编码并查询 | 表格展示设备履历记录 |
| 3 | 状态筛选 | 选择运行/空闲/异常状态查询 | 表格仅展示匹配状态数据 |
| 4 | 时间范围筛选 | 选择开始结束时间后查询 | 表格展示时间范围内履历 |
| 5 | 分页切换 | 查询出多页数据后切换分页 | 当前页数据刷新,总数正确 |
| 6 | 重置功能 | 点击重置 | 筛选项、表格和分页状态清空 |
| 7 | 空数据 | 输入无匹配条件查询 | 显示空态,不出现脚本错误 |
| 8 | 国际化检查 | 切换中英文语言 | 页面文案随语言切换 |
## 回归关注点
- 接口必须调用 `report/device/log`method 为 `get.device.status.log`
- 时间范围需要拆分为 `start_time``end_time`

View File

@@ -0,0 +1,11 @@
# 设备损耗品寿命管理功能测试任务列表
- [ ] 进入 `设备模型 / 设备损耗品 / 设备损耗品寿命管理`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,11 @@
# 设备损耗品更换日志功能测试任务列表
- [ ] 进入 `设备模型 / 设备损耗品 / 设备损耗品更换日志`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,11 @@
# 设备损耗品类别功能测试任务列表
- [ ] 进入 `设备模型 / 设备损耗品 / 设备损耗品类别`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,11 @@
# 设备损耗品项目功能测试任务列表
- [ ] 进入 `设备模型 / 设备损耗品 / 设备损耗品项目`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,8 @@
# 设备点检日志功能测试任务列表
- [ ] 进入 `设备模型 / 设备点检 / 设备点检日志`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,9 @@
# 设备点检记录功能测试任务列表
- [ ] 进入 `设备模型 / 设备点检 / 设备点检记录`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,10 @@
# 设备点检项目功能测试任务列表
- [ ] 进入 `设备模型 / 设备点检 / 设备点检项目`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,698 @@
# 设备类别功能测试流程文档
> **测试对象**:设备管理 → 设备模型 → 设备类别Equipment Category
> **迁移日期**2026-06-02
> **对应页面**`src/views/equipment-management/equipment-model/equipment-category/index.vue`
> **API 文件**`src/api/equipment-management/equipment-category.js`
> **路由路径**`/device_management/equipment_model/equipment_category`(旧值暂留)
> **i18n 前缀**`page.equipment_management.equipment_model.equipment_category`
---
## 一、测试环境配置
| 配置项 | 要求 |
|--------|------|
| 浏览器 | Chrome 最新版、Edge 最新版(兼容 IE 11+ |
| 屏幕分辨率 | ≥ 1920×1080 |
| Node.js | ≥ 16.x |
| 包管理器 | pnpm ≥ 7.x |
| 后端服务 | 设备类别相关 API 正常运行(`device_management/equipment_model/equipment_category/*` |
| 测试账号 | 具有设备管理 → 设备类别菜单权限的账号(含 create/edit/delete 权限) |
| 测试数据 | 准备至少 5 条测试用设备类别(编码唯一) |
| 语言切换 | 先测中文(简体中文),再切到英文验证 i18n |
| 权限分配 | 系统管理 → 菜单管理中确认设备类别按钮权限(新增、编辑、删除)已正确配置 |
---
## 二、测试前置条件
1. 后端服务Webman已启动`device_management` 模块的 API 可正常访问
2. 前端项目已执行 `pnpm install``pnpm dev` 正常启动,可访问登录页
3. 使用具有「设备管理 → 设备类别」菜单权限的管理员账号登录
4. 侧边栏菜单 **设备管理 → 设备模型** 下可见 **设备类别** 子菜单
5. 浏览器控制台无 Vue 警告或 i18n key 缺失报错
6. 确认 `src/locales/zh-chs.json``src/locales/en.json` 中存在 `page.equipment_management.equipment_model.equipment_category` 配置
7. 数据库中设备类别表为空或仅有少量测试数据,便于验证
---
## 三、功能测试用例
### 3.1 页面加载与数据展示
#### TC-EC-001菜单导航与页面加载
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 登录系统 2. 点击侧边栏菜单「设备管理 → 设备模型 → 设备类别」 |
| **预期结果** | 页面正常加载URL 显示 `/device_management/equipment_model/equipment_category`;页面顶部显示搜索栏(设备类别编码、设备类别名称、查询、重置按钮);中部显示设备类别列表表格;底部分页组件显示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-002列表表格列头与数据展示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看设备类别列表的表头列与各行数据 |
| **预期结果** | 表格列依次为:序号、设备类别编码、设备类别名称、备注、操作;操作列包含「编辑」「删除」两个按钮(带图标);当数据为空时显示空数据占位提示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-003工具栏按钮显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看表格上方的工具栏 |
| **预期结果** | 显示蓝色「新增」按钮(含加号图标),右上角显示问号「帮助」按钮(点击跳转 `/help/equipment-category` |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-004表格自适应高度
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 加载页面后查看表格高度 2. 缩小/放大浏览器窗口 3. 折叠/展开侧边栏 |
| **预期结果** | 表格高度自动填满 d2-container 剩余空间,窗口变化时无空白或滚动条异常 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.2 搜索功能
#### TC-EC-005按编码精确搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「设备类别编码」输入框输入完整的类别编码(如 `EQ_CAT_001` 2. 点击「查询」按钮 |
| **预期结果** | 表格仅显示编码匹配的数据行;分页总数更新为匹配条数;输入框右侧 X 按钮可清空内容 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-006按编码模糊搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「设备类别编码」输入框输入编码的片段(如 `EQ_` 2. 点击「查询」按钮 |
| **预期结果** | 表格显示所有编码包含 `EQ_` 的数据行 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-007按名称搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「设备类别名称」输入框输入关键字(如「自动化」) 2. 点击「查询」按钮 |
| **预期结果** | 表格仅显示名称包含关键字的设备类别 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-008组合条件搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 同时输入「设备类别编码」和「设备类别名称」搜索条件 2. 点击「查询」按钮 |
| **预期结果** | 表格显示同时满足两个条件的数据行AND 关系) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-009回车键触发搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在搜索输入框中输入关键字 2. 按下键盘回车键 |
| **预期结果** | 等同于点击「查询」按钮,表格按搜索条件刷新 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-010重置搜索
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 输入搜索条件并点击「查询」 2. 点击「重置」按钮 |
| **预期结果** | 搜索输入框清空,表格恢复显示全部设备类别数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-011搜索无结果
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 输入不存在的编码或名称 2. 点击「查询」 |
| **预期结果** | 表格显示空数据占位提示,分页总数显示 0 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.3 分页功能
#### TC-EC-012分页默认显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 加载页面后查看分页组件 |
| **预期结果** | 分页默认显示第 1 页,每页 10 条记录,总条数显示当前数据库设备类别总数 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-013切换每页条数
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在分页组件的「每页显示」下拉中切换为 20、50、100 2. 观察表格变化 |
| **预期结果** | 表格按新条数加载数据,分页组件正确显示总页数 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-014翻页功能
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 准备至少 25 条测试数据 2. 点击「下一页」「上一页」「首页」「末页」按钮 3. 输入页码跳转 |
| **预期结果** | 表格按页加载数据,翻页流畅无报错 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.4 新增设备类别
#### TC-EC-015打开新增弹框
| 项目 | 内容 |
|------|------|
| **测试步骤** | 点击表格上方「新增」按钮 |
| **预期结果** | 弹出新增设备类别对话框,标题显示"新增设备类别",包含设备类别编码、设备类别名称、备注三个表单项;「确定」「取消」按钮位于底部 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-016新增表单必填校验
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 不填写任何内容直接点击「确定」 |
| **预期结果** | 设备类别编码、设备类别名称输入框下方显示红色校验提示"请输入设备类别编码"、"请输入设备类别名称" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-017新增成功 - 正常数据
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 输入编码 `EQ_CAT_TEST_001` 3. 输入名称「测试设备类别001」 4. 输入备注「测试用」 5. 点击「确定」 |
| **预期结果** | 弹框关闭,页面右上角显示绿色成功提示"操作成功";表格自动刷新并显示新增的设备类别行 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-018新增成功 - 仅必填
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 仅填写编码和名称,备注留空 3. 点击「确定」 |
| **预期结果** | 新增成功,备注字段允许为空 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-019新增 - 编码长度校验
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 在编码输入框输入超过 100 个字符 3. 失焦后观察 |
| **预期结果** | 输入框下方显示校验提示"长度在 1 到 100 个字符" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-020新增 - 编码重复
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 输入已存在的设备类别编码 3. 点击「确定」 |
| **预期结果** | 提示后端返回的"编码已存在"等错误信息,新增失败 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-021取消新增
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 填写部分内容 3. 点击「取消」按钮 |
| **预期结果** | 弹框关闭,表格数据无变化,无任何提示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-022新增 - 备注多行输入
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 在备注框中输入多行文字(超过 2 行) 3. 观察文本框是否自动扩展 |
| **预期结果** | 备注为 textarea 类型,输入多行内容后自动扩展(最少 2 行,最多 6 行) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.5 编辑设备类别
#### TC-EC-023打开编辑弹框
| 项目 | 内容 |
|------|------|
| **测试步骤** | 点击某一设备类别行操作列的「编辑」按钮 |
| **预期结果** | 弹出编辑设备类别对话框,标题显示"编辑设备类别",设备类别编码、设备类别名称、备注三个字段正确回填该行的数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-024编辑成功
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框 2. 修改设备类别名称为"测试设备类别001-改" 3. 点击「确定」 |
| **预期结果** | 弹框关闭,提示"操作成功",表格对应行的名称列更新为新值 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-025编辑后清空必填项
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框 2. 清空设备类别名称输入框 3. 点击「确定」 |
| **预期结果** | 设备类别名称下方显示红色校验提示,无法提交 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-026取消编辑
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开编辑弹框 2. 修改部分字段 3. 点击「取消」按钮 |
| **预期结果** | 弹框关闭,表格数据不变 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.6 删除设备类别
#### TC-EC-027删除确认弹框
| 项目 | 内容 |
|------|------|
| **测试步骤** | 点击某一设备类别行操作列的「删除」按钮 |
| **预期结果** | 弹出 Element UI 确认提示框,内容为"确定要删除该设备类别吗?",包含「确定」和「取消」按钮,图标为警告三角 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-028删除成功
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 点击「删除」按钮 2. 在确认框中点击「确定」 |
| **预期结果** | 确认框关闭,提示"操作成功",该设备类别从列表中消失,分页总数减 1 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-029取消删除
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 点击「删除」按钮 2. 在确认框中点击「取消」 |
| **预期结果** | 确认框关闭,设备类别数据不变 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-030删除最后一页最后一条
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 翻到最后一页且只剩 1 条数据 2. 删除该数据 3. 观察分页跳转 |
| **预期结果** | 删除成功后自动跳转到新的最后一页,无空白页 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.7 权限控制
#### TC-EC-031无新增权限 - 按钮隐藏
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 登录无新增权限(`/device_management/equipment_model/equipment_category/create`)的账号 2. 进入设备类别页面 |
| **预期结果** | 工具栏「新增」按钮不显示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-032无编辑权限 - 按钮隐藏
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 登录无编辑权限(`/device_management/equipment_model/equipment_category/edit`)的账号 2. 进入设备类别页面 |
| **预期结果** | 行操作列「编辑」按钮不显示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-033无删除权限 - 按钮隐藏
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 登录无删除权限(`/device_management/equipment_model/equipment_category/delete`)的账号 2. 进入设备类别页面 |
| **预期结果** | 行操作列「删除」按钮不显示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-034完全无权限 - 仅可查看
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 登录仅有查看权限的账号 2. 进入设备类别页面 |
| **预期结果** | 表格正常加载数据;工具栏无「新增」按钮;行操作列无「编辑」「删除」按钮 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.8 国际化i18n
#### TC-EC-035简体中文 - 页面显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 切换系统语言为简体中文 2. 进入设备类别页面 |
| **预期结果** | 所有列头、按钮、表单标签、提示信息均显示中文("设备类别编码"、"设备类别名称"、"备注"、"操作"、"新增"、"编辑"、"删除"等) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-036英文 - 页面显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 切换系统语言为 English 2. 进入设备类别页面 |
| **预期结果** | 所有列头、按钮、表单标签、提示信息均显示英文("Equipment Category Code"、"Equipment Category Name"、"Remark"、"Actions"、"Add"、"Edit"、"Delete"等) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-037英文 - 弹框显示
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 切换到英文 2. 点击「新增」按钮 |
| **预期结果** | 弹框标题显示"Add Equipment Category",表单标签显示"Equipment Category Code"、"Equipment Category Name"、"Remark";底部按钮显示"Confirm"、"Cancel" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-038英文 - 删除确认
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 切换到英文 2. 点击某行的「Delete」按钮 |
| **预期结果** | 确认框内容显示"Are you sure to delete this equipment category?",按钮显示"Confirm"、"Cancel" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-039语言切换实时响应
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在中文下打开新增弹框 2. 不关闭弹框,直接切换系统语言到英文 |
| **预期结果** | 弹框内所有文字立即切换为英文,无需刷新页面 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.9 异常与边界场景
#### TC-EC-040网络异常 - 列表加载失败
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 停止后端服务 2. 刷新设备类别页面 |
| **预期结果** | 页面显示 loading 结束后,弹出错误提示(如"请求失败"或"数据请求异常"),表格显示空数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-041网络异常 - 新增失败
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 停止后端服务 3. 填写表单并点击「确定」 |
| **预期结果** | 提示网络错误信息,弹框不关闭,确定按钮恢复可点击 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-042特殊字符输入
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 在设备类别名称中输入特殊字符(如 `!@#$%^&*()_+-=[]{}|;':",./<>?` 3. 点击「确定」 |
| **预期结果** | 后端允许特殊字符时新增成功;不允许时显示后端错误提示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-043超长备注输入
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 在备注中输入超过 500 字符的文本 3. 点击「确定」 |
| **预期结果** | textarea 自动扩展(最多 6 行出现滚动条),新增/编辑成功 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-044备注包含换行符
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增/编辑弹框 2. 在备注中输入多行文字(含回车换行) 3. 提交后再次编辑查看 |
| **预期结果** | 备注正确保存换行符,再次打开编辑时能正确显示多行内容 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-045浏览器刷新页面
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在搜索栏输入条件后查询 2. 按 F5 或点击浏览器刷新按钮 |
| **预期结果** | 页面重新加载,搜索条件清空,表格显示全部数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.10 UI 与交互细节
#### TC-EC-047搜索区 - 标签文本正确
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看搜索区的标签label |
| **预期结果** | 显示"设备类别编码"、"设备类别名称";输入框 placeholder 显示"请输入设备类别编码"、"请输入设备类别名称" |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-048搜索区 - 按钮图标正确
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看搜索区的按钮 |
| **预期结果** | 「查询」按钮为蓝色 primary 样式,左侧带放大镜图标;「重置」按钮为默认样式,左侧带刷新图标 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-049操作列 - 按钮样式
| 项目 | 内容 |
|------|------|
| **测试步骤** | 查看行操作列 |
| **预期结果** | 「编辑」按钮为蓝色文字带编辑图标;「删除」按钮为红色文字带删除图标;按钮间有一定间距;操作列固定在右侧 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-050弹框 - 表单交互
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 观察表单布局 |
| **预期结果** | 表单 label 宽度 110px输入框占 90% 宽度;备注为 textarea可自适应高度2-6 行);所有表单项垂直排列;弹框宽度为 35% |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-051弹框 - 确定按钮 loading
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开新增弹框 2. 填写表单 3. 在网络较慢情况下点击「确定」 |
| **预期结果** | 「确定」按钮显示 loading 状态,无法重复点击;接口返回后自动关闭弹框 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-052空数据占位
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 清空设备类别表(或筛选不存在的条件) 2. 查看表格 |
| **预期结果** | 表格区域显示 Element UI 默认的空数据占位("暂无数据" 或类似提示) |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### 3.11 数据一致性
#### TC-EC-053新增后分页正确
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在有 10 条数据时(每页 10 条) 2. 新增 1 条数据 |
| **预期结果** | 新增后分页总数变为 11自动跳转到第 1 页并显示新数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-054编辑后数据刷新
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 编辑某行数据并保存 2. 重新搜索该数据 |
| **预期结果** | 搜索结果显示编辑后的最新数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
#### TC-EC-055删除后数据不残留
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 删除某条数据 2. 重新搜索该编码或刷新页面 |
| **预期结果** | 搜索结果显示无此数据 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
---
## 四、兼容性测试
### TC-EC-056Chrome 浏览器
| 项目 | 内容 |
|------|------|
| **测试步骤** | 使用 Chrome 最新版执行 TC-EC-001 ~ TC-EC-055 全部用例 |
| **预期结果** | 全部通过 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### TC-EC-057Edge 浏览器
| 项目 | 内容 |
|------|------|
| **测试步骤** | 使用 Edge 最新版执行核心用例 TC-EC-001/015/023/027/035/036 |
| **预期结果** | 全部通过 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### TC-EC-058不同分辨率适配
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 切换浏览器窗口分辨率为 1920×1080、1366×768 2. 验证页面布局 |
| **预期结果** | 表格、分页、弹框等元素无错位,按钮可正常点击 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
---
## 五、回归测试
### TC-EC-059菜单切换不卡顿
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 在「设备类别」页面停留 5 秒 2. 切换到「设备管理」其他子页面 3. 再切回「设备类别」 |
| **预期结果** | 页面切换流畅,无报错,数据正确加载 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
### TC-EC-060浏览器标签页切换
| 项目 | 内容 |
|------|------|
| **测试步骤** | 1. 打开「设备类别」页面 2. 切换到其他浏览器标签页 3. 30 秒后切回 |
| **预期结果** | 页面数据无丢失Token 未过期情况下正常显示 |
| **实际结果** | |
| **测试状态** | ⬜ 通过 / ⬜ 未通过 |
| **问题描述** | |
---
## 六、测试通过标准
| 类别 | 描述 |
|------|------|
| ✅ 全部通过 | 全部测试用例均通过 |
| ⚠️ 部分通过 | 个别非核心用例未通过,但不影响主要功能使用 |
| ❌ 未通过 | 存在阻塞性缺陷(页面无法加载、核心 CRUD 失败、权限绕过等) |
---
## 七、问题记录汇总
| 问题编号 | 关联测试用例 | 问题描述 | 严重程度 | 处理状态 | 处理人 |
|---------|------------|---------|---------|---------|-------|
| | | | | | |
| | | | | | |
---
## 八、测试结论
| 项目 | 内容 |
|------|------|
| **测试人员** | |
| **测试日期** | |
| **测试用例总数** | 60 |
| **通过用例数** | |
| **未通过用例数** | |
| **遗留问题数** | |
| **整体结论** | ⬜ 通过 ⬜ 有条件通过 ⬜ 未通过 |
| **备注说明** | |
---
> **文档维护说明**本测试文档为设备类别功能独立测试文档。后续该功能代码变更Bug 修复、新增功能、需求变更)时,需同步更新本测试文档并重新执行相关测试用例。

View File

@@ -0,0 +1,11 @@
# 设备维修日志功能测试任务列表
- [ ] 进入 `设备模型 / 设备维修 / 设备维修日志`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,11 @@
# 设备维修管理功能测试任务列表
- [ ] 进入 `设备模型 / 设备维修 / 设备维修管理`,页面正常加载,无控制台报错。
- [ ] 点击查询,列表按分页加载数据,表格字段显示完整。
- [ ] 输入关键字后点击查询,列表按条件刷新。
- [ ] 点击重置,查询条件清空并重新加载列表。
- [ ] 点击新增,填写表单并保存,保存成功后列表刷新。
- [ ] 点击编辑,表单带出当前行数据,修改后保存成功。
- [ ] 点击删除,确认后记录删除并刷新列表。
- [ ] 点击导出,系统可创建导出任务或返回成功提示。
- [ ] 分页切换页码和每页条数时,列表数据刷新正常。

View File

@@ -0,0 +1,36 @@
# 鹰眼功能测试任务列表
## 基础入口
- [ ] 进入 `数据中台 / 相关性分析 / 鹰眼`,页面正常加载,无控制台报错。
- [ ] 左侧分析条件区域显示生产批次、工序、NG 码三个筛选项和分析按钮。
- [ ] 页面右侧显示分析详情区域,未查询时为空状态。
## 查询条件
- [ ] 选择生产批次后,工序下拉框自动加载该批次下的不良工序列。
- [ ] 选择工序后NG 码下拉框自动切换为该工序对应的不良代码。
- [ ] 点击重置后批次、工序、NG 码、相关性结果和图表全部清空。
## 相关性分析
- [ ] 未选择生产批次时点击分析,系统提示需要选择批次。
- [ ] 未选择工序时点击分析,系统提示需要选择工序。
- [ ] 选择有效批次、工序和 NG 码后点击分析Pearson 相关性散点图正常渲染。
- [ ] PCC 表格显示工序参数、样本量、相关系数、P 值和相关性判断。
- [ ] 卡方表格显示工序参数、样本量、卡方值、P 值和相关性判断。
- [ ] 有不能参与分析的数据列时,顶部折叠区域展示对应参数名称。
## 图表与交互
- [ ] 散点图鼠标悬停时显示参数名称、相关系数和 P 值。
- [ ] P 值大于 0.05 的记录以蓝色相关状态显示。
- [ ] P 值小于或等于 0.05 的记录以红色不相关状态显示。
- [ ] 已选择 NG 码时点击表格中的相关性文字,弹出分析报告弹窗。
- [ ] 分析报告弹窗内按分类展示折线分布图,关闭后再次打开能正常刷新。
## 兼容性
- [ ] 页面在 1366px 宽度下表格和图表不重叠。
- [ ] 浏览器窗口缩放后图表能自动适配。
- [ ] 切换不同批次再次分析,旧批次结果不会残留。

View File

@@ -0,0 +1,140 @@
# 功能测试流程文档 ——【工艺流程】
> 本文档为【工艺流程】功能补齐后的独立测试文档。测试人员请按以下流程逐步执行,对通过的用例在“通过”列打勾(`[x]`),未通过的用例在“问题记录”列描述具体现象。
| 项目名称 | MES-UI生产主数据 → 工艺模型 → 工艺流程) |
| --- | --- |
| 文档版本 | v1.0 |
| 适用版本 | mes-ui 本次迁移版本 |
| 编写日期 | 2026-06-22 |
| 测试入口 | 菜单:生产主数据 → 工艺模型 → 工艺流程 |
| 关联文件 | `src/views/production-master-data/process-model/process-routing/index.vue``src/views/production-master-data/process-model/process-routing-card/index.vue``src/api/production-master-data/process-routing-card.js``src/api/production-master-data/calculation-script.js` |
---
## 一、测试环境配置要求
| 项 | 要求 |
| --- | --- |
| 后台环境 | Webman 已部署 `production_configuration/technology_model/technology_flow``technology_flow_process``calculation_script` 相关接口 |
| 前端环境 | 使用 Node 18.16.0,执行 `pnpm run serve` 启动 V2 项目 |
| 登录账号 | 拥有工艺流程、流程卡、设定值、结果参数、温度补偿、计算脚本相关权限点 |
| 数据准备 | 至少 1 个流程类别、1 个产品型号、多个工序单元;至少 1 个未绑定批次的工艺流程 |
| 浏览器工具 | 打开 DevTools → Network 与 Console便于核对接口参数和异常 |
---
## 二、测试前置条件
1. 已成功登录系统,侧边栏可进入 **生产主数据 → 工艺模型 → 工艺流程**
2. 工艺流程列表能正常加载,且存在可进入“设置工序”的流程。
3. 测试账号拥有以下权限点:新增、编辑、删除、复制、设置工序、排序、设定值、结果参数、温度补偿、计算脚本、查看日志。
4. 浏览器语言分别切换为简体中文 / English 时页面无 i18n key 缺失。
---
## 三、测试用例
### 3.1 工艺流程主列表
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.1.1 | 进入“工艺流程”菜单 | 列表加载成功,展示编码、名称、流程类别、产品、备注、创建人、创建时间、操作 | | [ ] | |
| 3.1.2 | 按编码、名称、流程类别、产品分别查询 | 请求参数正确,列表按条件刷新 | | [ ] | |
| 3.1.3 | 点击重置 | 查询条件清空,列表恢复第一页 | | [ ] | |
| 3.1.4 | 新增工艺流程并保存 | 调用 `technology_flow/create`,保存成功后列表刷新 | | [ ] | |
| 3.1.5 | 编辑工艺流程 | 表单回显正确,编码禁用,保存后列表更新 | | [ ] | |
| 3.1.6 | 复制工艺流程 | 弹出确认框;确认后调用 `technology_flow/copy` 并刷新列表 | | [ ] | |
| 3.1.7 | 删除未绑定批次流程 | 弹出确认框;确认后调用删除接口并刷新 | | [ ] | |
| 3.1.8 | 删除已绑定批次流程 | 页面提示已绑定批次不可删除,不发删除请求 | | [ ] | |
### 3.2 流程卡工序维护
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.2.1 | 点击列表行“设置工序” | 进入流程卡页面,展示工艺信息和工序明细 | | [ ] | |
| 3.2.2 | 点击“新增”选择工序单元 | 自动生成工序编码/名称,并按工序单元编码自动设置通道检测 | | [ ] | |
| 3.2.3 | 新增工序保存 | 调用 `technology_flow_process/create`,参数包含 `flow_id``workingsubclass_id``code``name``pin_check` | | [ ] | |
| 3.2.4 | 编辑工序 | 工序单元、编码、名称禁用,通道检测可回显;保存调用 `edit` | | [ ] | |
| 3.2.5 | 删除工序 | 调用 `technology_flow_process/delete`,参数包含 `id: []``flow_id` | | [ ] | |
| 3.2.6 | 上移/下移工序 | 调用 `move_up` / `move_down`,排序刷新正确 | | [ ] | |
| 3.2.7 | 已绑定批次流程 | 新增、删除、排序被限制或提示不可操作 | | [ ] | |
### 3.3 设定值
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.3.1 | 点击有 `setting_plugin` 的工序“设定值” | 弹出设定值窗口,显示插件类型、工序编码和现有 JSON | | [ ] | |
| 3.3.2 | 输入合法 JSON 并保存 | 调用 `technology_flow_process/set_setting``setting` 为 JSON 字符串 | | [ ] | |
| 3.3.3 | 输入非法 JSON | 页面提示 JSON 格式不正确,不提交接口 | | [ ] | |
### 3.4 结果参数
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.4.1 | 点击任一工序“结果参数” | 弹窗按当前 `flow_process_id` 调用 `get_optional_params_details` | | [ ] | |
| 3.4.2 | 按名称/参数查询 | 请求包含 `process_id``name``code`,列表刷新 | | [ ] | |
| 3.4.3 | 点击“添加结果参数” | 调用 `get_all_workingsubclass_params`,左侧显示全部参数,右侧显示已选参数 | | [ ] | |
| 3.4.4 | 勾选参数并同步到右侧后提交 | 调用 `add_optional_params``optional_params` 为 JSON 字符串,列表刷新 | | [ ] | |
| 3.4.5 | 未变更直接提交 | 页面提示请选择结果参数,不提交保存 | | [ ] | |
### 3.5 温度补偿
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.5.1 | 对化成/分容类工序点击“温度补偿” | 打开抽屉,调用 `get_step``get_temperature_list` | | [ ] | |
| 3.5.2 | 选择开始/结束工步 | 开始大于结束时出现提示 | | [ ] | |
| 3.5.3 | 新增温度补偿行并保存 | 调用 `create_temperature`,包含 `process_id`、工步范围、`temp_data` | | [ ] | |
| 3.5.4 | 输入非数字温度或补偿值 | 页面提示必须为数字,不提交 | | [ ] | |
| 3.5.5 | 输入重复温度 | 页面提示重复温度,不提交 | | [ ] | |
| 3.5.6 | 下载模板 | 调用 `get_temperature_template`,浏览器下载 xlsx 文件 | | [ ] | |
| 3.5.7 | 导入含“温度 / 温度补偿值”列的 Excel | 数据追加到表格并按温度升序排列 | | [ ] | |
### 3.6 计算脚本
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.6.1 | 点击工序“计算脚本” | 打开弹窗并调用 `calculation_script/all` | | [ ] | |
| 3.6.2 | 新增计算脚本 | 必填编码、名称、接口、接口位置、脚本内容;保存调用 `create` | | [ ] | |
| 3.6.3 | 编辑计算脚本 | 表单和脚本内容回显,保存调用 `edit` | | [ ] | |
| 3.6.4 | 删除计算脚本 | 弹出确认框,确认后调用 `delete` 并刷新列表 | | [ ] | |
| 3.6.5 | 脚本内容为空时保存 | 页面提示请输入脚本内容,不提交 | | [ ] | |
### 3.7 日志、权限与异常
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.7.1 | 点击“查看日志” | 打开日志抽屉并展示 `technology_flow_operate_log` | | [ ] | |
| 3.7.2 | 使用只读账号访问 | 新增/编辑/删除/排序/插件按钮按权限隐藏 | | [ ] | |
| 3.7.3 | 切换英文 | 主列表、流程卡、结果参数、温度补偿、计算脚本文案显示英文 | | [ ] | |
| 3.7.4 | 后端返回 500 或字段缺失 | 页面不白屏Console 无未捕获异常 | | [ ] | |
---
## 四、测试结果汇总
| 用例总数 | 通过 | 失败 | 阻塞 | 通过率 |
| --- | --- | --- | --- | --- |
| | | | | |
---
## 五、问题记录区
| 编号 | 用例编号 | 复现步骤 | 实际结果 | 严重程度 | 处理人 | 状态 | 备注 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | | | | | | | |
| 2 | | | | | | | | |
---
## 六、测试结论
| 项目 | 结论 |
| --- | --- |
| 功能完整性 | ☐ 满足 ☐ 部分缺失 ☐ 不满足 |
| 权限控制 | ☐ 正确 ☐ 存在漏洞 |
| 国际化 | ☐ 完整 ☐ 部分缺失 ☐ 缺失 |
| 是否可发布 | ☐ 是 ☐ 否(请说明阻塞问题) |
测试人员签字__________________ 日期__________

View File

@@ -0,0 +1,210 @@
# 功能测试流程文档 ——【异常不良管理】
> 本文档为【异常不良管理】功能迁移后的独立测试文档。测试人员请按以下流程逐步执行,对通过的用例在"通过"列打勾(`[x]`),未通过的用例在"问题记录"列描述具体现象(包括错误截图编号、操作步骤、实际/预期差异等)。
| 项目名称 | MES-UI生产主数据 → 产品模型 → 异常不良管理) |
| --- | --- |
| 文档版本 | v1.0 |
| 适用版本 | mes-ui 本次迁移版本 |
| 编写日期 | 2026-06-02 |
| 测试入口 | 菜单:生产主数据 → 产品模型 → 异常不良管理 |
| 关联文件 | [主页面](file:///d:/code/mes/mes-ui/src/views/production-master-data/product-model/product-ng-info/index.vue) · [导入组件](file:///d:/code/mes/mes-ui/src/views/production-master-data/product-model/product-ng-info/components/ImportDialog/index.vue) · [API](file:///d:/code/mes/mes-ui/src/api/production-master-data/product-ng-info.js) · [路由](file:///d:/code/mes/mes-ui/src/router/modules/production-master-data.js) · [文件工具](file:///d:/code/mes/mes-ui/src/utils/file.js) |
---
## 一、测试环境配置要求
| 项 | 要求 |
| --- | --- |
| 后台环境 | Webman + 已部署 `production_configuration/product_model/product_ng_info/` 路由接口;数据库中已创建 `product_ng_info``device_category` 数据表 |
| 前端环境 | `npm run serve` / `pnpm run serve` 启动 mes-ui 工程;浏览器推荐 Chrome 110+ |
| 登录账号 | 拥有「生产主数据 / 异常不良管理」菜单访问权限,且分配以下权限点:<br>· `…/product_ng_info/create`(新增 / 导入)<br>· `…/product_ng_info/edit`(编辑)<br>· `…/product_ng_info/delete`(删除 / 批量删除)<br>· `…/product_ng_info/export`(导出) |
| 网络要求 | 前后端网络互通;浏览器可访问 `VUE_APP_API` 环境变量对应域名 |
| 数据准备 | · 至少 3 条设备类别device_category数据<br>· 至少 5 条异常不良类别记录<br>· 准备一份合法格式的 Excel 导入文件(含 3 行导入数据)和一份缺少列的非法文件 |
| 浏览器工具 | 打开 DevToolsF12→ Network 与 Console便于抓取接口与异常 |
| 第三方库 | `xlsx` 已安装Excel 读写支持),确认 `node_modules/xlsx/` 目录存在 |
---
## 二、测试前置条件
1. 已成功登录系统,登录账号具备上述所有权限点。
2. 侧边栏显示 **生产主数据 → 产品模型 → 异常不良管理** 菜单可点击进入。
3. 浏览器语言切换为「简体中文」,界面文字全部为中文,无 `key is not defined` 或英文缺失。
4. 列表默认展示至少 5 条记录(通过 `product_ng_info/list` 接口返回)。
5. 浏览器缩放比例 100%;分辨率建议 1440×900 及以上。
6. DevTools 关闭缓存Network → Disable cache确保加载最新前端资源。
---
## 三、测试用例
> **字段说明**
> - 设备类别 `device_category_id`:必选,从设备类别 API 动态加载
> - 类别 `type`:必选,下拉值「异常(ERR)/不良(NG)」
> - 异常不良编码 `number`:必填,长度 1~100
> - 异常不良名称 `explain`:必填,长度 1~100
> - 备注 `note`:选填,多行文本
> - 列表展示字段:复选框 / 设备类别 / 异常不良类别 / 异常不良编码 / 异常不良名称 / 备注 / 操作
### 3.1 列表展示与加载
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.1.1 | 进入「异常不良管理」菜单 | 列表正常加载,无 JS 报错;表头依次为:复选框、设备类别、异常不良类别、异常不良编码、异常不良名称、备注、操作 | | [ ] | |
| 3.1.2 | 观察列表加载过程 | 列表加载期间显示 loading 遮罩动画,加载完成后消失 | | [ ] | |
| 3.1.3 | 列表为空时(搜索条件无匹配结果) | 表格区域显示空状态占位(如"暂无数据"),无 JavaScript 报错 | | [ ] | |
| 3.1.4 | 分页组件:跳转到第 2 页 | 请求参数 `page_no=2` 正确,数据刷新 | | [ ] | |
| 3.1.5 | 修改每页条数(如从 10 改为 20 | `page_size=20`,列表重载 | | [ ] | |
| 3.1.6 | 列表行内操作列固定在右侧,横向滚动查看 | 操作列不随滚动条消失,固定可见 | | [ ] | |
### 3.2 搜索功能
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.2.1 | 点击「设备类别」下拉框 → 从列表中选择一项 → 点击「查询」 | 列表仅展示所选设备类别的记录 | | [ ] | |
| 3.2.2 | 在「查询类型」下拉框中选择「异常」→ 点击「查询」 | 列表仅展示 `type=ERR` 的记录 | | [ ] | |
| 3.2.3 | 在「查询类型」下拉框中选择「不良」→ 点击「查询」 | 列表仅展示 `type=NG` 的记录 | | [ ] | |
| 3.2.4 | 在「异常不良编码」输入框输入关键字 → 点击「查询」 | 列表仅展示编码包含该关键字的记录 | | [ ] | |
| 3.2.5 | 在「异常不良名称」输入框输入关键字 → 点击「查询」 | 列表仅展示名称包含该关键字的记录 | | [ ] | |
| 3.2.6 | 设备类别 + 类型 + 编码同时填写 → 点击「查询」 | 列表为三条件 AND 过滤结果 | | [ ] | |
| 3.2.7 | 输入查询条件后点击「重置」 | 所有输入框、下拉框恢复初始状态,列表恢复为全量数据 | | [ ] | |
| 3.2.8 | 在搜索输入框中按回车键 | 等同于点击「查询」,触发列表刷新 | | [ ] | |
| 3.2.9 | 设备类别下拉框首次展开时(即 focus 事件) | 自动调用 `/device_category/all` 加载选项;未展开时不再重复请求 | | [ ] | |
### 3.3 新增
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.3.1 | 点击工具栏「新增」按钮 | 弹出标题为「新增异常不良类别」的对话框,表单为空 | | [ ] | |
| 3.3.2 | 新增弹框打开时,设备类别下拉框自动加载可选项 | 设备类别下拉列表有数据,与搜索时的下拉来源一致 | | [ ] | |
| 3.3.3 | 不填任何字段,点击「确定」 | 表单校验:设备类别、类别、编码、名称四个字段下方均红字提示必填 | | [ ] | |
| 3.3.4 | 仅选择设备类别与类别,不填编码 → 点击「确定」 | 仅编码字段提示必填;名称字段提示必填 | | [ ] | |
| 3.3.5 | 编码输入 101 字符 → 点击「确定」 | 编码字段下方提示「长度在1到100个字符」 | | [ ] | |
| 3.3.6 | 名称输入 101 字符 → 点击「确定」 | 名称字段下方提示「长度在1到100个字符」 | | [ ] | |
| 3.3.7 | 正常填写:设备类别=任意、类别=异常、编码=ERR-01、名称=设备宕机、备注=生产设备意外停机 → 点击「确定」 | 弹出"操作成功"提示,对话框自动关闭,列表自动刷新并出现该条记录 | | [ ] | |
| 3.3.8 | 新增弹框点击「取消」或右上角 × | 对话框关闭,列表未新增任何记录 | | [ ] | |
| 3.3.9 | 使用无 `product_ng_info/create` 权限的账号访问 | 工具栏不显示「新增」按钮 | | [ ] | |
| 3.3.10 | 后端返回「编码已存在」业务错误 | 页面友好提示错误原因,弹框不关闭(可修正后重试) | | [ ] | |
### 3.4 编辑
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.4.1 | 列表行点击「编辑」 | 弹出标题为「编辑异常不良类别」的对话框,表单字段回显该行当前数据 | | [ ] | |
| 3.4.2 | 清空编码后「确定」 | 提示编码必填 | | [ ] | |
| 3.4.3 | 修改名称为新值,备注保留为空 → 「确定」 | 操作成功,列表对应行名称更新,备注为空 | | [ ] | |
| 3.4.4 | 修改编码(与已有数据重复)→ 「确定」 | 后端返回重复提示,页面友好显示不崩溃 | | [ ] | |
| 3.4.5 | 编辑对话中点击「取消」 | 对话框关闭,列表数据未变化 | | [ ] | |
| 3.4.6 | 无 `product_ng_info/edit` 权限的账号 | 行内不显示「编辑」按钮 | | [ ] | |
| 3.4.7 | 两个标签页同时打开同一条编辑 → A 保存后 B 再次保存 | 后端返回最新数据的验证结果,不产生脏写 | | [ ] | |
### 3.5 删除(行内删除)
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.5.1 | 列表行点击「删除」 | 弹出确认框,提示「确定要执行该操作吗?」 | | [ ] | |
| 3.5.2 | 确认框点击「取消」 | 关闭确认框,数据未删除 | | [ ] | |
| 3.5.3 | 确认框点击「确定」 | 操作成功,列表自动移除该记录 | | [ ] | |
| 3.5.4 | 删除最后一页唯一一条数据 | 列表自动回退到上一页(或空状态),不出现空白页 | | [ ] | |
| 3.5.5 | 删除已被其他业务引用的记录 | 后端返回业务级错误提示,数据保留,页面不崩溃 | | [ ] | |
| 3.5.6 | 无 `product_ng_info/delete` 权限的账号 | 行内不显示「删除」按钮 | | [ ] | |
| 3.5.7 | 网络断开时点击「删除」 | 提示网络异常,数据未被误删 | | [ ] | |
### 3.6 批量删除
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.6.1 | 不勾选任何复选框,点击「批量删除」 | 提示"请先选择数据" | | [ ] | |
| 3.6.2 | 勾选 2~3 行记录 → 点击「批量删除」 | 弹出确认框「确定要删除所选异常不良类别吗?」 | | [ ] | |
| 3.6.3 | 确认框点击「确定」 | 选中的记录全部从列表消失,操作成功提示 | | [ ] | |
| 3.6.4 | 确认框点击「取消」 | 数据保留,勾选状态保留 | | [ ] | |
| 3.6.5 | 选中的行中包含已被引用的数据 | 后端返回针对性的业务错误提示,未删除任何数据 | | [ ] | |
| 3.6.6 | 勾选全选(表头复选框)→ 批量删除 | 所有可见页数据被选中并删除 | | [ ] | |
### 3.7 Excel 导入
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.7.1 | 点击工具栏「导入」按钮 | 弹出标题为「导入异常不良数据」的对话框,上方显示黄色警告提示 | | [ ] | |
| 3.7.2 | 点击「下载模板」按钮 | 浏览器下载 Excel 文件(文件名为「异常不良数据导入模版.xlsx」内容包含表头 | | [ ] | |
| 3.7.3 | 点击「选择文件」→ 选择非 Excel 文件(如 .txt | 提示"上传文件格式错误" | | [ ] | |
| 3.7.4 | 点击「选择文件」→ 选择列缺失的 Excel缺少"异常不良编码"列) | 提示"文件列缺失: 异常不良编码" | | [ ] | |
| 3.7.5 | 选择合法 Excel 文件(含 3 行数据) | 预览表格展示 3 行数据,列与 Excel 内容一致 | | [ ] | |
| 3.7.6 | 选择合法 Excel 后,再次选择另一个文件 | 上一个文件被替换,预览表格刷新为新文件数据 | | [ ] | |
| 3.7.7 | 预览数据无误后点击「确定」 | 提示"操作成功",弹框关闭,列表刷新,新数据出现在列表中 | | [ ] | |
| 3.7.8 | 未选择文件(预览表格为空)点击「确定」 | 提示"请先导入数据" | | [ ] | |
| 3.7.9 | 导入过程中点击「取消」或关闭弹框 | 操作中断,已读取的预览数据被清空 | | [ ] | |
| 3.7.10 | 无 `product_ng_info/create` 权限的账号 | 工具栏不显示「导入」按钮 | | [ ] | |
| 3.7.11 | 导入的 Excel 中设备类别名称在后端无法匹配 | 后端返回相应错误提示,列表不新增 | | [ ] | |
### 3.8 Excel 导出
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.8.1 | 点击工具栏「导出」按钮 | 弹出确认框「确定要导出当前查询结果吗?」 | | [ ] | |
| 3.8.2 | 确认框点击「取消」 | 提示"操作已取消",未触发任何请求 | | [ ] | |
| 3.8.3 | 确认框点击「确定」 | 提示"创建导出任务成功",自动跳转至任务管理页面 | | [ ] | |
| 3.8.4 | 在查询条件中筛选后再点击「导出」 | 后端收到的请求包含当前搜索条件 `device_category_id` / `type` / `number` / `explain` | | [ ] | |
| 3.8.5 | 无 `product_ng_info/export` 权限的账号 | 工具栏不显示「导出」按钮 | | [ ] | |
### 3.9 权限与国际化
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.9.1 | 切换为仅有「查询」权限的账号 | 仅能查看列表与查询,无新增/编辑/删除/导入/导出按钮 | | [ ] | |
| 3.9.2 | 切换为中文环境 → 英文环境 → 刷新页面 | 表头、按钮、弹框标题、验证提示语全部为英文 | | [ ] | |
| 3.9.3 | 中文下打开新增弹框 → 切换至英文 | 弹框标题、表单 label 立即切换为英文(无需关闭弹框) | | [ ] | |
| 3.9.4 | 英文环境下切换回中文 | 所有文案恢复中文 | | [ ] | |
| 3.9.5 | 英文下执行新增/编辑/导入功能,成功/失败提示 | 提示语为英文,含义正确 | | [ ] | |
### 3.10 异常与边界
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.10.1 | 后端 `/list` 接口返回 500 错误 | 列表显示空状态或错误提示用 Message 弹窗展示,页面不白屏 | | [ ] | |
| 3.10.2 | 后端返回字段缺失(如某行缺少 `device_category` | 缺失字段列显示为空,不抛 JS 异常 | | [ ] | |
| 3.10.3 | 备注字段输入 5000 字符并保存 | 提交成功,列表备注列可滚动展示(建议使用省略号截断) | | [ ] | |
| 3.10.4 | 新增/编辑弹框打开后按 ESC 键 | 弹框关闭,表单状态被重置 | | [ ] | |
| 3.10.5 | 列表横向宽度超过浏览器视口 | 操作列固定在右侧,表格支持横向滚动 | | [ ] | |
| 3.10.6 | DevTools Console 全程监控 | 无 `Vue warn`、无未捕获 Promise 异常、无 i18n key 缺失警告 | | [ ] | |
| 3.10.7 | 快速连续点击「新增」→ 「确定」 | 提交按钮 loading 状态阻止重复提交 | | [ ] | |
| 3.10.8 | 设备类别 API 请求失败时展开搜索下拉 | 下拉框为空,页面不崩溃;重试正常 | | [ ] | |
---
## 四、测试结果汇总
| 用例总数 | 通过 | 失败 | 阻塞 | 通过率 |
| --- | --- | --- | --- | --- |
| | | | | |
---
## 五、问题记录区
| 编号 | 用例编号 | 复现步骤 | 实际结果 | 严重程度 | 处理人 | 状态 | 备注 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | | | | | | | |
| 2 | | | | | | | |
| 3 | | | | | | | |
| 4 | | | | | | | |
| 5 | | | | | | | |
---
## 六、测试结论
| 项目 | 结论 |
| --- | --- |
| 功能完整性 | ☐ 满足 ☐ 部分缺失 ☐ 不满足 |
| 性能表现 | ☐ 良好 ☐ 一般 ☐ 差 |
| 权限控制 | ☐ 正确 ☐ 存在漏洞 |
| 国际化 | ☐ 完整 ☐ 部分缺失 ☐ 缺失 |
| 导入导出 | ☐ 正常 ☐ 部分异常 ☐ 不可用 |
| 是否可发布 | ☐ 是 ☐ 否(请说明阻塞问题) |
测试人员签字__________________ 日期__________
---
*本测试流程文档为【异常不良管理】功能迁移版本专用,请独立归档保存。*

View File

@@ -0,0 +1,153 @@
# 功能测试流程文档 ——【计量单位】
> 本文档为【计量单位】功能迁移后的独立测试文档。测试人员请按以下流程逐步执行,对通过的用例在"通过"列打勾(`[x]`),未通过的用例在"问题记录"列描述具体现象(包括错误截图编号、操作步骤、实际/预期差异等)。
| 项目名称 | MES-UI生产主数据 → 物料模型 → 计量单位) |
| --- | --- |
| 文档版本 | v1.0 |
| 适用版本 | mes-ui 本次迁移版本 |
| 编写日期 | 2026-06-02 |
| 测试入口 | 菜单:生产主数据 → 物料模型 → 计量单位 |
| 关联文件 | [`src/views/production-master-data/material-model/material-unit/index.vue`](file:///d:/code/mes/mes-ui/src/views/production-master-data/material-model/material-unit/index.vue) [`src/api/production-master-data/material-unit.js`](file:///d:/code/mes/mes-ui/src/api/production-master-data/material-unit.js) [`src/router/modules/production-master-data.js`](file:///d:/code/mes/mes-ui/src/router/modules/production-master-data.js) |
---
## 一、测试环境配置要求
| 项 | 要求 |
| --- | --- |
| 后台环境 | Webman + 已部署 `production_configuration/matetial_model/unit` 路由接口;数据库中存在 `unit` 数据表 |
| 前端环境 | `npm run serve` 启动 mes-ui 工程;浏览器推荐 Chrome 110+ |
| 登录账号 | 拥有 `生产主数据 / 计量单位` 菜单访问权限,且分配以下权限点:<br>· `…/unit/create`(新增)<br>· `…/unit/edit`(编辑)<br>· `…/unit/delete`(删除) |
| 网络要求 | 前后端网络互通;浏览器可访问 `VUE_APP_API` 域名 |
| 数据准备 | 至少 1 条已存在的单位数据;至少 1 个物料已引用本表(用于验证删除联动提示) |
| 浏览器工具 | 打开 DevToolsF12→ Network 与 Console方便抓取接口与异常 |
---
## 二、测试前置条件
1. 已成功登录系统,且侧边栏显示 **生产主数据 → 物料模型 → 计量单位** 菜单。
2. 浏览器语言分别切换为「简体中文 / English」时界面文字均能正确翻译`key is not defined` / 英文缺失等情况。
3. 列表默认展示接口 `production_configuration/matetial_model/unit/list` 返回的记录。
4. 浏览器缩放比例为 100%;分辨率建议 1440×900 及以上。
5. DevTools 关闭缓存Network → Disable cache避免旧 JS 资源影响测试。
---
## 三、测试用例
> **字段说明(数据库与表单共用)**
> - 编码 `code`:必填,长度 1~100文本
> - 名称 `name`:必填,长度 1~100文本
> - 备注 `remark`:选填,文本域(多行)
> - 列表展示字段:序号 / 编码 / 名称 / 备注 / 创建时间 / 操作
### 3.1 列表与搜索
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.1.1 | 进入"计量单位"菜单 | 列表正常加载,无报错;表头依次为:序号、单位编码、单位名称、备注、创建时间、操作 | | [ ] | |
| 3.1.2 | 在"单位编码"输入框输入关键字 → 点击「查询」 | 列表仅展示编码包含该关键字的记录 | | [ ] | |
| 3.1.3 | 在"单位名称"输入框输入关键字 → 点击「查询」 | 列表仅展示名称包含该关键字的记录 | | [ ] | |
| 3.1.4 | 编码 + 名称同时输入关键字 → 点击「查询」 | 列表为两条件 AND 过滤结果 | | [ ] | |
| 3.1.5 | 输入查询条件后点击「重置」 | 输入框清空,列表恢复为全量数据 | | [ ] | |
| 3.1.6 | 在搜索输入框按回车键 | 等同于点击「查询」,触发列表刷新 | | [ ] | |
| 3.1.7 | 列表分页:跳转到第 2 页 / 修改每页条数 | 列表请求参数 `page_no` / `page_size` 正确变化,数据正常刷新 | | [ ] | |
| 3.1.8 | 列表为空时(无数据) | 显示空状态占位(如"暂无数据"),不报错 | | [ ] | |
| 3.1.9 | 列表加载中 | 表格区域显示 loading 遮罩 | | [ ] | |
| 3.1.10 | 切换浏览器语言为 English 后刷新 | 表头、操作按钮、占位文字均显示英文 | | [ ] | |
### 3.2 新增
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.2.1 | 点击工具栏「新增」按钮 | 弹出标题为「新增单位」的对话框,显示空表单 | | [ ] | |
| 3.2.2 | 不填任何字段,点击「确定」 | 触发表单校验:「单位编码」「单位名称」下方红字提示必填 | | [ ] | |
| 3.2.3 | 仅填写编码(不填名称),点击「确定」 | 仅名称字段提示必填 | | [ ] | |
| 3.2.4 | 输入 101 字符的编码,点击「确定」 | 提示「长度在 1 到 100 个字符」 | | [ ] | |
| 3.2.5 | 正常填写:编码 `PCS`、名称 `个`、备注 `基本计数单位` → 点击「确定」 | 弹出"操作成功"提示,对话框自动关闭,列表自动刷新并出现该条记录 | | [ ] | |
| 3.2.6 | 必填项后存在前后空格时点击「确定」 | 提交数据带空格(视业务策略决定是否 trim列表正常展示 | | [ ] | |
| 3.2.7 | 新增弹框点击「取消」 | 对话框关闭,未提交任何数据 | | [ ] | |
| 3.2.8 | 新增弹框点击右上角 × | 对话框关闭,未提交任何数据 | | [ ] | |
| 3.2.9 | 在无 `unit/create` 权限的账号下访问 | 工具栏不显示「新增」按钮 | | [ ] | |
| 3.2.10 | 后端返回 `code 已存在` 错误 | 页面提示后端错误信息(如 `code 重复`),不崩溃 | | [ ] | |
### 3.3 编辑
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.3.1 | 在列表行点击「编辑」 | 弹出标题为「编辑单位」的对话框,且表单字段回显当前行数据 | | [ ] | |
| 3.3.2 | 清空编码,点击「确定」 | 提示编码必填 | | [ ] | |
| 3.3.3 | 修改名称为新值,备注保留为空,点击「确定」 | 提示操作成功,列表对应行的名称更新 | | [ ] | |
| 3.3.4 | 修改编码(与已有数据重复),点击「确定」 | 后端返回重复提示,页面友好显示 | | [ ] | |
| 3.3.5 | 编辑过程中点击「取消」 | 对话框关闭,原数据未发生变化 | | [ ] | |
| 3.3.6 | 无 `unit/edit` 权限的账号 | 行内不显示「编辑」按钮 | | [ ] | |
| 3.3.7 | 同时打开两个浏览器标签 A、B均进入编辑 | B 保存后 A 再次保存时数据为 B 已提交后的最新值(避免脏写) | | [ ] | |
### 3.4 删除
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.4.1 | 在列表行点击「删除」 | 弹出确认框,提示「确定要执行该操作吗?」 | | [ ] | |
| 3.4.2 | 确认框点击「取消」 | 关闭确认框,未删除 | | [ ] | |
| 3.4.3 | 确认框点击「确定」 | 提示操作成功,列表自动移除该记录 | | [ ] | |
| 3.4.4 | 删除被物料引用的单位 | 后端返回业务级提示,页面正确展示且不崩溃 | | [ ] | |
| 3.4.5 | 删除最后一页唯一一条记录后 | 列表自动回退到上一页(或显示空状态),无空白页 | | [ ] | |
| 3.4.6 | 无 `unit/delete` 权限的账号 | 行内不显示「删除」按钮 | | [ ] | |
| 3.4.7 | 网络断开时点击「删除」 | 提示网络异常,未误删数据 | | [ ] | |
### 3.5 权限与国际化
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.5.1 | 切换为仅有「查询」权限的账号 | 仅能查看列表与查询,无新增/编辑/删除按钮 | | [ ] | |
| 3.5.2 | 切换语言为 English刷新页面 | 表头、按钮、弹框标题、提示语全部为英文 | | [ ] | |
| 3.5.3 | 在中文下打开新增 → 切换为英文 | 弹框标题、表单 label 立即切换为英文(无需关闭弹框) | | [ ] | |
| 3.5.4 | 切换语言后,校验提示(如"长度在 1 到 100 个字符" | 同步显示对应语言 | | [ ] | |
### 3.6 异常与边界
| 用例编号 | 操作步骤 | 预期结果 | 实际结果 | 通过 | 问题记录 |
| --- | --- | --- | --- | --- | --- |
| 3.6.1 | 后端返回 500 错误 | 列表显示空状态或错误提示,不白屏 | | [ ] | |
| 3.6.2 | 后端返回字段缺失 | 缺失字段列显示为空,不抛 JS 异常 | | [ ] | |
| 3.6.3 | 备注字段输入 5000 字符 | 提交成功,列表中可滚动展示(可截断) | | [ ] | |
| 3.6.4 | 在表单输入过程中按 ESC | 弹框关闭,表单状态重置 | | [ ] | |
| 3.6.5 | 列表行内操作按钮溢出 | 操作列固定在右侧且可滚动查看 | | [ ] | |
| 3.6.6 | DevTools Console 检查 | 全程无 `Vue warn`、未捕获 Promise 异常、key 缺失警告 | | [ ] | |
---
## 四、测试结果汇总
| 用例总数 | 通过 | 失败 | 阻塞 | 通过率 |
| --- | --- | --- | --- | --- |
| | | | | |
---
## 五、问题记录区
| 编号 | 用例编号 | 复现步骤 | 实际结果 | 严重程度 | 处理人 | 状态 | 备注 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | | | | | | | |
| 2 | | | | | | | |
| 3 | | | | | | | |
---
## 六、测试结论
| 项目 | 结论 |
| --- | --- |
| 功能完整性 | ☐ 满足 ☐ 部分缺失 ☐ 不满足 |
| 性能表现 | ☐ 良好 ☐ 一般 ☐ 差 |
| 权限控制 | ☐ 正确 ☐ 存在漏洞 |
| 国际化 | ☐ 完整 ☐ 部分缺失 ☐ 缺失 |
| 是否可发布 | ☐ 是 ☐ 否(请说明阻塞问题) |
测试人员签字__________________ 日期__________
---
*本测试流程文档为【计量单位】功能迁移版本专用,请独立归档保存。*

File diff suppressed because it is too large Load Diff

443
docs/国际化规则.md Normal file
View File

@@ -0,0 +1,443 @@
# i18n 国际化规范文档
> **版本**v1.0
> **适用项目**`mes-ui`
> **语言包文件**`src/locales/zh-chs.json` / `src/locales/en.json` / `src/locales/zh-cht.json` / `src/locales/ja.json`
> **配合使用**`src/composables/useI18n.js``i18nMixin`
---
## 目录
1. [语言包文件规范](#1-语言包文件规范)
2. [Key 命名规范(三层层级)](#2-key-命名规范三层层级)
3. [公共 Key 规范page.common](#3-公共-key-规范pagecommon)
4. [页面中如何使用i18nMixin](#4-页面中如何使用i18nmixin)
5. [常见场景 Key 模板](#5-常见场景-key-模板)
6. [旧项目 Key 迁移对照](#6-旧项目-key-迁移对照)
7. [翻译格式规范](#7-翻译格式规范)
8. [新增页面 Checklist](#8-新增页面-checklist)
---
## 1. 语言包文件规范
### 1.1 文件清单
| 文件 | 语言 | `_element` 值 |
|------|------|--------------|
| `src/locales/zh-chs.json` | 简体中文 | `"zh-CN"` |
| `src/locales/zh-cht.json` | 繁体中文 | `"zh-TW"` |
| `src/locales/en.json` | 英文 | `"en"` |
| `src/locales/ja.json` | 日文 | `"ja"` |
### 1.2 文件格式
- **编码**UTF-8
- **格式**:标准 JSON不允许尾逗号不允许注释
- **顶层结构**
```json
{
"_element": "zh-CN",
"_name": "简体中文",
"page": { ... }
}
```
- `_element`:对应 `element-ui/lib/locale/lang/` 的语言包文件名
- `_name`:语言切换下拉菜单中的显示名
- `page`:所有业务翻译的根节点,之下按模块层级嵌套
### 1.3 维护原则
- 中文和英文文件**必须保持 key 结构完全一致**,不允许一边有 key 而另一边没有
- 新增页面时**中英文同步添加**
- 每次新增后用 `node -e "JSON.parse(require('fs').readFileSync('src/locales/zh-chs.json','utf8'))"` 验证 JSON 合法性
---
## 2. Key 命名规范(三层层级)
### 2.1 核心规则
```
page.{一级模块英文} .{二级模块英文} .{三级模块英文} .{具体key}
└─ snake_case ─┘└─ snake_case ─┘└─ snake_case ─┘
```
**英文来源**[后台Webman界面截图对照表](./后台Webman界面截图对照表.md) 中的英文列。
**格式转换**:对照表英文 → 全小写 + 空格替换为下划线 + `&` 替换为下划线。
### 2.2 对照表 → i18n Key 映射表
| 对照表英文名 | snake_case用于 i18n key | kebab-case用于目录名 |
|-------------|---------------------------|------------------------|
| System Administration | `system_administration` | `system-administration` |
| Production Master Data | `production_master_data` | `production-master-data` |
| Equipment Management | `equipment_management` | `equipment-management` |
| Planning & Production | `planning_production` | `planning-production` |
| Quality Management | `quality_management` | `quality-management` |
| Data Platform | `data_platform` | `data-platform` |
| Factory Model | `factory_model` | `factory-model` |
| Process Model | `process_model` | `process-model` |
| Product Management | `product_management` | `product-management` |
| Material Model | `material_model` | `material-model` |
| SPC Configuration | `spc_configuration` | `spc-configuration` |
| Team Model | `team_model` | `team-model` |
| User Management | `user_management` | `user-management` |
| Menu Management | `menu_management` | `menu-management` |
| System Utilities | `system_utilities` | `system-utilities` |
| System Monitoring | `system_monitoring` | `system-monitoring` |
| Batch Management | `batch_management` | `batch-management` |
| Production Monitoring | `production_monitoring` | `production-monitoring` |
| Process Control | `process_control` | `process-control` |
| Inspection Management | `inspection_management` | `inspection-management` |
| Traceability | `traceability` | `traceability` |
| Production Reports | `production_reports` | `production-reports` |
| Correlation Analysis | `correlation_analysis` | `correlation-analysis` |
| Factory Area | `factory_area` | `factory-area` |
| Production Line | `production_line` | `production-line` |
> **完整映射表**见本文档末尾附录 A。
### 2.3 完整示例
以「生产配置 → 工厂模型 → 工厂区域」页面为例:
```json
{
"page": {
"production_master_data": {
"factory_model": {
"factory_area": {
"search": "查询",
"reset": "重置",
"code": "所区编码",
"name": "所区名称",
"add": "新 增",
"edit": "编 辑",
"delete": "删 除"
}
}
}
}
}
```
对应的 `i18nMixin` 前缀:
```js
mixins: [i18nMixin('page.production_master_data.factory_model.factory_area')]
```
---
## 3. 公共 Key 规范page.common
### 3.1 什么应该放公共
跨页面、跨模块重复出现的文案,提取到 `page.common` 下:
```json
{
"page": {
"common": {
"help": "帮 助",
"confirm": "确定",
"cancel": "取消",
"save": "保存",
"delete": "删除",
"edit": "编辑",
"add": "新增",
"search": "查询",
"reset": "重置",
"operation": "操作",
"tip": "提示",
"confirm_delete": "确定要执行该操作吗?",
"operation_success": "操作成功",
"no_data": "暂无数据",
"loading": "加载中..."
}
}
}
```
### 3.2 已有公共 Key 清单
| key | 中文 | 英文 | 用途 |
|-----|------|------|------|
| `page.common.help` | 帮 助 | Help | 表格工具栏右侧帮助按钮 |
> 后续发现跨页面共用 key 时,持续往 `page.common` 中补充。
### 3.3 如何使用
```vue
<page-table :help-text="$t(ckey('help'))" />
```
`ckey('help')``'page.common.help'`,由 `i18nMixin` 自动注入。
### 3.4 判断标准:该不该放 common
| 情况 | 放哪里 | 示例 |
|------|--------|------|
| 多个一级模块都出现 | `page.common` | 帮助、确定、取消 |
| 只在本模块内出现 | 模块自己的 key | 所区编码、产线编码 |
| 不确定 | 先放在模块内,等第二次出现时提取 | — |
---
## 4. 页面中如何使用i18nMixin
### 4.1 页面 Script 部分
```js
import { i18nMixin } from '@/composables/useI18n'
export default {
mixins: [i18nMixin('page.production_master_data.factory_model.factory_area')],
data () {
return {
// 传入完整 i18n key不在此处翻译由子组件内部 $t() 处理
formCols: [
[{ label: this.key('code'), placeholder: this.key('enter_code') }]
],
rules: {
code: [{ required: true, message: this.key('enter_code'), trigger: 'blur' }]
}
}
},
created () {
this.columns = useTableColumns([
{ prop: 'code', label: this.key('code') }
])
}
}
```
### 4.2 页面 Template 部分
```vue
<template>
<!-- 当前页面翻译 -->
<el-form-item :label="$t(key('code'))">
<el-input :placeholder="$t(key('enter_code'))" />
</el-form-item>
<el-button>{{ $t(key('search')) }}</el-button>
<!-- 公共翻译 -->
<page-table :help-text="$t(ckey('help'))" />
</template>
```
### 4.3 data() 中传参的时机说明
`data()``created` 之前执行,此时 `this` 已经可用。因此:
- **column label / formCols / rules.message**:在 `data()` 中或 `created()` 中用 `this.key()` 传入完整 i18n key
- **翻译由子组件负责**`page-table``page-dialog-form` 内部使用 `$t()` 翻译传入的 key切换语言时自动响应更新
- **不要用 `k()` 提前翻译**`k()` 将 key 翻译成静态字符串,语言切换后不会更新
---
## 5. 常见场景 Key 模板
### 5.1 标准 CRUD 页面(每个页面必有的 key
```json
{
"search": "查询",
"reset": "重置",
"add": "新 增",
"edit": "编 辑",
"delete": "删 除",
"operation": "操作",
"add_title": "新增{模块名}",
"edit_title": "编辑{模块名}",
"operation_success": "操作成功",
"confirm_delete": "确定要执行该操作吗?",
"enter_xxx": "请输入{字段名}",
"select_xxx": "请选择{字段名}"
}
```
### 5.2 列表页字段 Key
```json
{
"sort": "序号",
"code": "{实体}编码",
"name": "{实体}名称",
"remark": "备注"
}
```
### 5.3 表单校验 Key
```json
{
"enter_code": "请输入{实体}编码",
"enter_name": "请输入{实体}名称",
"remark_length": "长度在 1 到 100 个字符",
"validation_fail": "校验失败"
}
```
### 5.4 登录页 Key
```json
{
"username": "用户名",
"password": "密码",
"login": "登录",
"please_enter_username": "请输入用户名",
"please_enter_password": "请输入密码",
"form_validation_failed": "表单校验失败,请检查"
}
```
---
## 6. 旧项目 Key 迁移对照
### 6.1 旧 Key 结构 vs 新 Key 结构
旧项目 key 路径深且命名不统一:
| 旧 key 前缀 | 新 key 前缀 |
|-----------|-----------|
| `page.system_settings.user_management.role` | `page.system_administration.user_management.role` |
| `page.system_settings.user_management.user` | `page.system_administration.user_management.user` |
| `page.system_settings.menu_configuration.menu` | `page.system_administration.menu_management.menu_configuration` |
| `page.system_settings.system_assistant.operate_log` | `page.system_administration.system_utilities.operation_logs` |
| `page.system_settings.system_monitoring.system.login` | `page.system_administration.system_monitoring.login` |
| `page.production_configuration.factory_model.factory_area` | `page.production_master_data.factory_model.factory_area` |
| `page.production_configuration.matetial_model.*` | `page.production_master_data.material_model.*` |
| `page.planning_production.production_batch_management.batch` | `page.planning_production.batch_management.batch_list` |
| `page.data_middleground.basic_traceability.*` | `page.data_platform.traceability.*` |
| `page.warehouse.*` | `page.warehouse.*`(待确定对照表英文名) |
### 6.2 搬迁时的操作步序
1. 确定页面对应的对照表三级模块英文名
2.`page.{一级}.{二级}.{三级}` 组装新 key 前缀
3.`zh-chs.json` 中按三层嵌套创建节点
4.`en.json` 中创建相同结构
5. 将旧 key 的翻译值复制到新 key 下
6. 页面代码中 `i18nMixin` 参数改为新前缀
7. 模板中 `$t('旧key')` 全部改为 `$t(key('新suffix'))`
---
## 7. 翻译格式规范
### 7.1 中文规范
| 场景 | 格式 | 示例 |
|------|------|------|
| 按钮文字 | 字间加空格(两字不加) | `"查询"``"新 增"``"批量删除"` |
| 占位提示 | `请输入{名称}` | `"请输入所区编码"` |
| 校验消息 | 完整句,不加句号 | `"长度在 1 到 100 个字符"` |
| 提示弹框 | 加问号 | `"确定要执行该操作吗?"` |
| 操作成功消息 | 不加"成功"后缀的冗余 | `"操作成功"`(而非"保存成功"、"编辑成功"各自定义) |
### 7.2 英文规范
| 场景 | 格式 | 示例 |
|------|------|------|
| 按钮文字 | 首字母大写 | `"Search"``"Add"``"Edit"` |
| 占位提示 | `Please enter {name}` | `"Please enter area code"` |
| 校验消息 | 完整句 | `"Length should be 1 to 100 characters"` |
| 提示弹框 | 问句 | `"Are you sure to delete?"` |
| 操作成功消息 | 过去式或名词 | `"Operation succeeded"` |
### 7.3 占位符
使用 `{name}` 格式,不使用 `%s` / `{0}`
```json
"please_enter": "请输入{name}"
```
```js
this.$t('please_enter', { name: '所区编码' })
// → "请输入所区编码"
```
---
## 8. 新增页面 Checklist
新增一个 CRUD 页面时,按以下顺序操作:
- [ ] 1. 在 [后台Webman界面截图对照表](./后台Webman界面截图对照表.md) 中找到该页面的三级英文名
- [ ] 2. 确定 i18n key 前缀:`page.{一级snake_case}.{二级snake_case}.{三级snake_case}`
- [ ] 3. 在 `zh-chs.json` 的对应节点下添加本页面全部 key
- [ ] 4. 在 `en.json` 的相同节点下添加对应英文翻译
- [ ] 5. 验证 JSON 合法性:`node -e "JSON.parse(require('fs').readFileSync('src/locales/zh-chs.json','utf8'))"`
- [ ] 6. 页面中使用 `mixins: [i18nMixin('key前缀')]`
- [ ] 7. 模板中用 `$t(key('xxx'))` 替代硬编码文字
- [ ] 8. data() 中用 `this.key('xxx')` 传入完整 i18n key不用 `k()` 提前翻译)
- [ ] 9. 公共文案(帮助、确定、取消等)用 `ckey('xxx')` 引用
- [ ] 10. `pnpm lint` 无报错
---
## 附录 A对照表 → i18n Key 完整映射
### 一级模块
| 对照表英文 | snake_casei18n | kebab-case目录 |
|-----------|-------------------|-------------------|
| System Administration | `system_administration` | `system-administration` |
| Production Master Data | `production_master_data` | `production-master-data` |
| Equipment Management | `equipment_management` | `equipment-management` |
| Planning & Production | `planning_production` | `planning-production` |
| Quality Management | `quality_management` | `quality-management` |
| Data Platform | `data_platform` | `data-platform` |
| Warehouse | `warehouse` | `warehouse` |
| SCADA Management | `scada_management` | `scada-management` |
### 生产配置 → 二级模块
| 二级(对照表) | snake_case | 三级页面数 |
|---------------|-----------|:--:|
| Factory Model | `factory_model` | 2 |
| Process Model | `process_model` | 3 |
| Product Management | `product_management` | 2 |
| Material Model | `material_model` | 4 |
| SPC Configuration | `spc_configuration` | 1 |
| Team Model | `team_model` | 3 |
### 设备模型 → 二级模块
| 二级(对照表) | snake_case |
|---------------|-----------|
| Equipment Category | `equipment_category` |
| Equipment Management | `equipment_management` |
| Inspection Management | `inspection_management` |
| Maintenance Management | `maintenance_management` |
| Repair Management | `repair_management` |
| Consumables Management | `consumables_management` |
### 系统设置 → 二级/三级
| 二级(对照表) | snake_case | 三级 snake_case |
|---------------|-----------|----------------|
| User Management | `user_management` | `role` / `user` |
| Menu Management | `menu_management` | `menu_configuration` |
| System Utilities | `system_utilities` | `operation_logs` / `api_logs` |
| System Monitoring | `system_monitoring` | `monitoring_configuration` |
| Organization | `organization` | `production_team_manage` / `production_shift_management` / `production_shift_calender` |
| OCR | `ocr` | `config` / `log` |
---
## 附录 B当前已实施页面
| 页面 | i18nMixin 前缀 | 语言包节点 |
|------|---------------|----------|
| 工厂区域 | `page.production_master_data.factory_model.factory_area` | `zh-chs.json` / `en.json` ✅ |

View File

@@ -0,0 +1,79 @@
# 工艺流程Process Routing迁移分析方案
## 一、旧代码研读范围
- 旧页面:`/home/james/WEBMAN-VUE-APP-develop/webman-vue-app/src/views/production_configuration/technology_model/technology_flow/process.vue`
- 旧 API`src/api/production_configuration/technology_model/technology_flow.js``technology_flow_process.js``calculation_script.js`
- 旧组件:`components/ProcessPlugin/ResultParam``TemperatureSupp``CalculationScript``components/technology/technology-flow-model.vue`
- V2 页面:`src/views/production-master-data/process-model/process-routing/index.vue``process-routing-card/index.vue`
## 二、旧模块接口清单
| 接口 | 方法 | method 参数 | platform | 主要参数 | 返回数据使用 |
| --- | --- | --- | --- | --- | --- |
| `production_configuration/technology_model/technology_flow/list` | GET | `production_configuration_technology_model_technology_flow_list` | background | `page_no``page_size``code``name``flow_category_id``product_model_id` | 工艺流程主列表 |
| `technology_flow/create` | POST | `production_configuration_technology_model_technology_flow_create` | background | `code``name``flow_category_id``product_model_id``remark` | 新增流程 |
| `technology_flow/edit` | PUT | `production_configuration_technology_model_technology_flow_edit` | background | `id` + 表单字段 | 编辑流程 |
| `technology_flow/delete` | DELETE | `production_configuration_technology_model_technology_flow_delete` | background | `id: []` | 删除流程 |
| `technology_flow/copy` | POST | `production_configuration_technology_model_technology_flow_copy` | background | `id: []` | 复制流程 |
| `technology_flow_process/all` | GET | `production_configuration_technology_model_technology_flow_process_all` | background | `flow_id` | `process``flow_data``is_binding_batch``technology_flow_operate_log` |
| `technology_flow_process/create` | POST | `..._create` | background | `flow_id``workingsubclass_id``code``name``pin_check` | 新增流程工序 |
| `technology_flow_process/edit` | PUT | `..._edit` | background | `id``flow_id`、表单字段 | 编辑流程工序 |
| `technology_flow_process/delete` | DELETE | `..._delete` | background | `id: []``flow_id` | 删除流程工序 |
| `technology_flow_process/move_up` | POST | `..._move_up` | background | `flow_id``move_id``quilt_move_id``move_sort``quilt_move_sort` | 上移排序 |
| `technology_flow_process/move_down` | POST | `..._move_down` | background | 同上 | 下移排序 |
| `technology_flow_process/set_setting` | POST | `..._set_setting` | background | `id``flow_id``setting: JSON.stringify(data)` | 保存设定值插件数据 |
| `technology_flow_process/get_optional_params_details` | GET | `..._get_optional_params_details` | background | `process_id``page_no``page_size``name``code` | 当前流程工序已绑定结果参数 |
| `technology_flow_process/get_all_workingsubclass_params` | GET | `..._get_all_workingsubclass_params` | background | `process_id` | 左右树:全部/已选结果参数 |
| `technology_flow_process/add_optional_params` | POST | `..._add_optional_params` | background | `process_id``optional_params: JSON.stringify(list)` | 保存结果参数绑定 |
| `technology_flow_process/get_step` | GET | `..._get_step` | background | 无 | 温度补偿工步下拉 |
| `technology_flow_process/get_temperature_list` | GET | `..._get_temperature_list` | background | `process_id` | `data``start_work_step_id``end_work_step_id` |
| `technology_flow_process/create_temperature` | POST | `..._create_temperature` | background | `process_id``start_work_step_id``end_work_step_id``temp_data` | 保存温度补偿 |
| `technology_flow_process/get_temperature_template` | POST | `..._get_temperature_template` | background | 无 | blob 模板文件 |
| `calculation_script/all` | GET | `production_configuration_technology_model_calculation_script_all` | background | `process_id` | 当前工序计算脚本列表 |
| `calculation_script/create` | POST | `..._create` | background | `process_id``code``name``interface_code``interface_position``status``remark``calculation_script_content` | 新增脚本 |
| `calculation_script/edit` | PUT | `..._edit` | background | `id` + 新增字段 | 编辑脚本 |
| `calculation_script/delete` | DELETE | `..._delete` | background | `id` | 删除脚本 |
## 三、旧组件清单
| 组件 | 功能 | 关键属性/状态 | 使用场景 |
| --- | --- | --- | --- |
| `SctBaseTable` | 工序明细表格,带上移/下移/操作列插槽 | `columns``data``buttontable``up/down/handle` 插槽 | 流程卡工序列表 |
| `SctBaseDialog` + `SctBaseForm` | 新增/编辑流程工序 | `workingsubclass_id``code``name``pin_check` | 工序新增编辑 |
| `TechnologyFlowModel` | 设定值插件容器 | `type``code``pluginData``rowData``processArr``is_binding_batch` | 依据工序插件类型编辑设定值 |
| `ResultParam` | 查看并绑定流程工序结果参数 | `flow_process_id``workingsubclass_id` | 结果参数弹窗 |
| `TemperatureSupp` | 温度补偿工步范围、补偿值维护、Excel 导入、模板下载 | `flow_process_id` | 化成/分容等工序温度补偿 |
| `CalculationScript` | 计算脚本列表、脚本新增/编辑/删除、接口位置配置 | `flow_process_id` | 流程工序计算脚本配置 |
| 日志抽屉 | 展示 `technology_flow_operate_log` | `nyr_date``week``username``action_name``process_name` | 查看流程卡操作日志 |
## 四、已迁移/本轮补齐内容
| 内容 | 现状 | 本轮处理 |
| --- | --- | --- |
| 工艺流程主表 CRUD/复制 | V2 已实现 | 保留 |
| 流程卡入口 | V2 已实现 | 保留旧路由 `/production_configuration/technology_model/technology_flow/:flow_id/process` |
| 流程卡工序新增/编辑/删除/排序 | V2 已实现 | 保留并修正按钮显示规则 |
| 设定值 | V2 已实现简化 JSON 版本 | 保留,继续使用 `set_setting` |
| 结果参数 | V2 误用工序单元参数组件,缺少 `flow_process_id` 绑定 | 新增流程卡专用 `result-param.vue`,按 `process_id` 查询与绑定 |
| 温度补偿 | V2 仅提示“暂未接入” | 新增 `temperature-compensation.vue`,恢复查询、工步范围、维护、导入和模板下载 |
| 计算脚本 | V2 按钮隐藏,仅提示“暂未接入” | 新增 `calculation-script.vue` 和 API恢复脚本 CRUD |
| 接口封装 | V2 缺少多个旧端点 | 补齐 `process-routing-card.js` 和新增 `calculation-script.js` |
| i18n | V2 缺少插件弹窗文本 | 补齐中英文语言项 |
## 五、迁移优先级与依赖
| 优先级 | 内容 | 依赖 | 原因 |
| --- | --- | --- | --- |
| P0 | 流程卡工序列表、排序、新增编辑删除 | `technology_flow_process/all/create/edit/delete/move_*` | 流程卡核心作业入口 |
| P0 | 结果参数按流程工序绑定 | `get_optional_params_details``get_all_workingsubclass_params``add_optional_params` | 生产下发/报表字段依赖结果参数 |
| P1 | 温度补偿 | `get_step``get_temperature_list``create_temperature``get_temperature_template``xlsx` 工具 | 化成/分容等工序需要温度修正 |
| P1 | 计算脚本 | `calculation_script/all/create/edit/delete` | 工序接口前后置计算依赖 |
| P2 | 设定值插件细分 UI | 旧 `TechnologyFlowModel` 各插件 | 当前 V2 为 JSON 维护,后续可恢复各插件可视化表单 |
| P2 | 日志详情“查看数据” | 操作日志明细接口待确认 | 旧页面仅展示入口文本,实际明细未完整实现 |
## 六、风险与后续建议
- 当前 V2 设定值仍是 JSON 编辑器,不是旧系统按插件类型渲染的专用表单;若业务用户依赖可视化配置,应后续迁移 `SelectionPlugin``FormationPlugin``OcvrPlugin` 等插件。
- 计算脚本编辑器使用文本域替代旧 Ace 包装组件,功能可提交,但代码高亮/格式化体验弱于旧系统。
- 温度补偿 Excel 导入按旧模板中文列名“温度 / 温度补偿值”解析,需要测试真实模板兼容性。

368
docs/布局迁移报告.md Normal file
View File

@@ -0,0 +1,368 @@
# header-aside 布局组件迁移报告
> 迁移日期2026-05-28
> 迁移范围:`src/layout/header-aside/`
> 适用项目MES-UI基于 D2Admin
---
## 一、迁移概览
| 项目 | 迁改前 | 迁改后 |
|------|--------|--------|
| **修改文件数** | — | **14 个** |
| **硬编码中文处数** | **~35 处** | **0 处** |
| **删除死代码** | — | **1 处**pageKeepAliveClean |
| **新增 i18n key** | 0 | **47 个**zh-chs/en/ja/zh-cht 各 47 个) |
| **语言包覆盖** | 仅 zh-chs + en | zh-chs / en / ja / zh-cht 四语言完整覆盖 |
---
## 二、执行逻辑判断结果
### 全部 16 个组件均在新项目中生效,无废弃组件
| 文件 | 状态 | 依赖 | 判断依据 |
|------|------|------|----------|
| `layout.vue` | ✅ 生效 | d2admin store 全模块 | 全局注册组件齐全 |
| `menu-side/index.js` | ✅ 生效 | d2admin/menu, d2-scrollbar | 组件已全局注册 |
| `menu-header/index.js` | ✅ 生效 | d2admin/menu + resize | throttle 正常 |
| `tabs/index.vue` | ✅ 生效 | d2admin/page, sortablejs | sortablejs 已安装 |
| `header-search/index.vue` | ✅ 生效 | 纯 emit | 无额外依赖 |
| `header-user/index.vue` | ✅ 生效 | d2admin/user + account | store 模块存在 |
| `header-fullscreen/index.vue` | ✅ 生效 | d2admin/fullscreen | store 模块存在 |
| `header-theme/index.vue` | ✅ 生效 | d2admin/theme | store 模块存在 |
| `header-theme/list/index.vue` | ✅ 生效 | d2admin/theme | store 模块存在 |
| `header-size/index.vue` | ✅ 生效 | d2admin/size | store 模块存在 |
| `header-color/index.vue` | ✅ 生效 | d2admin/color | store 模块存在 |
| `header-locales/index.vue` | ✅ 生效 | localeMixin | mixin 正常 |
| `header-log/index.vue` | ✅ 生效 | d2admin/log, 路由 log | log 路由存在 |
| `contextmenu/index.vue` | ✅ 生效 | 纯 UI | 无额外依赖 |
| `panel-search/index.vue` | ✅ 生效 | d2admin/search, fuse.js | fuse.js 已安装 |
| `locales/mixin.js` | ✅ 生效 | $i18n | i18n 已初始化 |
---
## 三、各文件改动明细
### 3.1 模板硬编码 → `$t()` (共 11 个文件)
| 文件 | 改动项 | 旧值 | 新值 |
|------|--------|------|------|
| **header-user/index.vue** | 用户问候 | `` `你好 ${info.name}` `` | `$t('page.layout.user.greeting', { name })` |
| | 未登录占位 | `'未登录'` | `$t('page.layout.user.not_logged_in')` |
| | 登出按钮 | `注销` | `$t('page.layout.user.logout')` |
| **header-fullscreen/index.vue** | 全屏 tooltip | `'全屏'` / `'退出全屏'` | `$t('page.layout.fullscreen.enter/exit')` |
| **header-theme/index.vue** | 主题按钮 tooltip | `content="主题"` | `:content="$t('page.layout.theme.title')"` |
| | 弹框标题 | `title="主题"` | `:title="$t('page.layout.theme.title')"` |
| **header-theme/list/index.vue** | 预览列标题 | `label="预览"` | `:label="$t('page.layout.theme.preview')"` |
| | 已激活按钮 | `已激活` | `$t('page.layout.theme.active')` |
| | 使用按钮 | `使用` | `$t('page.common.use')` |
| **header-size/index.vue** | 尺寸选项 | `'默认'/'中'/'小'/'最小'` | `$t('page.layout.size.*')` |
| | 通知标题 | `'提示'` | `$t('page.layout.size.notification_title')` |
| | 通知内容 | 硬编码 HTML | `$t('page.layout.size.notification_message')` |
| **header-log/index.vue** | tooltip 文本 | 模板字符串拼接 | `$t('page.layout.log.tooltip/no_log', {...})` |
| **menu-side/index.js** | 空菜单提示 | `没有侧栏菜单` | `this.$t('page.layout.menu.no_sidebar')` |
| **tabs/index.vue** | Tab 默认名 | `'未命名'` | `$t('page.layout.tabs.unnamed')` |
| | 关闭操作文字 | `关闭左侧/右侧/其它/全部` | `$t('page.layout.tabs.close_*')` |
| | 刷新文字 | `刷新` | `$t('page.layout.tabs.refresh')` |
| | 错误提示 | `'无效的操作'` | `$t('page.layout.tabs.invalid_operation')` |
| **panel-search/index.vue** | 搜索 placeholder | `placeholder="搜索页面"` | `:placeholder="$t('page.layout.search.placeholder')"` |
| | 快捷键提示 | 含 span 的散装文本 | `v-html="$t('page.layout.search.tip', {...})"` |
| **mixin/menu.js** | 临时菜单提示 | `'临时菜单'` | `$t('page.layout.menu.temp_menu')` |
| **libs/util.menu.js** | 菜单 fallback | `'未命名菜单'` | `this.$t('page.layout.menu.unnamed_menu')` |
| **locales/mixin.js** | 语言切换通知 | `'当前语言:...'/'语言变更'` | `$t('page.layout.locales.*')` |
### 3.2 data() → computed() 转换(响应式 i18n
| 文件 | 属性 | 原因 |
|------|------|------|
| **header-size/index.vue** | `options` → `sizeOptions` | 确保语言切换时下拉选项也跟随更新 |
| **tabs/index.vue** | `contextmenuListIndex` | 确保右键菜单 title 切换语言时跟随更新 |
| | `contextmenuList` | 同上 |
### 3.3 删除死代码
| 文件 | 删除项 | 原因 |
|------|--------|------|
| **header-size/index.vue** | `...mapMutations({ pageKeepAliveClean })` | 引入后从未被调用 |
| 同步删除了 `import { mapMutations }` | `mapMutations` 不再需要 | 单一用途,移除了整个 import |
---
## 四、新增 i18n Key 清单
所有 key 位于 `page.layout.*` 命名空间下,四语言同步添加:
```
page.layout.
├── user.greeting / not_logged_in / logout
├── fullscreen.enter / exit
├── theme.title / preview / active
├── size.default / medium / small / mini / notification_title / notification_message
├── log.no_log / tooltip / tooltip_zero
├── menu.no_sidebar / temp_menu / unnamed_menu
├── tabs.unnamed / refresh / close_left / close_right / close_other / close_all / invalid_operation
├── search.placeholder / tip
└── locales.changed / notification_title / preview_warning / preview_doc
```
加上 `page.common.use`,共计 **48 个新 key × 4 语言 = 192 条翻译**。
---
## 五、开发者注意事项
### 5.1 涉及 4 个语言包文件
> ⚠️ 所有修改的语言包 `zh-chs.json / en.json / ja.json / zh-cht.json` 已通过 `JSON.parse()` 验证合法性。
### 5.2 JSX 渲染函数的特殊语法
`menu-side/index.js` 和 `libs/util.menu.js` 使用 JSX 渲染函数,`$t()` 调用语法为 `{ this.$t('...') }`(单花括号),与 `.vue` 模板的 `{{ }}`(双花括号)不同。
### 5.3 `v-html` 使用处
`panel-search/index.vue` 的提示文本包含内联 `<span class="panel-search__key">` 标签,必须使用 `v-html` 绑定。
### 5.4 `data()` → `computed()` 的 Reactivity
`header-size` 和 `tabs` 组件中原来在 `data()` 里的中文文本数组已经移到 `computed`,确保 `$t()` 是响应式的。未来如果要在 `data()` 中放翻译文本,必须使用 computed 或确保使用者是组件内部翻译。
---
## 六、回滚指南
如需回滚任一组件的改动:
1. **布局组件** — `git checkout` 对应的组件文件即可,所有改动互相独立
2. **语言包** — 回滚 `src/locales/*.json`,新增的 `page.layout` 命名空间不影响业务页面
3. **localeMixin** — 回滚 `src/locales/mixin.js`
---
## 七、验证清单
| 验证项 | 方法 |
|--------|------|
| JSON 合法性 | `node -e "JSON.parse(require('fs').readFileSync('src/locales/zh-chs.json','utf8'))"` |
| 全量 JSON | 逐个检查 zh-chs/en/ja/zh-cht已通过 |
| 语言切换 | 打开页面 → 切换中文/English/日本語/繁體中文 → 观察全部 header 文字是否跟随变化 |
| 搜索面板 | `Ctrl+K` 打开搜索面板 → 检查 placeholder + 快捷键提示 |
| 右键 Tab | 右键点击 Tab → 检查菜单文字 |
| 全屏切换 | 鼠标悬停全屏按钮 → 检查 tooltip |
| 主题弹框 | 打开主题弹框 → 检查标题 + "预览"/"已激活"/"使用" |
| 组件尺寸 | 切换组件尺寸 → 检查通知弹框 |
| 用户区 | 检查用户问候语 + 登出按钮 |
---
## 八、菜单 i18n 翻译方案2026-05-28 追加)
### 8.1 问题背景
旧项目中,当用户切换语言(中文 → English侧边栏菜单和顶部一级导航菜单的文字会跟随切换为英文。当前项目迁移后缺少这个能力菜单文字始终为后端返回的单一语言文本。
### 8.2 方案设计
采用**双重保障**机制:
```
┌─ 方案 A$t() 包装(客户端翻译)
语言切换 ──────────┤
└─ 方案 BmenuReload重新拉取后端菜单
```
#### 方案 A渲染层 `$t()` 包装
将菜单渲染节点中的所有 `menu.title` 包裹 `$t()`。
**修改文件**
| 文件 | 改动 |
|------|------|
| `src/layout/header-aside/components/libs/util.menu.js` | `elMenuItem` 和 `elSubmenu` 中 `menu.title` → `this.$t(menu.title)` |
| `src/components/d2-module-index-menu/components/group.vue` | `{{menu.title}}` → `{{ $t(menu.title) }}`2 处) |
| `src/components/d2-module-index-menu/components/item.vue` | `{{menu.title}}` → `{{ $t(menu.title) }}` |
**工作原理**
```
后端返回 title 是 i18n key → $t() 返回对应语言的翻译 ✓
后端返回 title 是纯文本 → $t() 找不到 key返回原文本fallback
```
无需修改后端接口即可兼容两种模式。
#### 方案 B语言切换时重新拉取菜单
在 `src/store/modules/d2admin/modules/menu.js` 新增 `menuReload` action
```js
async menuReload ({ state, dispatch }) {
// 1. 清空 localStorage 缓存
await dispatch('d2admin/db/set', {
dbName: 'database',
path: '$menu.sourceData',
value: [],
user: true
}, { root: true })
state.sourceData = []
// 2. 重新从后端拉取(后端根据当前语言返回对应文本)
await dispatch('sourceDataLoad')
}
```
在 `src/locales/mixin.js` 的 `onChangeLocale` 末尾追加:
```js
this.$store.dispatch('d2admin/menu/menuReload')
```
### 8.3 工作流程
```
用户点击切换语言
├─ this.$i18n.locale = 'en' → 客户端组件重新渲染
│ $t(menu.title) 即时生效 ✓
├─ $store.dispatch('menuReload') → 清缓存 → 调后端
│ getMenuAll() 返回英文菜单
│ menu.install() 重建 header/aside
│ 侧栏 + 顶栏全部更新 ✓
└─ $notify({ title: 'Language Changed' }) → 通知用户
```
> **注意**:如果后端 `getMenuAll()` 接口**不支持**根据语言返回不同内容,方案 B 不会生效,此时仅依赖方案 A`$t()` 包装)。建议后续后端添加多语言菜单数据返回。
### 8.4 修改清单
| 文件 | 操作 | 行数 |
|------|------|------|
| `src/layout/header-aside/components/libs/util.menu.js` | `menu.title` → `this.$t(menu.title)` | 2 处 |
| `src/components/d2-module-index-menu/components/group.vue` | `{{menu.title}}` → `{{ $t(menu.title) }}` | 2 处 |
| `src/components/d2-module-index-menu/components/item.vue` | `{{menu.title}}` → `{{ $t(menu.title) }}` | 1 处 |
| `src/store/modules/d2admin/modules/menu.js` | 新增 `menuReload` action | +15 行 |
| `src/locales/mixin.js` | `onChangeLocale` 末尾追加 `menuReload` | +1 行 |
### 8.5 验证方法
1. 启动项目,确认**当前展示的菜单文字正确**(方案 A 生效)
2. 切换语言,观察侧边栏和顶部导航栏文字是否更新(方案 A + B 双重生效)
3. 如果切换语言后菜单文字不变,检查:
- 后端 `getMenuAll()` 是否支持多语言
- 菜单数据中的 `name` 是否为可翻译的 i18n key 路径
---
## 九、一级模块首页复用方案2026-05-28 追加)
### 9.1 问题背景
旧项目中,每个一级模块(如 `planning_production`)都有一个 `index/index.vue`
```vue
<template>
<d2-container>
<page-navi class="cs-m" v-model="root"/>
</d2-container>
</template>
<script>
export default {
name: 'produce-index',
components: {
PageNavi: () => import('@/layout/header-aside/components/header-navi')
},
data() { return { root: '/planning_production' } }
}
</script>
```
这些文件结构**高度重合**,仅 `root` 值不同。随着模块增多(对照表中约 20+ 个一级模块),需要逐个创建这些文件。
### 9.2 方案:通用 `module-index.vue`
创建一个**共享的路由级组件**,动态读取路由 meta 中的 `root` 来展示模块首页。
**文件**`src/views/system/function/module-index.vue`(已创建)
**核心逻辑**
```vue
<template>
<d2-container class="module-index-page">
<template #header>
<d2-module-index-banner
:title="$t(headerMenu.title)"
:sub-title="$t(headerMenu.title)" />
</template>
<d2-module-index-menu :menu="asideMenu" />
</d2-container>
</template>
<script>
export default {
computed: {
rootPath () { return this.$route.meta.root || this.$route.path },
headerMenu () {
return this.$store.state.d2admin.menu.header.find(
m => m.path === this.rootPath
) || { title: this.rootPath }
},
asideMenu () {
return this.$store.state.d2admin.menu.aside.find(
m => m.path === this.rootPath
) || { children: [] }
}
}
}
</script>
```
### 9.3 使用方式
在路由模块中,为每个一级模块添加一个指向同一组件的空路径路由:
**路由示例**`src/router/modules/production-master-data.js`
```js
export default {
path: '/production_configuration',
component: layoutHeaderAside,
children: (pre => [
// ★ 模块首页 — 所有一级模块共用同一个组件
{
path: '',
name: `${pre}index`,
meta: { ...meta, title: '生产配置', root: '/production_configuration' },
component: _import('system/function/module-index')
},
// 三级模块页面...
{
path: 'factory_model/factory_area',
name: `${pre}factory_model-factory_area`,
meta: { ...meta, cache: true, title: '工厂区域' },
component: _import('production-master-data/factory-model/factory-area')
}
])('production_configuration-')
}
```
### 9.4 对比
| 维度 | 旧方案 | 新方案 |
|------|--------|--------|
| **文件数** | 每个一级模块 1 个 index.vue20+ 个) | 全局共享 1 个 `module-index.vue` |
| **模板代码** | 每个文件 20 行重复代码 | 0 行重复 |
| **root 值** | 硬编码在每个 data() 中 | 路由 `meta.root` 动态读取 |
| **i18n** | 无 | 通过 `$t(menu.title)` 自动翻译 |
| **新增模块** | 创建目录 + 创建 index.vue + 写重复代码 | 仅需添加路由配置行 |
### 9.5 验证方法
1. 访问 `/production_configuration`(不带子路径),应显示"生产配置"模块的二级和三级模块导航
2. 切换语言banner 标题和菜单项应跟随翻译
3. 点击菜单项,正确跳转到对应页面对应的三级模块页面

View File

@@ -0,0 +1,580 @@
# 功能测试文档 — 工艺流程 (Process Routing)
> 模块路径:生产配置 → 工艺模型 → **工艺流程**
> 路由:`/production_configuration/technology_model/technology_flow`
> API BASE`production_configuration/technology_model/technology_flow/`
> i18n 前缀:`page.production_master_data.process_model.process_routing`
> 文档版本v1.0
> 适用代码版本:基于 [process-routing/index.vue](file:///d:/code/mes/mes-ui/src/views/production-master-data/process-model/process-routing/index.vue)
> 测试目标:验证工艺流程页面的列表、查询、新增、编辑、删除、流程卡管理入口等核心操作
---
## 0. 文档使用说明
- 测试人员按顺序执行 **T-XX** 编号的测试用例
- 每个用例的 **预期结果** 描述必须与实际界面/接口响应一致才可标记为通过
- 失败的用例在 **问题描述** 列填写具体错误信息、截图编号、操作环境
- 所有"实际结果"必须如实记录,禁止空填或留白
- 整体测试结论位于文末 **测试总结**
---
## 1. 测试环境配置要求
| 项目 | 要求 |
| --- | --- |
| 操作系统 | Windows 10 / 11 64-bit |
| Node.js | **18.16.0**(与项目 `.node-version` / `package.json#engines` 一致) |
| 包管理器 | **pnpm 10.33.0**(与 `package.json#packageManager` 一致) |
| 浏览器 | Chrome 100+ / Edge 100+ |
| 后端服务 | Webman 后端已启动且数据库已初始化 |
| 数据库 | 工艺流程、流程类别、产品、权限等基础数据已存在 |
| 启动命令 | `pnpm install``pnpm dev`,访问 `http://localhost:8080` |
| 测试账号 | 具备「生产配置-工艺模型-工艺流程」读写权限的账号 |
| 浏览器语言 | 中英文均需验证(默认以中文为准) |
---
## 2. 测试前置条件
1. 已使用具备 `production_configuration/technology_model/technology_flow` 下 create / edit / delete 权限的账号登录
2. **流程类别** 至少存在 1 条数据(否则新增时的「流程类别」下拉为空)
3. **产品列表** 至少存在 1 条数据(否则新增时的「关联产品」下拉为空)
4. 浏览器开发者工具 Network 面板可正常观察接口请求
5. 已确认 `src/locales/zh-chs.json``src/locales/en.json` 中存在 `page.production_master_data.process_model.process_routing` 节点
---
## 3. 测试用例
### 3.1 列表与查询
#### T-01页面正常加载
- **操作步骤**
1. 登录系统
2. 进入「生产配置 → 工艺模型 → 工艺流程」
- **预期结果**
- URL 跳转到 `/production_configuration/technology_model/technology_flow`
- 页面顶部展示搜索区(编码、名称、查询、重置)
- 下方展示表格列:序号 / 工艺流程编码 / 工艺流程名称 / 流程类别 / 关联产品 / 版本 / 状态 / 备注 / 操作
- 工具栏右上角显示帮助按钮,鼠标悬停提示「工艺流程用于设置生产工艺流程并管理流程卡…」
- 控制台无报错
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-02默认分页加载列表
- **操作步骤**
1. 访问工艺流程页面
- **预期结果**
- 列表自动加载(无需手动点击查询)
- 加载时表格显示 loading 遮罩
- 加载完成显示数据行(如有数据)
- 分页组件显示「共 X 条」并按 10 条/页 显示
- 发起请求 `GET production_configuration/technology_model/technology_flow/list?method=production_master_data_process_model_process_routing_list&page_no=1&page_size=10&code=&name=`
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-03按编码精确搜索
- **操作步骤**
1. 在「工艺流程编码」输入框输入已存在的完整编码
2. 点击「查询」按钮
- **预期结果**
- 列表仅展示编码完全匹配的数据行
- 列表刷新到第 1 页
- 接口请求参数 `code=<已输入值>`
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-04按名称模糊搜索
- **操作步骤**
1. 在「工艺流程名称」输入框输入名称片段
2. 点击「查询」按钮
- **预期结果**
- 列表仅展示名称包含该片段的数据行
- 接口请求参数 `name=<已输入值>`
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-05按回车键触发查询
- **操作步骤**
1. 在「工艺流程编码」或「工艺流程名称」输入框聚焦
2. 输入关键字后按键盘 `Enter`
- **预期结果**
- 等同于点击「查询」按钮,触发列表刷新
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-06重置搜索条件
- **操作步骤**
1. 在搜索框输入任意条件并点击「查询」
2. 点击「重置」按钮
- **预期结果**
- 两个搜索输入框被清空
- 列表自动以空条件重新加载
- 页码回到第 1 页
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-07分页切换
- **操作步骤**
1. 准备超过 10 条工艺流程数据
2. 在分页器中切换到第 2 页或修改每页条数
- **预期结果**
- 列表按新页码 / 每页条数重新加载
- 接口请求参数 `page_no` / `page_size` 与界面一致
- 分页总数保持正确
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-08空数据展示
- **操作步骤**
1. 在没有任何工艺流程数据时访问页面,或筛选一个不存在的数据
- **预期结果**
- 表格区域显示 Element UI 空数据占位(无红色错误)
- 分页器显示「共 0 条」
- 不会弹出错误提示
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-09i18n 中文切换
- **操作步骤**
1. 在用户设置中切换语言到「简体中文」
2. 访问工艺流程页面
- **预期结果**
- 所有表头、按钮、提示文本为中文("工艺流程编码"、"新增"、"删除"等)
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-10i18n 英文切换
- **操作步骤**
1. 切换语言到「English」
2. 访问工艺流程页面
- **预期结果**
- 所有表头、按钮、提示文本为英文("Routing Code"、"Add"、"Delete" 等)
- 切换瞬间不需要刷新页面即生效
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
---
### 3.2 新增
#### T-11打开新增弹窗
- **操作步骤**
1. 点击工具栏的「新增」按钮
- **预期结果**
- 弹出标题为「新增工艺流程」的对话框(宽 40%
- 表单为空且编码字段可编辑
- 默认值:版本 = `1.0`、状态 = 启用
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-12新增必填校验 — 编码
- **操作步骤**
1. 打开新增弹窗
2. 编码留空,其它字段填写完整
3. 点击「确定」
- **预期结果**
- 编码输入框下方红色提示「请输入工艺流程编码」
- 接口未发起,弹窗保持打开
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-13新增必填校验 — 名称
- **操作步骤**
1. 打开新增弹窗
2. 名称留空,其它字段填写完整
3. 点击「确定」
- **预期结果**
- 名称输入框下方红色提示「请输入工艺流程名称」
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-14新增必填校验 — 流程类别
- **操作步骤**
1. 打开新增弹窗
2. 不选择「流程类别」
3. 点击「确定」
- **预期结果**
- 流程类别下拉框下方红色提示「请选择流程类别」
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-15新增必填校验 — 版本
- **操作步骤**
1. 打开新增弹窗
2. 清空「版本」(默认 `1.0`
3. 点击「确定」
- **预期结果**
- 版本输入框下方红色提示「请输入版本号」
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-16新增字段长度校验
- **操作步骤**
1. 打开新增弹窗
2. 在「编码」输入超过 100 个字符
3. 点击「确定」
- **预期结果**
- 编码输入框下方红色提示「长度在 1 到 100 个字符」
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-17新增成功
- **操作步骤**
1. 打开新增弹窗
2. 填写完整有效数据:编码、名称、流程类别、关联产品、版本、状态、备注
3. 点击「确定」
- **预期结果**
- 接口请求 `POST production_configuration/technology_model/technology_flow/create` 状态码 200`code=0`
- 页面弹出绿色提示「操作成功」
- 弹窗自动关闭
- 列表自动刷新,新数据展示在表格中
- 页码回到第 1 页
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-18新增重复编码
- **操作步骤**
1. 准备一个已存在的编码
2. 在新增弹窗中输入相同编码
3. 点击「确定」
- **预期结果**
- 后端返回业务错误
- 页面弹出红色错误提示(如「编码已存在」)
- 弹窗保持打开,用户可修改后重试
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-19取消新增
- **操作步骤**
1. 打开新增弹窗,填写部分数据
2. 点击「取消」按钮或右上角 X
- **预期结果**
- 弹窗关闭
- 不发起任何接口请求
- 再次打开新增弹窗,表单恢复为空(默认值除外)
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-20新增提交中重复点击防护
- **操作步骤**
1. 打开新增弹窗,填写有效数据
2. 连续快速点击「确定」两次
- **预期结果**
- 第一次点击后按钮进入 loading 状态,禁用重复提交
- 接口仅被调用 1 次
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
---
### 3.3 编辑
#### T-21打开编辑弹窗
- **操作步骤**
1. 在列表中点击某行的「编辑」按钮
- **预期结果**
- 弹出标题为「编辑工艺流程」的对话框
- 表单自动回填该行数据
- 「编码」字段为禁用状态(不可编辑)
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-22编辑必填校验
- **操作步骤**
1. 打开编辑弹窗
2. 清空「名称」
3. 点击「确定」
- **预期结果**
- 名称输入框下方红色提示「请输入工艺流程名称」
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-23编辑成功
- **操作步骤**
1. 打开编辑弹窗
2. 修改名称、流程类别、版本、状态、备注等字段
3. 点击「确定」
- **预期结果**
- 接口请求 `PUT production_configuration/technology_model/technology_flow/edit` 状态码 200`code=0`
- 页面弹出绿色提示「操作成功」
- 弹窗关闭
- 列表自动刷新,目标行显示新值
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-24编辑时编码不可修改
- **操作步骤**
1. 打开编辑弹窗
2. 尝试修改「编码」字段
- **预期结果**
- 编码字段处于禁用状态,无法输入
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-25取消编辑
- **操作步骤**
1. 打开编辑弹窗,修改若干字段
2. 点击「取消」按钮
- **预期结果**
- 弹窗关闭
- 不发起任何接口请求
- 列表数据保持原样
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
---
### 3.4 删除
#### T-26删除二次确认弹窗
- **操作步骤**
1. 点击某行的「删除」按钮
- **预期结果**
- 弹出警告提示「确定要删除该工艺流程吗?」
- 提示框有「确定」与「取消」两个按钮
- 列表中的该行仍存在
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-27删除 — 取消
- **操作步骤**
1. 点击「删除」按钮
2. 在确认弹窗中点击「取消」
- **预期结果**
- 弹窗关闭
- 不发起删除接口
- 数据行保持原样
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-28删除成功
- **操作步骤**
1. 点击「删除」按钮
2. 在确认弹窗中点击「确定」
- **预期结果**
- 接口请求 `DELETE production_configuration/technology_model/technology_flow/delete` 状态码 200`code=0`
- 页面弹出绿色提示「操作成功」
- 列表自动刷新,目标行消失
- 删除当前页最后一行时,自动跳转到合理页码
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-29删除 — 关联数据拒绝
- **操作步骤**
1. 准备一条已被产品、批次或其它模块引用的工艺流程
2. 尝试删除
- **预期结果**
- 后端返回业务错误
- 页面弹出红色错误提示(如「该工艺流程已被引用,不可删除」)
- 列表数据保持原样
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
---
### 3.5 流程卡管理入口
#### T-30流程卡管理按钮存在
- **操作步骤**
1. 在列表中查看任意一行的操作列
- **预期结果**
- 操作列包含「编辑」、「流程卡管理」、「删除」3 个按钮
- 「流程卡管理」按钮为黄色文字 + `el-icon-tickets` 图标
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-31点击流程卡管理
- **操作步骤**
1. 点击某行的「流程卡管理」按钮
- **预期结果**
- 当前阶段:弹出信息提示「流程卡管理: <工艺流程名称>」(占位实现)
- 后续阶段:应打开独立的流程卡管理抽屉 / 弹窗
- 不影响列表状态
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
---
### 3.6 权限控制
#### T-32无「新增」权限
- **操作步骤**
1. 使用无 `/production_configuration/technology_model/technology_flow/create` 权限的账号登录
2. 访问工艺流程页面
- **预期结果**
- 工具栏不显示「新增」按钮
- 列表正常加载
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-33无「编辑」权限
- **操作步骤**
1. 使用无 `…/edit` 权限的账号登录
2. 访问工艺流程页面
- **预期结果**
- 行内「编辑」按钮不显示
- 「新增」与「删除」按钮仍可正常显示(按权限配置)
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-34无「删除」权限
- **操作步骤**
1. 使用无 `…/delete` 权限的账号登录
2. 访问工艺流程页面
- **预期结果**
- 行内「删除」按钮不显示
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-35未登录访问
- **操作步骤**
1. 退出登录后,直接在地址栏访问 `/production_configuration/technology_model/technology_flow`
- **预期结果**
- 自动跳转到登录页
- 不会出现 404 或白屏
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
---
### 3.7 错误处理
#### T-36网络异常
- **操作步骤**
1. 在浏览器开发者工具 Network 面板中离线Offline
2. 刷新工艺流程页面
- **预期结果**
- 页面顶部红色错误提示(如「请求超时」或「网络异常」)
- loading 状态关闭
- 表格维持之前的数据或显示空数据
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-37后端 500 错误
- **操作步骤**
1. 模拟后端列表接口返回 500
2. 刷新工艺流程页面
- **预期结果**
- 拦截器统一弹出红色错误提示
- 表格显示空数据
- 控制台无未捕获异常
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
#### T-38参数缺失
- **操作步骤**
1. 模拟后端创建接口缺参返回 `code=500`
2. 在新增弹窗点击「确定」
- **预期结果**
- 拦截器弹出后端返回的错误信息
- 弹窗不关闭
- 表单数据保持原样
- **实际结果**__________
- **测试状态**:☐ 通过 ☐ 失败
- **问题描述**__________
---
## 4. 测试总结
| 维度 | 统计 |
| --- | --- |
| 用例总数 | 38 |
| 通过数 | __________ |
| 失败数 | __________ |
| 阻塞数 | __________ |
| 跳过数 | __________ |
| 整体结论 | ☐ 通过 ☐ 有条件通过 ☐ 不通过 |
### 4.1 遗留问题清单
| 编号 | 用例编号 | 严重程度 | 描述 | 负责人 | 计划修复日期 |
| --- | --- | --- | --- | --- | --- |
| 1 | | | | | |
| 2 | | | | | |
| 3 | | | | | |
### 4.2 测试执行信息
- **测试执行人**__________
- **测试起止时间**__________
- **测试环境版本**Node `18.16.0` / pnpm `10.33.0` / 浏览器 `__________`
- **后端版本 / 提交**__________
- **测试账号**__________
---
## 5. 附录
### 5.1 关键文件
| 类型 | 路径 |
| --- | --- |
| 主页面 | [process-routing/index.vue](file:///d:/code/mes/mes-ui/src/views/production-master-data/process-model/process-routing/index.vue) |
| API 文件 | [process-routing.js](file:///d:/code/mes/mes-ui/src/api/production-master-data/process-routing.js) |
| 路由模块 | [production-master-data.js](file:///d:/code/mes/mes-ui/src/router/modules/production-master-data.js) |
| 中文语言包 | [zh-chs.json#process_routing](file:///d:/code/mes/mes-ui/src/locales/zh-chs.json) |
| 英文语言包 | [en.json#process_routing](file:///d:/code/mes/mes-ui/src/locales/en.json) |
### 5.2 关键接口
| 操作 | Method | URL |
| --- | --- | --- |
| 查询列表 | GET | `production_configuration/technology_model/technology_flow/list` |
| 新增 | POST | `production_configuration/technology_model/technology_flow/create` |
| 编辑 | PUT | `production_configuration/technology_model/technology_flow/edit` |
| 删除 | DELETE | `production_configuration/technology_model/technology_flow/delete` |
公共参数:`method=production_master_data_process_model_process_routing_<action>``platform=background`
### 5.3 字段说明
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| code | string | 是 | 工艺流程编码,唯一,创建后不可修改 |
| name | string | 是 | 工艺流程名称 |
| category_id | int | 是 | 流程类别 ID关联工艺流程类别 |
| product_id | int | 否 | 关联产品 ID关联产品列表 |
| version | string | 是 | 版本号,默认 `1.0` |
| status | int | 是 | 1=启用0=禁用 |
| remark | string | 否 | 备注 |

439
docs/登录页迁移.md Normal file
View File

@@ -0,0 +1,439 @@
# 登录页面搬迁文档
> **搬迁源**`D:\code\company\SCTMES_MES_V5\vue-app`
> **搬迁目标**`d:\code\mes\mes-ui`
> **状态**:✅ 已完成2026-05-26
---
## 一、文件清单与依赖关系
```
登录页面 index.vue
├── ① 页面自身
├── ② 依赖的 Store 模块
├── ③ 依赖的 API 文件
├── ④ 依赖的静态资源(图片)
├── ⑤ 依赖的 i18n 语言包
├── ⑥ 依赖的 CSS 公共样式(% placeholder
├── ⑦ 依赖的工具库
└── ⑧ 路由中已有框架(无需搬迁本文件)
```
---
## 二、需要搬迁的文件
### 2.1 页面核心文件
| 文件 | 旧路径 | 新目标路径 | 说明 |
|------|--------|-----------|------|
| 登录页面 | `src/views/system_settings/system_monitoring/system/login/index.vue` | **覆盖** `src/views/system/login/index.vue` | 新项目已有一个简易占位页面,需用旧项目的完整页面替换 |
> 旧路径嵌套很深:`system_settings/system_monitoring/system/login/`。
> 新项目按对照表命名为简化的 `system/login/`,保持一致的命名风格。
---
### 2.2 Store 模块Vuex
| 文件 | 旧路径 | 新目标路径 | 说明 |
|------|--------|-----------|------|
| account | `src/store/modules/d2admin/modules/account.js` | `src/store/modules/d2admin/modules/account.js` | **核心**:含 `login``logout` action |
| user | `src/store/modules/d2admin/modules/user.js` | `src/store/modules/d2admin/modules/user.js` | account.login 中调用 `d2admin/user/set`**新项目已存在** |
> `account.js` 的 `login` action 依赖链:
> `login()` → `loginAdminUser()` API → 写 cookie(token/uuid) → `dispatch(d2admin/user/set)` → `dispatch(load)`
> `load()` → 依次加载 user/theme/transition/page/menu/size/color
**account.js 依赖的其它模块(新项目已存在,不需搬迁)**
| 模块 | 路径 | 状态 |
|------|------|:--:|
| user | `src/store/modules/d2admin/modules/user.js` | ✅ 已有 |
| theme | `src/store/modules/d2admin/modules/theme.js` | ✅ 已有 |
| transition | `src/store/modules/d2admin/modules/transition.js` | ✅ 已有 |
| page | `src/store/modules/d2admin/modules/page.js` | ✅ 已有 |
| menu | `src/store/modules/d2admin/modules/menu.js` | ✅ 已有 |
| size | `src/store/modules/d2admin/modules/size.js` | ✅ 已有 |
| color | `src/store/modules/d2admin/modules/color.js` | ✅ 已有 |
| db | `src/store/modules/d2admin/modules/db.js` | ✅ 已有 |
---
### 2.3 API 文件
| 文件 | 旧路径 | 新目标路径 | 说明 |
|------|--------|-----------|------|
| 登录/注销 API | `src/api/login.js` | `src/api/auth.js` | 含 `loginAdminUser()``logoutAdminUser()` |
> 注意:旧项目 `login.js` 中 import 了 `@/plugin/axios/request`,这是旧项目的 axios 封装。
> 新项目使用 `@/api/_service` 中的 `request`,搬迁时需替换 import 路径。
---
### 2.4 静态资源(图片)
| 文件 | 旧路径 | 新目标路径 | 说明 |
|------|--------|-----------|------|
| 登录页 Logo | `public/image/logo/sc_logo.png` | `public/image/logo/sc_logo.png` | 登录表单上方的 Logo |
> 旧项目 `public/image/logo/` 目录下共有 9 个文件,但登录页面只用 `sc_logo.png`。
> 根据需要可按需搬其他 logo 文件。新项目原有 `src/views/system/login/image/logo@2x.png`,搬迁后可删除。
---
### 2.5 i18n 语言包
**i18n key 前缀**`page.system_administration.system_monitoring.login`
| key | 中文 | 英文 |
|-----|------|------|
| `time_is_most_precious` | 时间是一切财富中最宝贵的财富 | Time is the most precious of all wealth |
| `username` | 用户名 | Username |
| `password` | 密码 | Password |
| `login` | 登录 | Login |
| `quick_select_user` | 快速选择用户 | Quick Select User |
| `please_enter_username` | 请输入用户名 | Please enter username |
| `please_enter_password` | 请输入密码 | Please enter password |
| `please_enter_code` | 请输入验证码 | Please enter captcha |
| `dev_version` | 开发版本 | Development Version |
| `test_version` | 测试版本 | Test Version |
| `form_validation_failed` | 表单校验失败,请检查 | Form validation failed |
**搬迁操作**
1.`src/locales/zh-chs.json``page.system_administration.system_monitoring` 下新增:
```json
"login": {
"time_is_most_precious": "时间是一切财富中最宝贵的财富",
"username": "用户名",
"password": "密码",
"login": "登录",
"please_enter_username": "请输入用户名",
"please_enter_password": "请输入密码",
"dev_version": "开发版本",
"test_version": "测试版本",
"form_validation_failed": "表单校验失败,请检查"
}
```
2.`src/locales/en.json` 中对应添加英文翻译。
---
### 2.6 CSS 公共样式(依赖但不在页面内)
页面中使用了 SCSS 的 `%placeholder` 选择器:
| placeholder | 作用 | 定义位置 |
|-------------|------|---------|
| `%unable-select` | 禁止用户选中 + 鼠标变手形 | `src/assets/style/public.scss` |
| `%full` | 绝对定位填满父元素 | `src/assets/style/public.scss` |
| `%flex-center-col` | flex 垂直水平居中 | `src/assets/style/public.scss` |
| `$color-text-normal` | 文字颜色变量 | `src/assets/style/unit/color.scss` |
| `$color-primary` | 主色变量 | `src/assets/style/unit/color.scss` |
| `$color-bg` | 背景色变量 | `src/assets/style/unit/color.scss` |
> ✅ 这些在新项目中已存在(通过 `additionalData` 全局注入),不需要额外搬迁。
---
### 2.7 工具/插件依赖(新项目已有,不需搬迁)
| 依赖 | 旧路径 | 新项目状态 |
|------|--------|:--:|
| `util.cookies` | `src/libs/util.cookies.js``src/libs/util.js` | ✅ 已有 |
| `localeMixin` | `src/locales/mixin.js` | ✅ 已有 |
| `dayjs` | npm 包 | ✅ 已有(`package.json` 中) |
| `$baseUrl` | `Vue.prototype.$baseUrl = process.env.BASE_URL` | ✅ 已在 `plugin/d2admin/index.js` 注册 |
| `vuex` `mapActions` | npm 包 | ✅ 已有 |
---
### 2.8 路由(新项目已配置,不需搬迁)
旧路由:
```js
{
path: '/login',
name: 'login',
component: _import('system_settings/system_monitoring/system/login')
}
```
新项目路由已在 `routes.js``frameOut` 中配置:
```js
{
path: '/login',
name: 'login',
component: _import('system/login')
}
```
> ✅ 新路由已指向 `system/login`,对应的 `src/views/system/login/index.vue` 需要替换为旧页面内容。
---
## 三、搬迁执行步骤
| 步骤 | 操作 | 文件 |
|:--:|------|------|
| 1 | 拷贝登录 API替换 import 为 `@/api/_service` | `src/api/login.js``src/api/auth.js` |
| 2 | 拷贝 account Store替换 API 引用路径) | `src/store/modules/d2admin/modules/account.js` |
| 3 | 拷贝 Logo 图片 | `public/image/logo/sc_logo.png` |
| 4 | 更新登录页面(替换 import 路径 + i18n key + logo 路径) | `src/views/system/login/index.vue` |
| 5 | 添加 i18n 语言包 | `src/locales/zh-chs.json` / `en.json` |
| 6 | 验证:`pnpm serve` 启动 → 访问 `/login` 测试登录流程 |
---
## 四、页面中需要修改的内容
登录页面 `index.vue` 从旧项目拷贝后,需改以下几处:
### 4.1 import 路径修正
```diff
- import { mapActions } from 'vuex'
- import util from '@/libs/util'
- import localeMixin from '@/locales/mixin.js'
+ // 这些在新项目中路径一致,无需修改
+ // util.cookies、localeMixin、mapActions 均同上
```
> 注意:旧页面 mixins 中引用了 `localeMixin`(切换语言),新项目中此 mixin 在 `src/locales/mixin.js` 已存在,不需动。
### 4.2 Logo 图片路径
```diff
- <img class="page-login--logo" :src="`${$baseUrl}image/logo/sc_logo.png`">
+ <img class="page-login--logo" src="/image/logo/sc_logo.png">
```
> 新项目中 `$baseUrl` 同样已注册,两种写法均可。建议用绝对路径 `/image/logo/sc_logo.png` 更直观。
### 4.3 i18n key 修正
旧页面使用的 key 前缀为 `page.system_settings.system_monitoring.system.login.xxx`,在新项目中统一简化为 `page.system.login.xxx`,或按新项目目录结构调整。
建议调整为更简洁的 key
| 旧 key太长 | 新 key建议 |
|---------------|---------------|
| `page.system_settings.system_monitoring.system.login.username` | `page.system.login.username` |
| `page.system_settings.system_monitoring.system.login.password` | `page.system.login.password` |
---
## 五、不涉及的依赖(记录说明)
| 依赖 | 原因 |
|------|------|
| `@/libs/websocket.js` | 登录页面本身不 import websocket`account.js``logout` action 中引用。新项目如不需 websocket注释掉即可 |
| `@/api/modules/sys.user.api.js` | 旧 `account.login` 只调 `login.js` API不涉及此文件 |
| `public/image/logo/` 其他 png | 登录页只用 `sc_logo.png`,其余 logo 按需搬迁 |
---
## 登录流程完整流程图
### 正向流程:用户登录
```mermaid
sequenceDiagram
participant User as 用户
participant LoginPage as Login 页面
participant VUEX as Store account
participant API as 后端 POST /login
participant Cookie as Cookie
participant Router as router.beforeEach
participant Home as 首页
User->>LoginPage: 输入用户名密码,点击登录
LoginPage->>LoginPage: el-form.validate 校验表单
alt 校验失败
LoginPage-->>User: message.error 表单校验失败
else 校验通过
LoginPage->>VUEX: dispatch login { username, password }
VUEX->>API: loginAdminUser
alt 登录失败 401 或密码错误
API-->>VUEX: throw Error
VUEX->>VUEX: remove token 和 uuid
VUEX-->>LoginPage: Promise rejected
LoginPage-->>User: message.error
else 登录成功
API-->>VUEX: token 和 userInfo
VUEX->>Cookie: 写入 token / uuid 有效期365天
VUEX->>VUEX: localStorage.setItem user_id
VUEX->>VUEX: dispatch user/set
VUEX->>VUEX: dispatch load 加载持久化配置
Note over VUEX: load按序加载: user theme transition page menu size color sourceData
VUEX-->>LoginPage: Promise resolved
LoginPage->>Router: router.replace redirect or /
Router->>Router: beforeEach 检查 token
Router-->>Home: 鉴权通过,跳转目标页
end
end
```
### 反向流程:用户注销
```mermaid
sequenceDiagram
participant User as 用户
participant Header as 顶栏用户菜单
participant VUEX as Store account
participant API as 后端 POST /logout
participant Cookie as Cookie
participant WS as WebSocket
participant LoginPage as Login 页面
User->>Header: 点击注销
Header->>VUEX: dispatch logout { confirm: true }
VUEX->>User: confirm 确定要注销吗
alt 取消
User-->>VUEX: 取消
else 确认
VUEX->>VUEX: Loading 遮罩
VUEX->>WS: closeSock 断开 WebSocket
VUEX->>API: logoutAdminUser
API-->>VUEX: 服务端清除 session
VUEX->>VUEX: dispatch db/set 清空 sourceData
VUEX->>VUEX: dispatch user/set 清空用户信息
VUEX->>Cookie: remove token / uuid / set block true
VUEX->>VUEX: Loading 关闭
VUEX->>LoginPage: router.push { name: login }
LoginPage-->>User: 返回登录页面
end
```
### 路由守卫鉴权流程(分三种情况)
#### 情况 A无 Token → 跳转登录页
```mermaid
flowchart TD
A["用户访问 URL"] --> B{"路由需要 auth?"}
B -->|是| C["Cookie.get(token)"]
C -->|"token 为空"| D["重定向到 /login?redirect=原地址"]
D --> E["用户在登录页输入账号密码"]
E --> F["登录成功"]
F --> G["router.replace 回到目标页"]
G --> H["进入首页"]
```
#### 情况 B有 Token → 恢复会话
```mermaid
flowchart TD
A["用户访问 URLCookie 中已有 token"] --> B{"路由需要 auth?"}
B -->|是| C["Cookie.get(token)"]
C -->|"token 有效"| D["next 放行"]
D --> E["框架渲染 header-aside 布局"]
E --> F["d2admin/page/isLoaded"]
F --> G["d2admin/size/isLoaded"]
G --> H["页面正常加载"]
style C fill:#f9f,stroke:#333
style D fill:#9f9,stroke:#333
style H fill:#9f9,stroke:#333
```
#### 情况 CToken 有效但后端已过期 → API 层拦截
```mermaid
flowchart TD
A["页面加载后调用业务 API"] --> B["axios 请求携带 Authorization header"]
B --> C{"后端 code === 401?"}
C -->|否| D["正常返回数据"]
C -->|"是 401"| E["axios 响应拦截器 catch 401"]
E --> F["清除 Cookie(token / uuid)"]
F --> G["Message.error 请重新登录"]
G --> H["router.push /login"]
style C fill:#f96,stroke:#333
style H fill:#f96,stroke:#333
```
### 已有 Token 时的完整恢复时序
```mermaid
sequenceDiagram
participant User as 用户
participant Browser as 浏览器
participant Router as router.beforeEach
participant Cookie as Cookie
participant Store as Vuex Store
participant DB as Local DB lowdb
participant Layout as Layout
participant Page as 目标页面
User->>Browser: 打开网页
Browser->>Router: beforeEnter 触发
Router->>Store: dispatch page/isLoaded
Router->>Store: dispatch size/isLoaded
Router->>Cookie: get token
Cookie-->>Router: token = eyJ...
Router->>Router: next 放行
Router->>Layout: 渲染 header-aside
Layout->>Store: menu 加载侧边栏
Store->>DB: get sys.menu.asideCollapse
DB-->>Store: 上次展开收起状态
Layout->>Store: theme 加载主题
Store->>DB: get sys.theme.activeName
DB-->>Store: 上次选择的主题
Layout->>Store: page 加载多标签页
Store->>DB: get sys.page.opened
DB-->>Store: 上次打开的标签页列表
Layout->>Page: 目标页面渲染完成
Page-->>User: 首页正常显示,主题侧栏标签页全部恢复
```
### 对比:首次登录 vs 已有 Token
| 维度 | 首次登录(无 Token | 已有 Token 恢复 |
|------|-------------------|----------------|
| 入口 | `/login` 登录页 | 任意页面 URL |
| 路由守卫 | 拦下 → 重定向 /login | 放行 |
| 用户操作 | 输入用户名密码 | 无需操作 |
| `account/login` | ✅ 触发 | ❌ 不触发 |
| `account/load()` | ✅ 触发(写入 DB | ❌ 不触发 |
| `page/isLoaded` | 触发(首次无缓存) | 触发(从 DB 恢复) |
| `size/isLoaded` | 触发 | 触发 |
| 主题/侧栏/标签页 | 从登录后 load() 写入 | 从 lowdb 读取上次状态 |
| Cookie | 新建 token / uuid | 复用已有 token |
---
### 整体状态流转
```mermaid
stateDiagram-v2
[*] --> 未登录: 首次访问
[*] --> 已登录: 已有 token恢复会话
未登录 --> 登录页面: 路由守卫拦下
登录页面 --> 提交中: 输入账号密码,点击登录
提交中 --> 登录成功: API 返回 token
提交中 --> 登录失败: API 报错 / 401
登录失败 --> 登录页面: 清除 cookie允许重试
登录成功 --> 已登录: 写入 cookie + load() 加载配置
已登录 --> 已登录: 页面刷新token 仍有效Router + DB 恢复)
已登录 --> 未登录: API 返回 401被强制退出
已登录 --> 注销中: 点击注销
注销中 --> 已登录: 取消确认
注销中 --> 未登录: 确认 → logout API → 清 cookie → 跳 /login
```
---
## 六、搬迁后验证清单
- [ ] `pnpm lint` 无报错
- [ ] `pnpm serve` 启动成功
- [ ] 访问 `http://localhost:8081/login` 能看到完整登录页面
- [ ] 输入正确的用户名密码能登录并跳转首页
- [ ] 中文/英文切换按钮文字正确
- [ ] 登录失败有表单校验提示
- [ ] 浏览器 Cookie 中有 `token``uuid`

601
docs/菜单权限迁移.md Normal file
View File

@@ -0,0 +1,601 @@
# Menu 权限迁移方案
> 参照项目:`D:\code\company\SCTMES_MES_V5\vue-app`(以下简称"源项目"
---
## 一、源项目SCTMESMenu 权限架构
### 1.1 后端接口
```
GET system_settings/menu_configuration/menu/all
```
API 文件:[src/api/system_settings/menu_configuration/menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\api\system_settings\menu_configuration\menu.js)
返回当前用户可见的**扁平数组**,字段如下:
| 字段 | 类型 | 说明 |
|------|------|------|
| `menu_id` | number | 主键,用于构建父子关系 |
| `parent_id` | number | 父节点 ID`0` 表示顶栏根节点 |
| `url` | string | 前端路由路径,如 `/system_settings/user_management/user` |
| `name` | string | 菜单显示名称 |
| `icon` | string | 图标名FontAwesome |
| `is_navi` | number | 是否作为导航菜单展示1=是) |
| `status` | number | 启用/禁用 |
| `type` | string | 菜单类型 |
| `params` | string | 额外参数 |
| `sort` | number | 排序 |
| `remark` | string | 备注 |
### 1.2 菜单数据全链路
```
登录成功 → account.login() → dispatch('load')
account.load()
...加载 user/theme/transition/page/menu/size/color...
dispatch('d2admin/menu/sourceDataLoad')
┌────────────┴────────────┐
│ │
localStorage localStorage 为空
有缓存 且有 token
│ │
▼ ▼
直接读缓存 GET /menu/all 后端接口
写入 localStorage 缓存
└────────────┬────────────┘
menu.install(this, sourceData)
```
**Store 文件**[src/store/modules/d2admin/modules/menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\store\modules\d2admin\modules\menu.js)
```js
state: {
header: [],
aside: [],
asideCollapse: setting.menu.asideCollapse,
asideTransition: setting.menu.asideTransition,
authKey: {}, // ← 权限字典 { '/path': '菜单名', ... }
sourceData: [] // ← 菜单源数据(来自后端或本地缓存)
}
```
### 1.3 `sourceDataLoad` action 核心逻辑
```js
async sourceDataLoad({ state, dispatch }) {
// 1. 优先从 localStorage 读取缓存
state.sourceData = await dispatch('d2admin/db/get', {
dbName: 'database',
path: '$menu.sourceData',
defaultValue: [],
user: true
}, { root: true })
// 2. 缓存为空且已登录 → 调后端获取
if (!state.sourceData.length && util.cookies.get('token')) {
const res = await getMenuAll(null)
state.sourceData = res.data || []
await dispatch('d2admin/db/set', {
dbName: 'database',
path: '$menu.sourceData',
value: state.sourceData,
user: true
}, { root: true })
}
// 3. 处理为 header/aside/authKey
menu.install(this, state.sourceData)
}
```
### 1.4 `menu.install()` — 扁平数据 → 菜单树 + 权限字典
**文件**[src/menu/index.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\menu\index.js)
```js
export default {
install(vm, source) {
// 1. 构建权限字典 { '/path': '菜单名' }
vm.commit('d2admin/menu/headerAuth', source)
// 2. 扁平数据转为 {header: [], aside: []} 树结构
const { header, aside } = getMenuData(source)
// 3. 写入 store → 触发菜单渲染
vm.commit('d2admin/menu/headerSet', header)
vm.commit('d2admin/menu/asideSet', aside)
}
}
```
`getMenuData()` 核心流程:
```
source (扁平数组)
├── 过滤: is_navi !== 1 的跳过
├── parent_id === 0 → 推入 header[]
└── 全部节点 → 推入 aside[]
util.formatDataToTree(aside) { menu_id ↔ parent_id }
树形结构 aside
```
**`headerAuth` mutation**:遍历 `source`,将每个有 `url` 的节点写入 `authKey[url] = name`
```js
headerAuth(state, source) {
let auth = {}
source.forEach(value => {
if (value.url) {
auth[value.url] = value.name
}
})
state.authKey = auth
}
```
### 1.5 权限控制系统
**`$permission()` 方法** — 定义在 [src/plugin/d2admin/index.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\plugin\d2admin\index.js#L50)
```js
Vue.prototype.$permission = (value, type = 'menu') => {
let path = ''
const auth = store.state.d2admin.menu.authKey
switch (type) {
case 'menu': // 直接用 URL 查
path = value
break
case 'router': // 路由 name → URL
path = value.name.replace(/-/g, '/')
path.slice(0, 1) !== '/' && (path = '/' + path)
break
}
return !!(path && Object.prototype.hasOwnProperty.call(auth, path))
}
```
**`v-permission` 指令** — 定义在 [src/main.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\main.js#L72-L78)
```js
Vue.directive('permission', {
bind: (el, binding) => {
if (!Vue.prototype.$permission(binding.value)) {
el.parentNode ? el.parentNode.removeChild(el) : el.style.display = 'none'
}
}
})
```
使用示例:
```html
<el-button v-permission="'/system_settings/user_management/user'">新增用户</el-button>
```
### 1.6 菜单导航权限过滤
**Menu Mixin** — [src/layout/header-aside/components/mixin/menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\layout\header-aside\components\mixin\menu.js)
点击顶栏一级菜单时,不直接跳转,而是查找第一个有权限的子路由:
```js
getRouterAuthPath(index, indexPath) {
// 子路由直接访问
if (index === '/index' || !indexPath || indexPath.length > 1) {
this.$router.push({ path: index })
return
}
// 查找一级路由下第一个有权限的子路由
let router = null
for (const value of frameInRoutes) {
if (value.path === index) {
router = value.children
break
}
}
if (!router) {
this.$router.push({ path: index })
return
}
for (const value of router) {
const newPath = index + '/' + value.path
if (this.$permission(newPath)) {
this.$router.push({ path: newPath })
break
}
}
}
```
### 1.7 路由 — 全部静态注册
路由在 [src/router/routes.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\router\routes.js) 中**全部静态定义**,不使用 `addRoute`
路由守卫([src/router/index.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\router\index.js))仅判断 token 是否存在,不校验具体路由权限。权限控制在**菜单渲染**和**菜单点击时**完成。
### 1.8 main.js 启动流程
[src/main.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\main.js#L108-L137)
```js
created() {
// 仅初始化页面池,不再设置静态菜单
this.$store.commit('d2admin/page/init', frameInRoutes)
// 静态菜单设置已注释:
// this.$store.commit('d2admin/menu/headerSet', menuHeader)
// this.$store.commit('d2admin/search/init', menuHeader)
},
mounted() {
this.$store.dispatch('d2admin/account/load') // → sourceDataLoad → 获取菜单
},
watch: {
// $route.matched 切换侧边栏的 watch 已注释
}
```
---
## 二、mes-ui 当前现状 vs 目标
| 模块 | mes-ui 现状 | 源项目(目标) |
|------|-----------|---------------|
| 菜单数据来源 | `src/menu/modules/*.js` 静态硬编码 | 后端 `GET /menu/all` + localStorage 缓存 |
| `sourceDataLoad` | 仅 localStorage 读取,不参与菜单构建 | localStorage 兜底 + 调后端 → `menu.install()` |
| 权限字典 | 无 | `authKey: { '/path': 'name' }` |
| 菜单树构建 | 编译时 `supplementPath()` | 运行时 `getMenuData()` + `formatDataToTree()` |
| 权限检查 | 无 | `$permission()` + `v-permission` 指令 |
| 菜单点击 | 直接 `$router.push` | `getRouterAuthPath()` 查找首个有权限子路由 |
| main.js 菜单初始化 | `created``headerSet(menuHeader)` | 注释掉静态菜单,由 `mounted` 中的 `load()` 触发 |
| 路由注册 | 全部静态 | 全部静态(一致) |
| 路由守卫 | 仅 token 检查 | 仅 token 检查(一致) |
---
## 三、迁移计划
### 阶段 1约定后端接口格式
后端接口:`GET /api/menu/all`(或复用源项目的 `system_settings/menu_configuration/menu/all`
返回格式(扁平数组):
```json
{
"code": 0,
"data": [
{ "menu_id": 1, "parent_id": 0, "url": "/index", "name": "首页", "icon": "home", "is_navi": 1 },
{ "menu_id": 2, "parent_id": 0, "url": "/production_master_data", "name": "生产主数据", "icon": "cogs", "is_navi": 1 },
{ "menu_id": 3, "parent_id": 2, "url": "/production_master_data/factory_model/factory_area", "name": "工厂区域", "icon": "map-marker", "is_navi": 1 }
]
}
```
### 阶段 2新增/改造 API 层
**新增** `src/api/menu.js`(参照源项目 [menu.js](file:///D:\code\company\SCTMES_MES_V5\vue-app\src\api\system_settings\menu_configuration\menu.js)
```js
import { request } from '@/api/_service'
export function getMenuAll(data) {
return request({
url: 'menu/all',
method: 'get',
params: {
method: 'system_settings_menu_configuration_menu_all',
platform: 'background',
...data
}
})
}
```
### 阶段 3改造 `menu.js` Store
**改造** [src/store/modules/d2admin/modules/menu.js](file:///d:\code\mes\mes-ui\src\store\modules\d2admin\modules\menu.js)
| 改动 | 内容 |
|------|------|
| state | 新增 `authKey: {}` |
| `sourceDataLoad` action | 改为localStorage 兜底 → 调后端 → `menu.install()` |
| mutations | 新增 `headerAuth(state, source)` → 构建 `authKey` 字典 |
```js
// 关键变更 — sourceDataLoad:
async sourceDataLoad({ state, commit, dispatch }) {
// 1. 先读 localStorage 缓存
state.sourceData = await dispatch('d2admin/db/get', {
dbName: 'database',
path: '$menu.sourceData',
defaultValue: [],
user: true
}, { root: true })
// 2. 缓存为空且已登录 → 调后端
if (!state.sourceData.length && util.cookies.get('token')) {
const res = await getMenuAll()
state.sourceData = res || []
await dispatch('d2admin/db/set', {
dbName: 'database',
path: '$menu.sourceData',
value: state.sourceData,
user: true
}, { root: true })
}
// 3. 构建菜单树 + 权限字典
menuUtil.install(this, state.sourceData)
}
```
### 阶段 4改造 `src/menu/index.js` — 从静态导出变为工具模块
将 [src/menu/index.js](file:///d:\code\mes\mes-ui\src\menu\index.js) 从"导出静态菜单配置"改为"菜单处理工具"(参照源项目):
```js
import util from '@/libs/util'
function getMenuData(arr) {
let tree = { header: [], aside: [] }
arr.forEach(value => {
if (!value.is_navi) return // 过滤非导航菜单
const menuItem = {
path: value.url,
title: value.name,
icon: value.icon,
type: value.type,
params: value.params
}
if (value.parent_id === 0) {
tree.header.push({ ...menuItem })
}
menuItem.menu_id = value.menu_id
menuItem.parent_id = value.parent_id
tree.aside.push(menuItem)
})
// 扁平数组转树
tree.aside = util.formatDataToTree(tree.aside)
return tree
}
export default {
install(vm, source) {
vm.commit('d2admin/menu/headerAuth', source)
const { header, aside } = getMenuData(source)
vm.commit('d2admin/menu/headerSet', header)
vm.commit('d2admin/menu/asideSet', aside)
}
}
```
原有的静态菜单模块(`src/menu/modules/demo-*.js`)可保留但不再被引用,后续按需清理。
### 阶段 5增加权限控制基础设施
#### 5.1 `$permission` 方法
**改造** `src/plugin/d2admin/index.js`,新增:
```js
Vue.prototype.$permission = (value, type = 'menu') => {
let path = ''
const auth = store.state.d2admin.menu.authKey
switch (type) {
case 'menu':
path = value
break
case 'router':
path = value.name.replace(/-/g, '/')
path.slice(0, 1) !== '/' && (path = '/' + path)
break
}
return !!(path && Object.prototype.hasOwnProperty.call(auth, path))
}
```
#### 5.2 `v-permission` 指令
**改造** `src/main.js`,新增:
```js
Vue.directive('permission', {
bind: (el, binding) => {
if (!Vue.prototype.$permission(binding.value)) {
el.parentNode ? el.parentNode.removeChild(el) : el.style.display = 'none'
}
}
})
```
#### 5.3 菜单点击权限过滤
**改造** [src/layout/header-aside/components/mixin/menu.js](file:///d:\code\mes\mes-ui\src\layout\header-aside\components\mixin\menu.js),增加 `getRouterAuthPath` 方法:
```js
import { frameInRoutes } from '@/router/routes'
methods: {
handleMenuSelect(index, indexPath) {
if (/^d2-menu-empty-\d+$/.test(index) || index === undefined) {
this.$message.warning('临时菜单')
} else if (/^https:\/\/|http:\/\//.test(index)) {
util.open(index)
} else {
this.getRouterAuthPath(index, indexPath)
}
},
getRouterAuthPath(index, indexPath) {
if (index === '/index' || !indexPath || indexPath.length > 1) {
this.$router.push({ path: index })
return
}
let router = null
for (const value of frameInRoutes) {
if (value.path === index) {
router = value.children
break
}
}
if (!router) {
this.$router.push({ path: index })
return
}
for (const value of router) {
const newPath = index + '/' + value.path
if (this.$permission(newPath)) {
this.$router.push({ path: newPath })
break
}
}
}
}
```
### 阶段 6改造 `main.js` 启动流程
**改造** [src/main.js](file:///d:\code\mes\mes-ui\src\main.js)
```js
created() {
this.$store.commit('d2admin/page/init', frameInRoutes)
// 注释掉静态菜单设置:
// this.$store.commit('d2admin/menu/headerSet', menuHeader)
// this.$store.commit('d2admin/search/init', menuHeader)
},
mounted() {
this.$store.commit('d2admin/releases/versionShow')
this.$store.dispatch('d2admin/account/load') // → sourceDataLoad → 获取后端菜单
this.$store.commit('d2admin/ua/get')
this.$store.dispatch('d2admin/fullscreen/listen')
},
watch: {
// 注释掉 $route.matched 侧边栏切换(由 store.aside 直接驱动)
// '$route.matched': { ... }
}
```
### 阶段 7增加 `util.formatDataToTree` 工具函数
**改造** `src/libs/util.js`,新增:
```js
util.formatDataToTree = (data, key = 'menu_id', pid = 'parent_id') => {
if (!data || data.length <= 0) return []
let map = {}
data.forEach(value => { map[value[key]] = { ...value } })
let tree = []
data.forEach(item => {
const id = item[key]
if (map[id][pid] && map[map[id][pid]]) {
if (!map[map[id][pid]].children) {
map[map[id][pid]].children = []
}
map[map[id][pid]].children.push(map[id])
} else {
tree.push(map[id])
}
})
return tree
}
```
---
## 四、影响的文件清单
| 文件 | 改动类型 | 说明 |
|------|----------|------|
| `src/api/menu.js` | **新增** | 菜单 API`getMenuAll` |
| `src/store/modules/d2admin/modules/menu.js` | **改造** | `sourceDataLoad` 加后端调用 + `headerAuth` mutation + `authKey` state |
| `src/menu/index.js` | **重写** | 从静态配置改为 `install()` 工具模块 |
| `src/plugin/d2admin/index.js` | **改造** | 新增 `$permission` 方法 |
| `src/main.js` | **改造** | 注释静态菜单设置;新增 `v-permission` 指令 |
| `src/layout/header-aside/components/mixin/menu.js` | **改造** | 增加 `getRouterAuthPath` 权限过滤 |
| `src/libs/util.js` | **改造** | 新增 `formatDataToTree` 工具函数 |
| `src/menu/modules/demo-*.js` | **后续可删** | 静态菜单数据不再使用,单独清理 |
---
## 五、完整时序图
```
用户登录
login/index.vue → dispatch('d2admin/account/login')
account.js login action
├── loginAdminUser() → 后端登录接口
├── util.cookies.set() → 存 token/uuid
├── dispatch('d2admin/user/set') → 存用户信息
└── dispatch('load')
├── d2admin/user/load → 加载用户名
├── d2admin/theme/load → 加载主题
├── d2admin/transition/load → 加载过渡效果
├── d2admin/page/openedLoad → 加载标签页
├── d2admin/menu/asideLoad → 加载侧边栏收起设置
├── d2admin/size/load → 加载全局尺寸
├── d2admin/color/load → 加载颜色设置
└── d2admin/menu/sourceDataLoad
├── 先读 localStorage 缓存
├── 缓存空 → GET /api/menu/all 后端接口
├── 写入 localStorage 缓存
└── menu.install(this, sourceData)
├── headerAuth → 构建 authKey 权限字典
├── getMenuData → 扁平 → {header, aside} 树
├── headerSet → 顶栏菜单渲染
└── asideSet → 侧边栏菜单渲染
跳转到首页 → 菜单已按权限渲染
```
---
## 六、注意事项
1. **路由仍是静态注册的**mes-ui 不需要改造成动态 `addRoute`,路由全部在 `router/routes.js` 中静态定义即可,权限通过菜单显示/隐藏 + `getRouterAuthPath` 控制。
2. **不要删除源项目代码**:源项目在 `D:\code\company\SCTMES_MES_V5\vue-app`,仅作为参照,不对其做任何修改。
3. **localStorage 缓存**是离线兜底:首次登录调后端,后续从缓存读取;注销时清空缓存。
4. **`block` cookie**:已在登录页 `mounted` 中设为 `'false'`,注销时设为 `'true'`,用于控制错误日志是否弹出提示。

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,245 @@
# 质量管理功能测试任务列表
## 检验类别管理 (Inspection Type Management)
- [ ] 通过菜单或地址 /quality_control/first_inspection/category 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 首巡检项目配置 (First Article Inspection Configuration)
- [ ] 通过菜单或地址 /quality_control/first_inspection/setting 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 首巡检录入 (First Article Inspection Records)
- [ ] 通过菜单或地址 /quality_control/first_inspection/input 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 首巡检报表 (First Article Inspection Reports)
- [ ] 通过菜单或地址 /quality_control/first_inspection/report 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
## 检验单管理 (Inspection Orders)
- [ ] 通过菜单或地址 /quality_control/xqc/inspection_order_manage 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 检验标准 (Inspection Standards)
- [ ] 通过菜单或地址 /quality_control/xqc/inspection_standard 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 接收质量限 (AQL Standards)
- [ ] 通过菜单或地址 /quality_control/xqc/aql_config 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 检测方案维护 (Inspection Plans)
- [ ] 通过菜单或地址 /quality_control/xqc/inspection_plan 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 检验项目 (Inspection Items)
- [ ] 通过菜单或地址 /quality_control/xqc/inspection_item 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## 抽样方案配置 (Sampling Plans)
- [ ] 通过菜单或地址 /quality_control/xqc/sampling_plan 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## SPC渲染条件配置 (SPC Configuration)
- [ ] 通过菜单或地址 /spc/management 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 新增一条测试数据,确认必填校验、提交成功提示和列表刷新正常。
- [ ] 编辑刚新增的数据,确认回显、保存和刷新后的字段值正确。
- [ ] 删除测试数据,确认二次确认弹窗、删除请求和列表刷新正常。
## XBar-R (XBar-R Chart)
- [ ] 通过菜单或地址 /spc/chart/XBar-R 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## XBar-S (XBar-S Chart)
- [ ] 通过菜单或地址 /spc/chart/XBar-S 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## I-MR (I-MR Chart)
- [ ] 通过菜单或地址 /spc/chart/I-MR 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## Levey-Jennings (Levey-Jennings Chart)
- [ ] 通过菜单或地址 /spc/chart/Levey-Jennings 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## EWMA (EWMA Chart)
- [ ] 通过菜单或地址 /spc/chart/EWMA 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## CUSUM (CUSUM Chart)
- [ ] 通过菜单或地址 /spc/chart/CUSUM 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## MA (Moving Average Chart)
- [ ] 通过菜单或地址 /spc/chart/MA 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## MAMR (Moving Average MR Chart)
- [ ] 通过菜单或地址 /spc/chart/MAMR 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## MAMS (Moving Average S Chart)
- [ ] 通过菜单或地址 /spc/chart/MAMS 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## CPK (Process Capability Index)
- [ ] 通过菜单或地址 /spc/chart/Cpk 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## DPMO (DPMO)
- [ ] 通过菜单或地址 /spc/chart/DPMO 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## PChart (P Chart)
- [ ] 通过菜单或地址 /spc/chart/PChart 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## NPChart (NP Chart)
- [ ] 通过菜单或地址 /spc/chart/NPChart 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## CChart (C Chart)
- [ ] 通过菜单或地址 /spc/chart/CChart 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。
## UChart (U Chart)
- [ ] 通过菜单或地址 /spc/chart/UChart 打开页面,确认页面标题、查询区和列表区域正常显示。
- [ ] 输入主要查询条件后点击查询,确认请求参数和列表刷新符合旧系统字段。
- [ ] 点击重置,确认查询条件清空并回到第一页。
- [ ] 切换分页大小和页码,确认列表数据、总数和加载状态正常。
- [ ] 对照旧系统同一查询条件,确认报表/只读列表的关键字段展示一致。
- [ ] 查询有样本数据的 SPC 项目,确认折线图区域和明细表同步展示,并且无样本时页面不报错。

View File

@@ -0,0 +1,94 @@
# MES V2 迁移任务列表
> 根据 `后台Webman界面截图对照表.md` 生成。状态以当前 V2 项目中已落地的页面目录为准。
- 总功能数79
- 已迁移79
- 未迁移0
| 状态 | 一级模块 | 二级模块 | 三级模块 | 功能说明 | V2 目标路径 |
|:---:|---|---|---|---|---|
| ✅ | 系统设置 (System Administration) | 用户管理 (User Management) | 角色 (Role) | 设置用户组并分配权限(增删改查用户组,并实现权限分配功能) | `src/views/system-administration/user-management/role/` |
| ✅ | 系统设置 (System Administration) | 用户管理 (User Management) | 用户 (User) | 管理用户账号并绑定对应角色 | `src/views/system-administration/user-management/user/` |
| ✅ | 系统设置 (System Administration) | 菜单管理 (Menu Management) | 菜单配置 (Menu Configuration) | 系统菜单配置 | `src/views/system-administration/menu-management/menu-configuration/` |
| ✅ | 系统设置 (System Administration) | 系统助手 (System Utilities) | 操作日志 (Operation Logs) | 系统操作日志 | `src/views/system-administration/system-utilities/operation-logs/` |
| ✅ | 系统设置 (System Administration) | 系统助手 (System Utilities) | 接口日志 (API Logs) | 与设备对接流程交互日志(支持按 IP 和接口名称查询) | `src/views/system-administration/system-utilities/api-logs/` |
| ✅ | 系统设置 (System Administration) | 系统监控 (System Monitoring) | 监控设置 (Monitoring Configuration) | 系统监控配置 | `src/views/system-administration/system-monitoring/monitoring-configuration/` |
| ✅ | 生产配置 (Production Master Data) | 工厂模型 (Factory Model) | 产线设置 (Production Line) | 管理产线(支持增删改查) | `src/views/production-master-data/factory-model/production-line/` |
| ✅ | 生产配置 (Production Master Data) | 工厂模型 (Factory Model) | 工厂区域 (Factory Area) | 管理工厂区域(支持增删改查) | `src/views/production-master-data/factory-model/factory-area/` |
| ✅ | 生产配置 (Production Master Data) | 工艺模型 (Process Model) | 工艺流程类别 (Process Category) | 工艺流程类别的增删改查 | `src/views/production-master-data/process-model/process-category/` |
| ✅ | 生产配置 (Production Master Data) | 工艺模型 (Process Model) | 工序单元 (Process Step) | 配置工序单元(节点),支持参数预设 | `src/views/production-master-data/process-model/process-step/` |
| ✅ | 生产配置 (Production Master Data) | 工艺模型 (Process Model) | 工艺流程 (Process Routing) | 设置生产工艺流程并管理流程卡 | `src/views/production-master-data/process-model/process-routing/` |
| ✅ | 生产配置 (Production Master Data) | 产品管理 (Product Management) | 产品列表 (Product List) | 产品管理(增删改查) | `src/views/production-master-data/product-management/product-list/` |
| ✅ | 生产配置 (Production Master Data) | 产品管理 (Product Management) | 不良管理 (Defect Management) | 不良代码及描述管理,支持批量导入 | `src/views/production-master-data/product-model/product-ng-info/` |
| ✅ | 生产配置 (Production Master Data) | 物料模型 (Material Model) | 物料类别列表 (Material Category) | 区分原材料和半成品 | `src/views/production-master-data/material-model/material-category/` |
| ✅ | 生产配置 (Production Master Data) | 物料模型 (Material Model) | 物料信息管理 (Material Master) | 维护物料编码、名称、规格等属性 | `src/views/production-master-data/material-model/material-master/` |
| ✅ | 生产配置 (Production Master Data) | 物料模型 (Material Model) | BOM物料清单 (Bill of Materials) | 产品BOM管理 | `src/views/production-master-data/material-model/bill-of-materials/` |
| ✅ | 生产配置 (Production Master Data) | 物料模型 (Material Model) | 计量单位 (Unit of Measure) | 计量单位配置与管理 | `src/views/production-master-data/material-model/material-unit/` |
| ✅ | 生产配置 (Production Master Data) | SPC采集模型 (SPC Configuration) | SPC采集配置 (Data Collection Configuration) | 配置SPC采集参数 | `src/views/production-master-data/spc-configuration/data-collection-configuration/` |
| ✅ | 生产配置 (Production Master Data) | 班组模型 (Team Model) | 班组管理 (Team Management) | 管理生产班组 | `src/views/production-master-data/team-model/team-management/` |
| ✅ | 生产配置 (Production Master Data) | 班组模型 (Team Model) | 班次管理 (Shift Management) | 管理生产班次 | `src/views/production-master-data/team-model/shift-management/` |
| ✅ | 生产配置 (Production Master Data) | 班组模型 (Team Model) | 排班日历 (Scheduling Calendar) | 查看排班日历 | `src/views/production-master-data/team-model/scheduling-calendar/` |
| ✅ | 设备模型 (Equipment Management) | 设备类别 (Equipment Category) | 设备类别 (Equipment Category) | 管理设备类别 | `src/views/equipment-management/equipment-model/equipment-category/` |
| ✅ | 设备模型 (Equipment Management) | 设备信息 (Equipment Management) | 设备信息 (Equipment Registry) | 管理设备信息 | `src/views/equipment-management/equipment-model/equipment-registry/` |
| ✅ | 设备模型 (Equipment Management) | 设备点检 (Inspection Management) | 设备点检项目 (Inspection Items) | 点检项目管理 | `src/views/equipment-management/inspection-management/inspection-items/` |
| ✅ | 设备模型 (Equipment Management) | 设备点检 (Inspection Management) | 设备点检记录 (Inspection Records) | 点检记录管理 | `src/views/equipment-management/inspection-management/inspection-records/` |
| ✅ | 设备模型 (Equipment Management) | 设备点检 (Inspection Management) | 设备点检日志 (Inspection Logs) | 点检日志查询 | `src/views/equipment-management/inspection-management/inspection-logs/` |
| ✅ | 设备模型 (Equipment Management) | 设备保养 (Maintenance Management) | 设备保养项目 (Maintenance Items) | 保养项目管理 | `src/views/equipment-management/maintenance-management/maintenance-items/` |
| ✅ | 设备模型 (Equipment Management) | 设备保养 (Maintenance Management) | 设备保养详情 (Maintenance Details) | 保养详情管理 | `src/views/equipment-management/maintenance-management/maintenance-details/` |
| ✅ | 设备模型 (Equipment Management) | 设备保养 (Maintenance Management) | 设备保养日志 (Maintenance Logs) | 保养日志查询 | `src/views/equipment-management/maintenance-management/maintenance-logs/` |
| ✅ | 设备模型 (Equipment Management) | 设备维修 (Repair Management) | 设备维修管理 (Repair Management) | 维修管理 | `src/views/equipment-management/repair-management/repair-management/` |
| ✅ | 设备模型 (Equipment Management) | 设备维修 (Repair Management) | 设备维修日志 (Repair Logs) | 维修日志查询 | `src/views/equipment-management/repair-management/repair-logs/` |
| ✅ | 设备模型 (Equipment Management) | 设备损耗品 (Consumables Management) | 设备损耗品类别 (Consumables Category) | 损耗品分类管理 | `src/views/equipment-management/consumables-management/consumables-category/` |
| ✅ | 设备模型 (Equipment Management) | 设备损耗品 (Consumables Management) | 设备损耗品项目 (Consumables Items) | 损耗品项目管理 | `src/views/equipment-management/consumables-management/consumables-items/` |
| ✅ | 设备模型 (Equipment Management) | 设备损耗品 (Consumables Management) | 设备损耗品寿命管理 (Consumables Lifecycle Management) | 寿命管理 | `src/views/equipment-management/consumables-management/consumables-lifecycle/` |
| ✅ | 设备模型 (Equipment Management) | 设备损耗品 (Consumables Management) | 设备损耗品更换日志 (Replacement Logs) | 更换记录查询 | `src/views/equipment-management/consumables-management/replacement-logs/` |
| ✅ | 计划与生产 (Planning & Production) | 生产批次管理 (Batch Management) | 批次列表 (Batch List) | 批次管理 | `src/views/planning-production/batch-management/batch-list/` |
| ✅ | 计划与生产 (Planning & Production) | 生产批次管理 (Batch Management) | 批次托盘 (Tray Tracking) | 托盘跟踪与操作 | `src/views/planning-production/batch-management/tray-tracking/` |
| ✅ | 计划与生产 (Planning & Production) | 生产批次管理 (Batch Management) | 生产批次不良报表 (Batch Defect Report) | 不良报表 | `src/views/planning-production/batch-management/batch-defect-report/` |
| ✅ | 计划与生产 (Planning & Production) | 预警中心 (Alert Center) | 预警中心 (Alert Center) | 预警中心 | `src/views/planning-production/alert-center/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 物料监控 (Material Monitoring) | 物料监控 | `src/views/planning-production/production-monitoring/material-monitoring/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 电池复投管理 (Rework Management) | 返工管理 | `src/views/planning-production/production-monitoring/rework-management/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 托盘管理 (Tray Management) | 托盘管理 | `src/views/planning-production/production-monitoring/tray-management/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 托盘登录 (Tray Registration) | 托盘登记 | `src/views/planning-production/production-monitoring/tray-registration/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 设备监控 (Equipment Monitoring) | 设备监控 | `src/views/planning-production/production-monitoring/equipment-monitoring/` |
| ✅ | 计划与生产 (Planning & Production) | 生产监控 (Production Monitoring) | 电池工序管理 (Process Execution) | 工序管理 | `src/views/planning-production/production-monitoring/process-execution/` |
| ✅ | 质量管理 (Quality Management) | 过程控制 (Process Control) | 检验类别管理 (Inspection Type Management) | | `src/views/quality-management/process-control/inspection-type-management/` |
| ✅ | 质量管理 (Quality Management) | 过程控制 (Process Control) | 首巡检项目配置 (First Article Inspection Configuration) | | `src/views/quality-management/process-control/first-article-inspection-configuration/` |
| ✅ | 质量管理 (Quality Management) | 过程控制 (Process Control) | 首巡检录入 (First Article Inspection Records) | | `src/views/quality-management/process-control/first-article-inspection-records/` |
| ✅ | 质量管理 (Quality Management) | 过程控制 (Process Control) | 首巡检报表 (First Article Inspection Reports) | | `src/views/quality-management/process-control/first-article-inspection-reports/` |
| ✅ | 质量管理 (Quality Management) | 检验控制 (Inspection Management) | 检验单管理 (Inspection Orders) | | `src/views/quality-management/inspection-management/inspection-orders/` |
| ✅ | 质量管理 (Quality Management) | 检验控制 (Inspection Management) | 检验标准 (Inspection Standards) | | `src/views/quality-management/inspection-management/inspection-standards/` |
| ✅ | 质量管理 (Quality Management) | 检验控制 (Inspection Management) | 接收质量限 (AQL Standards) | | `src/views/quality-management/inspection-management/aql-standards/` |
| ✅ | 质量管理 (Quality Management) | 检验控制 (Inspection Management) | 检测方案维护 (Inspection Plans) | | `src/views/quality-management/inspection-management/inspection-plans/` |
| ✅ | 质量管理 (Quality Management) | 检验控制 (Inspection Management) | 检验项目 (Inspection Items) | | `src/views/quality-management/inspection-management/inspection-items/` |
| ✅ | 质量管理 (Quality Management) | 检验控制 (Inspection Management) | 抽样方案配置 (Sampling Plans) | | `src/views/quality-management/inspection-management/sampling-plans/` |
| ✅ | 质量管理 (Quality Management) | SPC统计过程控制 (SPC Control) | SPC渲染条件配置 (SPC Configuration) | | `src/views/quality-management/spc-control/spc-configuration/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | XBar-R (XBar-R Chart) | | `src/views/quality-management/spc-variable-charts/xbar-r/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | XBar-S (XBar-S Chart) | | `src/views/quality-management/spc-variable-charts/xbar-s/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | I-MR (I-MR Chart) | | `src/views/quality-management/spc-variable-charts/i-mr/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | Levey-Jennings (Levey-Jennings Chart) | | `src/views/quality-management/spc-variable-charts/levey-jennings/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | EWMA (EWMA Chart) | | `src/views/quality-management/spc-variable-charts/ewma/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | CUSUM (CUSUM Chart) | | `src/views/quality-management/spc-variable-charts/cusum/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | MA (Moving Average Chart) | | `src/views/quality-management/spc-variable-charts/ma/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | MAMR (Moving Average MR Chart) | | `src/views/quality-management/spc-variable-charts/mamr/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | MAMS (Moving Average S Chart) | | `src/views/quality-management/spc-variable-charts/mams/` |
| ✅ | 质量管理 (Quality Management) | SPC计量型报表 (SPC Variable Charts) | CPK (Process Capability Index) | | `src/views/quality-management/spc-variable-charts/cpk/` |
| ✅ | 质量管理 (Quality Management) | SPC计数型报表 (SPC Attribute Charts) | DPMO (DPMO) | | `src/views/quality-management/spc-attribute-charts/dpmo/` |
| ✅ | 质量管理 (Quality Management) | SPC计数型报表 (SPC Attribute Charts) | PChart (P Chart) | | `src/views/quality-management/spc-attribute-charts/pchart/` |
| ✅ | 质量管理 (Quality Management) | SPC计数型报表 (SPC Attribute Charts) | NPChart (NP Chart) | | `src/views/quality-management/spc-attribute-charts/npchart/` |
| ✅ | 质量管理 (Quality Management) | SPC计数型报表 (SPC Attribute Charts) | CChart (C Chart) | | `src/views/quality-management/spc-attribute-charts/cchart/` |
| ✅ | 质量管理 (Quality Management) | SPC计数型报表 (SPC Attribute Charts) | UChart (U Chart) | | `src/views/quality-management/spc-attribute-charts/uchart/` |
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 反向追溯 (Backward Traceability) | 反向追溯 | `src/views/data-platform/traceability/backward/` |
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 正向追溯 (Forward Traceability) | 正向追溯 | `src/views/data-platform/traceability/forward/` |
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池曲线 (Battery Curve) | 电池曲线 | `src/views/data-platform/traceability/battery-curve/` |
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 托盘追溯 (Tray Traceability) | 托盘追溯 | `src/views/data-platform/traceability/tray/` |
| ✅ | 数据中台 (Data Platform) | 基础追溯 (Traceability) | 电池追溯 (Battery Traceability) | 电池追溯 | `src/views/data-platform/traceability/battery/` |
| ✅ | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 设备履历报表 (Equipment History Report) | 设备履历报表 | `src/views/data-platform/production-reports/equipment-history/` |
| ✅ | 数据中台 (Data Platform) | 生产报表 (Production Reports) | 电池详情报表 (Battery Detail Report) | 电池详情报表 | `src/views/data-platform/production-reports/battery-detail/` |
| ✅ | 数据中台 (Data Platform) | 相关性分析 (Correlation Analysis) | 鹰眼 (Hawkeye) | 鹰眼 | `src/views/data-platform/correlation-analysis/hawkeye/` |
## 状态说明
-V2 项目中已存在对应页面,或本轮已完成转换并通过构建验证。
- ⬜:尚未确认/尚未转换到 V2 页面目录。

424
docs/迁移任务清单.md Normal file
View File

@@ -0,0 +1,424 @@
# MES-UI 搬迁任务列表
> 从旧项目 `D:\code\company\SCTMES_MES_V5\vue-app` 搬迁至本项目 `d:\code\mes\mes-ui`
## 搬迁规则
| 规则 | 说明 |
|------|------|
| 目录结构 | 按 `后台Webman界面截图对照表.md` 中的 一级→二级→三级 模块层级创建 |
| 页面视图 | `src/views/{一级}/{二级}/{三级}/index.vue` |
| API 接口 | `src/api/{一级}/{二级}.js` |
| Vuex Store | `src/store/modules/{一级}/{二级}.js` |
| 路由 | `src/router/modules/{一级}.js`,汇总到 `routes.js` |
| 组件 | 公用组件放 `src/components/`,模块内组件放 `views` 下的 `components/` |
| 表格 | 搬迁时统一替换为 `page-table``sct-table` + `sct-toolbar`(见 [重构方案](./SCT基础表格重构设计.md)),不再使用旧的 `sct-base-table` |
| 代码审查 | 搬迁前检查旧代码中的不合理处(见下方「代码审查与改进清单」),搬迁时一并修复 |
---
## 预览:前置准备
| ID | 任务 | 源文件 | 目标位置 | 状态 |
|----|------|--------|----------|:----:|
| P0 | 创建目标目录结构(所有一级/二级/三级空文件夹) | — | `src/views/` | ⬜ |
| P1 | 迁移公共服务层axios 实例、工具函数等) | `src/api/service.js` `src/api/tools.js` `src/api/index.js` `src/libs/` | `src/api/` `src/libs/` | ⬜ |
| P2 | 迁移登录页面、首页、404/刷新/重定向等系统通用页面 | `src/views/system_settings/system_monitoring/system/` `src/views/system_settings/home_page/` | `src/views/system-settings/` | ⬜ |
| P3 | 迁移路由入口和 routes.js 汇总 | `src/router/index.js` `src/router/routes.js` | `src/router/` | ⬜ |
| P4 | 迁移全局 Stored2admin | `src/store/modules/d2admin/` | `src/store/modules/d2admin/` | ⬜ |
| P5 | 迁移布局组件header-aside及菜单配置 | `src/layout/` `src/menu/` | `src/layout/` `src/menu/` | ⬜ |
| P6 | 迁移第三方依赖main.js 中的插件、组件注册) | `src/main.js` `src/App.vue` `src/plugin/` | `src/main.js` `src/App.vue` `src/plugin/` | ⬜ |
| P7 | 迁移本地化文件i18n | `src/locales/` `src/i18n.js` | `src/locales/` `src/i18n.js` | ⬜ |
| P8 | 迁移全局设置 | `src/setting.js` `.env` 系列 | `src/setting.js` `.env` 系列 | ⬜ |
| P9 | 移植旧项目专用组件form、sct-ace 等) | `src/components/battery/` `src/components/calculation/` `src/components/device-monitor/` `src/components/dm-print/` `src/components/form/` `src/components/menu-tree/` `src/components/sct-ace/` `src/components/sct-ace-editor/` `src/components/OCR/` | `src/components/` | ⬜ |
| P10 | 迁移旧项目 public 目录下的静态资源 | `public/` | `public/` | ⬜ |
| P11 | 迁移旧项目 assets 资源 | `src/assets/` | `src/assets/` | ⬜ |
---
## 一、系统设置 (System Administration)
> 目标目录根:`src/views/system-settings/`
### 1.1 用户管理 (User Management)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| S1 | 角色 (Role) | `system_settings/user_management/role/` | `system_settings/user_management/role.js` | `sctmesadmin/modules/role.js` | `system-settings/user-management/role/` | ⬜ |
| S2 | 用户 (User) | `system_settings/user_management/user/` | `system_settings/user_management/user.js` | `sctmesadmin/modules/user.js` | `system-settings/user-management/user/` | ⬜ |
### 1.2 菜单管理 (Menu Management)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| S3 | 菜单配置 | `system_settings/menu_configuration/menu/` | `system_settings/menu_configuration/menu.js` | `system-settings/menu-management/menu-configuration/` | ⬜ |
### 1.3 系统助手 (System Utilities)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| S4 | 操作日志 | `system_settings/system_assistant/operate_log/` | `system_settings/system_assistant/operate_log.js` | `system-settings/system-utilities/operation-logs/` | ⬜ |
| S5 | 接口日志 | `system_settings/system_assistant/interface_log/` | `system_settings/system_assistant/interface_log.js` | `system-settings/system-utilities/api-logs/` | ⬜ |
### 1.4 系统监控 (System Monitoring)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| S6 | 监控设置 | `system_settings/system_monitoring/setting/` | `system_settings/system_monitor/setting.js` | `system-settings/system-monitoring/monitoring-configuration/` | ⬜ |
### 1.5 系统设置 - 路由汇总
| ID | 任务 | 源文件 | 目标位置 | 状态 |
|----|------|--------|----------|:----:|
| S7 | 系统设置路由 | `router/system_settings/system.js` | `router/modules/system-settings.js` | ⬜ |
---
## 二、生产配置 (Production Master Data)
> 目标目录根:`src/views/production-configuration/`
### 2.1 工厂模型 (Factory Model)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| P1 | 产线设置 | `production_configuration/factory_model/factory_line/` | 需从路由确认 | `sctmesadmin/modules/line.js` | `production-configuration/factory-model/production-line/` | ⬜ |
| P2 | 工厂区域 | `production_configuration/factory_model/factory_area/` | 需从路由确认 | `sctmesadmin/modules/area.js` | `production-configuration/factory-model/factory-area/` | ⬜ |
### 2.2 工艺模型 (Process Model)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| P3 | 工艺流程类别 | `production_configuration/technology_model/technology_flow_category/` | 需从路由确认 | `sctmesadmin/modules/technology_category.js` | `production-configuration/process-model/process-category/` | ⬜ |
| P4 | 工序单元 | 需确认 | `production_configuration/workerman/workermanSet.js` | `sctmesadmin/modules/steps.js` | `production-configuration/process-model/process-step/` | ⬜ |
| P5 | 工艺流程 | `production_configuration/technology_model/technology_flow/` | 需从路由确认 | `sctmesadmin/modules/technologyflow.js` | `production-configuration/process-model/process-routing/` | ⬜ |
### 2.3 产品管理 (Product Management)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| P6 | 产品列表 | `production_configuration/product_model/battery_model/` | 需从路由确认 | `sctmesadmin/modules/product_battery.js` | `production-configuration/product-management/product-list/` | ⬜ |
| P7 | 不良管理 | `production_configuration/product_model/product_ng_info/` | 需从路由确认 | `sctmesadmin/modules/product_ng_info.js` | `production-configuration/product-management/defect-management/` | ⬜ |
### 2.4 物料模型 (Material Model)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| P8 | 物料类别列表 | `production_configuration/matetial_model/matetial_category/` | `warehouse/basic/material_category.js` | `sctmesadmin/modules/material_category.js` | `production-configuration/material-model/material-category/` | ⬜ |
| P9 | 物料信息管理 | `production_configuration/matetial_model/matetial_management/` | `warehouse/basic/material.js` | — | `production-configuration/material-model/material-master/` | ⬜ |
| P10 | BOM物料清单 | `production_configuration/matetial_model/bom/` | `production_configuration/matetial_model/bom.js` | — | `production-configuration/material-model/bom/` | ⬜ |
| P11 | 计量单位 | `production_configuration/matetial_model/unit/` | `production_configuration/matetial_model/unit.js` | `sctmesadmin/modules/unit.js` | `production-configuration/material-model/unit-of-measure/` | ⬜ |
### 2.5 SPC采集模型 (SPC Configuration)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| P12 | SPC采集配置 | `production_configuration/spc_configuration/binding_scada_node/` | 需从路由确认 | `production-configuration/spc-configuration/spc-data-collection/` | ⬜ |
### 2.6 班组模型 (Team Model)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| P13 | 班组管理 | `system_settings/organization/production_team_manage/` | 需从路由确认 | `sctmesadmin/modules/production_team_manage.js` | `production-configuration/team-model/team-management/` | ⬜ |
| P14 | 班次管理 | `system_settings/organization/production_shift_management/` | 需从路由确认 | — | `production-configuration/team-model/shift-management/` | ⬜ |
| P15 | 排班日历 | `system_settings/organization/production_shift_calender/` | 需从路由确认 | — | `production-configuration/team-model/scheduling-calendar/` | ⬜ |
### 2.7 生产配置 - 路由汇总
| ID | 任务 | 源文件 | 目标位置 | 状态 |
|----|------|--------|----------|:----:|
| P16 | 生产配置路由 | `router/production_configuration/index.js` | `router/modules/production-configuration.js` | ⬜ |
---
## 三、设备模型 (Equipment Management)
> 目标目录根:`src/views/equipment-management/`
### 3.1 设备类别 (Equipment Category)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| E1 | 设备类别 | `production_configuration/device_model/device_category/` | 需从路由确认 | `sctmesadmin/modules/device_category.js` | `equipment-management/equipment-category/` | ⬜ |
### 3.2 设备信息 (Equipment Info)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| E2 | 设备信息 | `production_configuration/device_model/device_management/` | 需从路由确认 | `sctmesadmin/modules/device.js` | `equipment-management/equipment-info/` | ⬜ |
### 3.3 设备点检 (Inspection Management)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| E3 | 设备点检项目 | `device_management/device_check/device_check_items/` | 需从路由确认 | `sctmesadmin/modules/device_check_items.js` | `equipment-management/inspection-management/inspection-items/` | ⬜ |
| E4 | 设备点检记录 | `device_management/device_check/device_check_record/` | 需从路由确认 | — | `equipment-management/inspection-management/inspection-records/` | ⬜ |
| E5 | 设备点检日志 | `device_management/device_check/device_check_items_log/` | 需从路由确认 | — | `equipment-management/inspection-management/inspection-logs/` | ⬜ |
### 3.4 设备保养 (Maintenance Management)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| E6 | 设备保养项目 | `device_management/device_maintain/device_maintain_items/` | 需从路由确认 | `sctmesadmin/modules/device_maintain_items.js` | `equipment-management/maintenance-management/maintenance-items/` | ⬜ |
| E7 | 设备保养详情 | `device_management/device_maintain/device_maintain_items_details/` | 需从路由确认 | — | `equipment-management/maintenance-management/maintenance-details/` | ⬜ |
| E8 | 设备保养日志 | `device_management/device_maintain/device_maintain_items_log/` | 需从路由确认 | — | `equipment-management/maintenance-management/maintenance-logs/` | ⬜ |
### 3.5 设备维修 (Repair Management)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| E9 | 设备维修管理 | `device_management/device_repair/device_repair_management/` | 需从路由确认 | `equipment-management/repair-management/repair-management/` | ⬜ |
| E10 | 设备维修日志 | `device_management/device_repair/device_repair_log/` | 需从路由确认 | `equipment-management/repair-management/repair-logs/` | ⬜ |
### 3.6 设备损耗品 (Consumables Management)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| E11 | 设备损耗品类别 | `device_management/device_consumables/device_consumables_category/` | 需从路由确认 | `sctmesadmin/modules/device_consumables_category.js` | `equipment-management/consumables/consumables-category/` | ⬜ |
| E12 | 设备损耗品项目 | `device_management/device_consumables/device_consumables_items/` | 需从路由确认 | `sctmesadmin/modules/device_consumables_items.js` | `equipment-management/consumables/consumables-items/` | ⬜ |
| E13 | 设备损耗品寿命管理 | 需确认 | 需从路由确认 | `sctmesadmin/modules/device_consumables_lifetime_management.js` | `equipment-management/consumables/consumables-lifecycle/` | ⬜ |
| E14 | 设备损耗品更换日志 | `device_management/device_consumables/device_consumables_replace_log/` | 需从路由确认 | — | `equipment-management/consumables/replacement-logs/` | ⬜ |
### 3.7 设备模型 - 路由汇总
| ID | 任务 | 源文件 | 目标位置 | 状态 |
|----|------|--------|----------|:----:|
| E15 | 设备模型路由 | `router/device_management/device.js` | `router/modules/equipment-management.js` | ⬜ |
---
## 四、计划与生产 (Planning & Production)
> 目标目录根:`src/views/planning-production/`
### 4.1 生产批次管理 (Batch Management)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| B1 | 批次列表 | `planning_production/production_batch_management/batch/` | `data_dashboards/produce/batch.js` | `sctmesadmin/modules/batch.js` | `planning-production/batch-management/batch-list/` | ⬜ |
| B2 | 批次托盘 | `planning_production/production_batch_management/batch_tray/` | 需从路由确认 | — | `planning-production/batch-management/tray-tracking/` | ⬜ |
| B3 | 生产批次不良报表 | `planning_production/production_batch_management/bad/` | 需从路由确认 | — | `planning-production/batch-management/batch-defect-report/` | ⬜ |
### 4.2 预警中心 (Alert Center)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| B4 | 预警中心 | 需确认(可能在 pannel/index | `planning_production/pannel/index.js` | `planning-production/alert-center/` | ⬜ |
### 4.3 生产监控 (Production Monitoring)
| ID | 三级模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|---------|---------|--------|----------|-----------|:----:|
| B5 | 物料监控 | `planning_production/produce/monitor/wareroom/ic/` 或 WIP | `data_dashboards/produce/material/wip.js` | — | `planning-production/production-monitoring/material-monitoring/` | ⬜ |
| B6 | 电池复投管理 | 需确认 | `data_dashboards/produce/battery/replace.js` | — | `planning-production/production-monitoring/rework-management/` | ⬜ |
| B7 | 托盘管理 | `planning_production/produce/monitor/tray_manage/` | `data_dashboards/produce/tray/list.js` `planning_production/produce/tray_manage.js` | — | `planning-production/production-monitoring/tray-management/` | ⬜ |
| B8 | 托盘登录 | `planning_production/produce/monitor/tray_login/` | `planning_production/battery/login.js` `planning_production/produce/tray_login.js` | — | `planning-production/production-monitoring/tray-registration/` | ⬜ |
| B9 | 设备监控 | `planning_production/produce/monitor/device/` | `data_dashboards/produce/report/device.js` | — | `planning-production/production-monitoring/equipment-monitoring/` | ⬜ |
| B10 | 电池工序管理 | `planning_production/produce/monitor/batch_battery/` 等 | `planning_production/produce/batch_battery.js` | `sctmesadmin/modules/batch_battery.js` | `planning-production/production-monitoring/process-execution/` | ⬜ |
### 4.4 计划与生产 - 路由汇总
| ID | 任务 | 源文件 | 目标位置 | 状态 |
|----|------|--------|----------|:----:|
| B11 | 计划与生产路由 | `router/planning_production/index.js` | `router/modules/planning-production.js` | ⬜ |
---
## 五、质量管理 (Quality Management)
> 目标目录根:`src/views/quality-management/`
### 5.1 过程控制 (Process Control)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| Q1 | 检验类别管理 | `quality_control/first_inspection/category/` | `quality_control/xqc/inspection_category.js` | `quality-management/process-control/inspection-type/` | ⬜ |
| Q2 | 首巡检项目配置 | `quality_control/first_inspection/setting/` | 需从路由确认 | `quality-management/process-control/first-article-inspection-config/` | ⬜ |
| Q3 | 首巡检录入 | `quality_control/first_inspection/input/` | 需从路由确认 | `quality-management/process-control/first-article-inspection-records/` | ⬜ |
| Q4 | 首巡检报表 | `quality_control/first_inspection/report/` | 需从路由确认 | `quality-management/process-control/first-article-inspection-reports/` | ⬜ |
### 5.2 检验控制 (Inspection Management)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| Q5 | 检验单管理 | `quality_control/xqc/inspection_order_manage/` | `quality_control/xqc/inspection_order_manage.js` | `quality-management/inspection-control/inspection-orders/` | ⬜ |
| Q6 | 检验标准 | `quality_control/xqc/inspection_standard/` | `quality_control/xqc/inspection_standard.js` | `quality-management/inspection-control/inspection-standards/` | ⬜ |
| Q7 | 接收质量限 (AQL) | `quality_control/xqc/aql_config/` `quality_control/xqc/aql_sample/` | `quality_control/xqc/aql_config.js` `quality_control/xqc/aql_sample.js` | `quality-management/inspection-control/aql-standards/` | ⬜ |
| Q8 | 检测方案维护 | `quality_control/xqc/inspection_plan/` | `quality_control/xqc/inspection_plan.js` | `quality-management/inspection-control/inspection-plans/` | ⬜ |
| Q9 | 检验项目 | `quality_control/xqc/inspection_item/` | `quality_control/xqc/inspection_item.js` | `quality-management/inspection-control/inspection-items/` | ⬜ |
| Q10 | 抽样方案配置 | `quality_control/xqc/sampling_plan/` | `quality_control/xqc/sampling_plan.js` | `quality-management/inspection-control/sampling-plans/` | ⬜ |
### 5.3 SPC统计过程控制 (SPC Control)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| Q11 | SPC渲染条件配置 | `spc/manage/` | `spc/index.js` | `quality-management/spc-control/spc-configuration/` | ⬜ |
### 5.4 SPC计量型报表 (SPC Variable Charts)
| ID | 图表 | 源 views | 目标 views | 状态 |
|----|------|---------|----------|:----:|
| Q12 | XBar-R | `spc/spc_chart/xbar-r/` | `quality-management/spc-variable-charts/xbar-r/` | ⬜ |
| Q13 | XBar-S | `spc/spc_chart/xbar-s/` | `quality-management/spc-variable-charts/xbar-s/` | ⬜ |
| Q14 | I-MR | `spc/spc_chart/i-mr/` | `quality-management/spc-variable-charts/i-mr/` | ⬜ |
| Q15 | Levey-Jennings | `spc/spc_chart/levey-jennings/` | `quality-management/spc-variable-charts/levey-jennings/` | ⬜ |
| Q16 | EWMA | `spc/spc_chart/ewma/` | `quality-management/spc-variable-charts/ewma/` | ⬜ |
| Q17 | CUSUM | `spc/spc_chart/cusum/` | `quality-management/spc-variable-charts/cusum/` | ⬜ |
| Q18 | MA | `spc/spc_chart/ma/` | `quality-management/spc-variable-charts/ma/` | ⬜ |
| Q19 | MAMR | `spc/spc_chart/mamr/` | `quality-management/spc-variable-charts/mamr/` | ⬜ |
| Q20 | MAMS | `spc/spc_chart/mams/` | `quality-management/spc-variable-charts/mams/` | ⬜ |
| Q21 | CPK | `spc/spc_chart/Cpk/` | `quality-management/spc-variable-charts/cpk/` | ⬜ |
### 5.5 SPC计数型报表 (SPC Attribute Charts)
| ID | 图表 | 源 views | 目标 views | 状态 |
|----|------|---------|----------|:----:|
| Q22 | DPMO | `spc/spc_chart/dpmo/` | `quality-management/spc-attribute-charts/dpmo/` | ⬜ |
| Q23 | PChart | `spc/spc_chart/p-chart/` | `quality-management/spc-attribute-charts/p-chart/` | ⬜ |
| Q24 | NPChart | `spc/spc_chart/np-chart/` | `quality-management/spc-attribute-charts/np-chart/` | ⬜ |
| Q25 | CChart | `spc/spc_chart/c-chart/` | `quality-management/spc-attribute-charts/c-chart/` | ⬜ |
| Q26 | UChart | `spc/spc_chart/u-chart/` | `quality-management/spc-attribute-charts/u-chart/` | ⬜ |
### 5.6 质量管理 - 路由汇总
| ID | 任务 | 源文件 | 目标位置 | 状态 |
|----|------|--------|----------|:----:|
| Q27 | 质量管理路由 | `router/quality_control/quality.js` | `router/modules/quality-management.js` | ⬜ |
| Q28 | SPC路由 | `router/spc/index.js` | 合并到 `router/modules/quality-management.js` | ⬜ |
---
## 六、数据中台 (Data Platform)
> 目标目录根:`src/views/data-platform/`
### 6.1 基础追溯 (Traceability)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| D1 | 反向追溯 | `data_middleground/basic_traceability/reverse_direction_traceability/` 或正向追溯 | `data_dashboards/produce/traceability/battery.js` | `data-platform/traceability/backward/` | ⬜ |
| D2 | 正向追溯 | `data_middleground/basic_traceability/` 下确认 | `data_dashboards/produce/traceability/bom_batch.js` | `data-platform/traceability/forward/` | ⬜ |
| D3 | 电池曲线 | `planning_production/produce/traceability/curve/` | `data_dashboards/produce/traceability/curve.js` | `data-platform/traceability/battery-curve/` | ⬜ |
| D4 | 托盘追溯 | `planning_production/produce/traceability/tray/` | `data_dashboards/produce/traceability/tray.js` | `data-platform/traceability/tray/` | ⬜ |
| D5 | 电池追溯 | `planning_production/produce/traceability/battery/` | `data_dashboards/produce/traceability/battery.js` | `data-platform/traceability/battery/` | ⬜ |
### 6.2 生产报表 (Production Reports)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| D6 | 设备履历报表 | `planning_production/produce/report/battery/` 或设备报告 | `data_dashboards/produce/report/all_report.js` `data_dashboards/produce/report/device.js` | `data-platform/production-reports/equipment-history/` | ⬜ |
| D7 | 电池详情报表 | `planning_production/produce/report/battery_details_report/` 或电池报告 | `data_dashboards/produce/report/battery.js` | `data-platform/production-reports/battery-detail/` | ⬜ |
### 6.3 相关性分析 (Correlation Analysis)
| ID | 三级模块 | 源 views | 源 api | 目标 views | 状态 |
|----|---------|---------|--------|----------|:----:|
| D8 | 鹰眼 (Hawkeye) | `data_middleground/eagle_eyes/` | `data_middle_office/eagle_eyes/index.js` | `data-platform/correlation-analysis/hawkeye/` | ⬜ |
### 6.4 数据中台 - 路由汇总
| ID | 任务 | 源文件 | 目标位置 | 状态 |
|----|------|--------|----------|:----:|
| D9 | 数据中台路由 | `router/data_middleground/index.js` | `router/modules/data-platform.js` | ⬜ |
---
## 七、仓储管理 (Warehouse)
> 目标目录根:`src/views/warehouse/`
| ID | 模块 | 源 views | 源 api | 源 store | 目标 views | 状态 |
|----|------|---------|--------|----------|-----------|:----:|
| W1 | 仓库设置(业务类型/单据类型/仓库/库区/库位/货架) | `warehouse/setting/` | `warehouse/setting/` | `warehouse/modules/` | `warehouse/settings/` | ⬜ |
| W2 | 基础数据(客户/物料类别/物料/供应商/领料单) | `warehouse/basic/` | `warehouse/basic/` | `warehouse/modules/` | `warehouse/basic/` | ⬜ |
| W3 | ERP接口接口/采购订单/产品出库/发送日志) | `warehouse/erp/` | `warehouse/erp/` | — | `warehouse/erp/` | ⬜ |
| W4 | 收货管理(采购入库/打印/来料检验/上架等) | `warehouse/receiving_management/` | `warehouse/receiving_management/` | — | `warehouse/receiving/` | ⬜ |
| W5 | 发货管理(出库/委外出库等) | `warehouse/shipping_management/` | 需确认 | — | `warehouse/shipping/` | ⬜ |
| W6 | 库存管理(库存/冻结/锁定/操作日志) | `warehouse/stock_management/` | `warehouse/stock_management/` | — | `warehouse/stock/` | ⬜ |
| W7 | 作业管理(库存移动/盘点) | `warehouse/working/` | `warehouse/working/` | — | `warehouse/operations/` | ⬜ |
| W8 | 仓储路由 | `router/warehouse/index.js` | — | — | `router/modules/warehouse.js` | ⬜ |
---
## 八、SCADA管理保留旧模块不在主文档中
> 目标目录根:`src/views/scada-management/`
| ID | 模块 | 源 views | 源 api | 目标 views | 状态 |
|----|------|---------|--------|----------|:----:|
| SC1 | 车间管理(配置/点位) | `scada_manage/workshop_manage/` | `scada_manage/workshop_manage/` | `scada-management/workshop/` | ⬜ |
| SC2 | 基础配置SCADA配置/查询/节点映射/EMS | `scada_manage/basic_configuration/` | `modules/scada.configure.api.js` | `scada-management/basic-config/` | ⬜ |
| SC3 | 边缘服务器(配置/监控/日志) | `scada_manage/lecpserver/` `scada_manage/EdgeProcessorsManage/` | `modules/edgeServer.api.js` | `scada-management/edge-server/` | ⬜ |
| SC4 | 设备采集监控 | `scada_manage/device_gather/` | `scada_manage/huankong_management/` | `scada-management/device-gather/` | ⬜ |
| SC5 | SCADA路由 | `router/scada_management/scada.js` | — | `router/modules/scada-management.js` | ⬜ |
---
## 代码审查与改进清单
> 在搬迁过程中,逐项检查旧代码中的不合理之处,搬迁时一并修复。每个问题标注 **发现时间** 和 **处理状态**。
### 🔴 严重问题(必须修复)
| # | 问题描述 | 影响范围 | 改进方案 | 状态 |
|---|---------|---------|---------|:--:|
| CR01 | **拼写错误遍布路由和目录名**`matetial`→应为`material``freezeunfreeze``freeze-unfreeze`,出现 23+ 处 | `router/production_configuration/index.js`<br>`views/production_configuration/matetial_model/` | 搬迁时统一修正为正确拼写,路由 path 也一并修正 | ⬜ |
| CR02 | **生产代码残留 `console.log`**285+ 处 `console.log/warn/error` 分布在 100+ 个文件中 | `src/views/` 几乎所有模块 | 移除所有调试用 `console.log`,仅保留关键 `console.error` 并使用统一日志工具 `util.log` | ⬜ |
| CR03 | **重复/拷贝目录残留**`scada_query copy/` 显式拷贝备份目录 | `views/scada_manage/basic_configuration/scada_query copy/` | 删除该拷贝目录,如需要保留则合并到正式目录 | ⬜ |
### 🟡 中等问题(建议修复)
| # | 问题描述 | 影响范围 | 改进方案 | 状态 |
|---|---------|---------|---------|:--:|
| CR04 | **API 注入模式混乱**:旧模式用 `require.context` 动态注入(`api/modules/*.api.js`),新模式用直接 `import``api/system_settings/`),两套并存 | `api/index.js` + `api/modules/` | 统一为直接 `import` 模式,移除 `require.context` 动态注入和 `api/modules/` 目录 | ⬜ |
| CR05 | **`let` 滥用**API 文件中大量 `let url = urls + 'xxx'`URL 拼接后从不重新赋值 | `api/` 下所有文件 | 全部改为 `const` | ⬜ |
| CR06 | **Store 初始化直接用 `localStorage` 无容错**`JSON.parse(localStorage.getItem('roleData'))` 放在 state 声明顶层,解析失败会导致模块加载崩溃 | `store/modules/sctmesadmin/modules/role.js` 等 36 个模块 | 改为在 getter 或 action 中惰性读取,并用 try-catch 包裹 `JSON.parse` | ⬜ |
| CR07 | **每个 API 函数都手动传 `method` 和 `platform` 参数**,冗余且容易遗漏 | `api/` 下 80+ 文件 | 在 `request` 公共层统一注入 `platform: 'background'``method` 参数通过约定 url 自动映射 | ⬜ |
| CR08 | **axios 拦截器 `switch-case` 冗长**:响应拦截器整段 switch-case 映射 HTTP 状态码到错误消息 | `api/service.js` | 改用 Map 结构 | error.message = statusMessages[status] \|\| error.message更简洁 | ⬜ |
| CR09 | **路由文件命名不一致**:有 `system.js``device.js``scada.js``index.js` 混用 | `router/` 所有文件 | 统一为 `index.js`,按文件夹区分模块 | ⬜ |
| CR10 | **`system_Assistant` 大小写不一致**:路由 path 中是 `system_Assistant`大写A目录名是 `system_assistant`小写a | `router/system_settings/system.js` | 统一为 `system-assistant`kebab-case | ⬜ |
| CR11 | **Store 模块 `namespaced: true` 命名不规范**:部分模块路径很深 `sctmesadmin/modules/xxx`,难以维护 | `store/modules/sctmesadmin/` | 按功能打平为 `store/modules/{功能名}.js`,去掉多余嵌套 | ⬜ |
### 🟢 建议优化(可选)
| # | 问题描述 | 影响范围 | 改进方案 | 状态 |
|---|---------|---------|---------|:--:|
| CR12 | **页面组件 `PageHeader/PageMain` 内联模式冗余**:绝大多数页面都是 `index.vue` + `components/PageHeader/index.vue` + `components/PageMain/index.vue` 三层结构PageHeader 大多只传几个 props | 所有 views | 评估是否可将简单的 PageHeader/PageMain 合并为单文件组件,减少目录嵌套 | ⬜ |
| CR13 | **`Promise.resolve(...)` 包裹 sync 数据**Store actions 中 `return Promise.resolve(res.data)``async` 函数里是多余的 | `store/modules/` 所有 actions | 直接 `return res.data``async` 函数自动包装返回值 | ⬜ |
| CR14 | **国际化键名硬编码**:大量组件中 `$t('xxx')` 的 key 没有类型约束,容易拼错 | 所有 Vue 组件 | 搬迁后统一整理 i18n key考虑用常量池管理 | ⬜ |
| CR15 | **公共组件未按功能分组**`components/` 下散落 `battery/``calculation/``tray/``technology/` 等多个业务组件与通用组件混放 | `src/components/` | 业务组件迁入对应模块 views 的 `components/`,公共组件保留并文档化 | ⬜ |
| CR16 | **`sct-base-table` 组件架构臃肿**215 行代码包含致命 bug引入 yargs、60% 死代码、buttonList/columns 在 100+ 页面中重复定义 | `components/sct-base-table/` 及所有引用页面 | 📄 详见 [SCT基础表格重构设计](./SCT基础表格重构设计.md):拆分为 7 个小组件 + 5 个 composable 函数,消除重复,迁移与搬迁同步进行 | ⬜ |
### 📄 专项重构方案
| 文档 | 说明 |
|------|------|
| [SCT基础表格重构设计](./SCT基础表格重构设计.md) | 组合式重构:拆组件+composable消除 buttonList/columns 手动定义,覆盖 100+ 页面 |
---
## 搬迁统计
| 一级模块 | 三级页面数 | 路由文件 | API文件 | Store模块 | 已完成 |
|---------|-----------|---------|---------|----------|:----:|
| 系统设置 | 6 | 1 | 5 | 2 | 0/13 |
| 生产配置 | 15 | 1 | ~10 | 12 | 0/37 |
| 设备模型 | 14 | 1 | ~10 | 7 | 0/31 |
| 计划与生产 | 10 | 1 | ~8 | 3 | 0/21 |
| 质量管理 | 26 | 2 | ~15 | 0 | 0/43 |
| 数据中台 | 8 | 1 | ~8 | 0 | 0/17 |
| 仓储管理 | 25+ | 1 | ~20 | 11 | 0/56 |
| SCADA管理 | 10+ | 1 | ~6 | 0 | 0/16 |
| 前置准备 | — | 2 | — | 1 | 0/11 |
| **合计** | **114+** | **11** | **82+** | **36** | **0/245** |
---
## 搬迁流程说明
每条 ID 任务完成后,将状态从 ⬜ 改为 ✅,并在下方补充日期和备注。
示例:
```
| S1 | 角色 (Role) | `...` | `...` | `...` | ✅ |
```

View File

@@ -0,0 +1,359 @@
# MES-UI 迁移功能测试流程文档(累积追加版)
> 本文档用于记录每次 MES-UI 迁移完成后的功能测试流程。
> 采用**累积追加**模式:每次完成新功能迁移,将对应测试内容追加到本文件末尾,并在「目录」中补充章节索引。
> 测试人员按章节顺序执行用例,每完成一项需在「[ ]」中改为「[x]」并填写实际结果;对未通过项在「问题记录」区域详细描述。
>
> **测试结果约定**
> - ✅ 通过Pass
> - ❌ 失败Fail
> - ⚠️ 阻塞Block依赖其他功能未通过
>
> **填写示例**
> - `[x] 1.1 列表正常加载 ✅ 实际10 条记录,分页正常`
> - `[ ] 1.2 编码为空校验 ❌ 实际:未拦截空值,提示词缺失`
---
## 目录
- [一、测试环境与通用前置条件](#一测试环境与通用前置条件)
- [二、物料类别列表Material Category](#二物料类别列表material-category)
- [三、物料信息管理Material Master](#三物料信息管理material-master)
---
## 一、测试环境与通用前置条件
> 所有功能测试前,请先确认以下环境和基础数据准备就绪。
### 1.1 测试环境
| 项目 | 要求 |
|------|------|
| 操作系统 | Windows 10 / 11 或 macOS |
| 浏览器 | Chrome ≥ 100推荐、Edge ≥ 100 |
| Node.js | ≥ 16.0(用于本地构建) |
| MES-UI 仓库 | `d:\code\mes\mes-ui`,已安装依赖 `pnpm install` |
| 后端服务 | Webman 后台已启动(地址、端口按部署环境),数据库表 `material_category` 已存在 |
| 启动命令 | `pnpm dev``npm run serve`,默认 `http://localhost:8080` |
| 登录账号 | 具备「生产配置」菜单权限的账号,建议使用 `admin` 角色 |
| 网络 | 能正常访问后端 API |
### 1.2 通用前置条件
1. 已完成 `pnpm install`,依赖安装无错误。
2. `pnpm dev` 启动成功,浏览器可访问 `http://localhost:8080`
3. 使用具有「生产配置 / 物料模型 / 物料类别列表」访问权限的账号登录。
4. 后端数据库中 `material_category` 表至少有 1 条数据,用于列表展示和编辑。
5. 中英文语言切换正常:在右上角下拉框切换「中文 / English」所有标签翻译均能显示。
6. 浏览器 DevTools 的 Network 面板可见请求 URL 类似 `production_configuration/matetial_model/matetial_category/list?...`(迁移后保持旧 URL
### 1.3 测试结果总览(按功能)
| 功能 | 章节 | 用例数 | 通过 | 失败 | 阻塞 | 测试人 / 日期 |
|------|------|:----:|:----:|:----:|:----:|---------------|
| 物料类别列表 | 二 | 22 | | | | |
| 物料信息管理 | 三 | 30 | | | | |
---
## 二、物料类别列表Material Category
### 2.1 功能概述
- **一级模块**生产配置Production Master Data
- **二级模块**物料模型Material Model
- **三级模块**物料类别列表Material Category
- **功能说明**:用于维护物料类别(区分原材料和半成品),支持编码、名称、备注、创建时间等字段的增删改查
- **菜单路径**:生产配置 → 物料模型 → 物料类别列表
- **路由地址**`/production_configuration/matetial_model/matetial_category`(迁移阶段沿用旧 URL
- **涉及文件**
- 页面:[src/views/production-master-data/material-model/material-category/index.vue](file:///d:/code/mes/mes-ui/src/views/production-master-data/material-model/material-category/index.vue)
- API[src/api/production-master-data/material-category.js](file:///d:/code/mes/mes-ui/src/api/production-master-data/material-category.js)
- 路由:[src/router/modules/production-master-data.js](file:///d:/code/mes/mes-ui/src/router/modules/production-master-data.js)
- i18n`src/locales/zh-chs.json` & `en.json`key 前缀 `page.production_master_data.material_model.material_category.*`
### 2.2 字段说明
| 字段 | 类型 | 必填 | 长度限制 | 说明 |
|------|------|:----:|---------|------|
| 序号 | 数字 | — | — | 表格自增序号,由 `useTableColumns` 自动生成 |
| 物料类别编码 | 字符串 | ✅ | 1~45 | 唯一标识 |
| 物料类别名称 | 字符串 | ✅ | 1~45 | 类别中文名 |
| 备注 | 字符串 | ❌ | — | 多行文本 |
| 创建时间 | 日期 | — | — | 后端自动填充 |
| 操作 | — | — | — | 行内「编辑」「删除」按钮 |
### 2.3 前置条件
1. 已登录具备「生产配置 / 物料模型 / 物料类别列表」权限的账号。
2. 后端 `material_category` 表存在;若为空,可通过本测试用例的「新增」步骤补足。
3. 浏览器地址栏输入 `/production_configuration/matetial_model/matetial_category` 可直接访问。
4. 当前页面右上角语言切换为「中文」切换为「English」后再次验证关键标签。
### 2.4 测试用例
#### 2.4.1 列表与搜索
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 1.1 | 打开「物料类别列表」页面 | 表格自动加载,列表正常显示;表头依次为:序号 / 物料类别编码 / 物料类别名称 / 备注 / 创建时间 / 操作 | | ☐ |
| 1.2 | 在「物料类别编码」输入框输入已存在的关键字,点击「查询」 | 列表仅显示编码模糊匹配的数据,页码回到 1URL 不暴露搜索值 | | ☐ |
| 1.3 | 在「物料类别名称」输入框输入已存在的关键字,点击「查询」 | 列表仅显示名称模糊匹配的数据 | | ☐ |
| 1.4 | 同时输入编码 + 名称后点击「查询」 | 列表为 AND 条件过滤结果 | | ☐ |
| 1.5 | 在搜索框内按 `Enter` 键 | 触发查询,效果与点击「查询」一致 | | ☐ |
| 1.6 | 点击「重置」按钮 | 搜索框清空,列表恢复初始数据,页码回到 1 | | ☐ |
| 1.7 | 翻到第 2 页,点击「重置」 | 页码回到 1列表刷新 | | ☐ |
| 1.8 | 列表行数超过 1 页时,切换「每页显示条数」 | 列表按新分页重新加载URL / 请求参数同步变化 | | ☐ |
| 1.9 | 切换右上角语言为「English」 | 表头列名翻译正确No. / Category Code / Category Name / Remark / Create Time / Actions | | ☐ |
| 1.10 | 后端返回空数据 | 表格区域显示空数据占位,分页总数为 0 | | ☐ |
#### 2.4.2 新增物料类别
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 2.1 | 点击工具栏「新增」按钮 | 弹出「新增物料类别」对话框,含编码 / 名称 / 备注三个表单项,编码默认聚焦 | | ☐ |
| 2.2 | 编码留空,名称输入「测试类别 A」备注输入「原材料」点击「确定」 | 弹框内编码字段红色错误提示「请输入物料类别编码」;不会提交成功 | | ☐ |
| 2.3 | 编码输入「TEST_001」名称留空点击「确定」 | 名称字段红色错误提示「请输入物料类别名称」 | | ☐ |
| 2.4 | 编码输入 46 个字符(如 46 个 `a`),名称输入「测试类别 A」点击「确定」 | 编码字段提示「长度在 1 到 45 个字符」 | | ☐ |
| 2.5 | 名称输入 46 个字符编码输入「TEST_002」点击「确定」 | 名称字段提示「长度在 1 到 45 个字符」 | | ☐ |
| 2.6 | 编码输入已存在的编码(如数据库现存 `RAW_001`),名称输入「重复测试」,点击「确定」 | 提交失败,弹出后端返回的错误提示(如「编码已存在」);列表不刷新 | | ☐ |
| 2.7 | 编码输入「TEST_001」名称输入「测试类别 A」备注输入「用于半成品分类」点击「确定」 | 提交成功,弹框关闭,顶部提示「操作成功」;列表新增一行 | | ☐ |
| 2.8 | 在弹框中点击「取消」 | 弹框关闭,不提交任何数据 | | ☐ |
| 2.9 | 打开新增弹框后点击右上角 × 关闭 | 弹框关闭,再次打开时表单已重置 | | ☐ |
| 2.10 | 重复 2.7 步骤的编码「TEST_001」再次提交 | 后端返回「编码已存在」或类似错误,不重复创建 | | ☐ |
#### 2.4.3 编辑物料类别
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 3.1 | 在列表中找到「测试类别 A」2.7 创建),点击行内「编辑」 | 弹出「编辑物料类别」对话框,编码 / 名称 / 备注自动回填 | | ☐ |
| 3.2 | 将名称修改为「测试类别 A1」备注改为「原材料-已更新」,点击「确定」 | 提交成功,弹框关闭,提示「操作成功」;列表行名称 / 备注同步更新 | | ☐ |
| 3.3 | 编辑时清空编码并保存 | 编码字段必填提示「请输入物料类别编码」 | | ☐ |
| 3.4 | 编辑时清空名称并保存 | 名称字段必填提示「请输入物料类别名称」 | | ☐ |
| 3.5 | 编辑时将编码修改为与另一行相同的值(如 `RAW_001`),点击「确定」 | 后端返回「编码已存在」错误 | | ☐ |
| 3.6 | 编辑弹框打开后点击「取消」 | 数据不保存,列表无变化 | | ☐ |
| 3.7 | 编辑后重新打开编辑弹框 | 表单仍展示上一次保存后的数据 | | ☐ |
| 3.8 | 编辑成功后检查「创建时间」字段 | 创建时间未变化(仅首次新增时赋值) | | ☐ |
#### 2.4.4 删除物料类别
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 4.1 | 在列表中找到「测试类别 A1」点击行内「删除」 | 弹出确认框「确定要执行该操作吗?」,标题为「提示」 | | ☐ |
| 4.2 | 在确认框中点击「取消」 | 删除取消,列表无变化 | | ☐ |
| 4.3 | 在确认框中点击「确定」 | 确认框关闭,顶部提示「操作成功」;该行从列表中消失 | | ☐ |
| 4.4 | 在仅剩 1 条数据的列表上点击「删除」并确认 | 删除成功后,列表变为空,分页回到第 1 页 | | ☐ |
| 4.5 | 尝试删除仍被「物料信息」引用的物料类别 | 后端返回「存在引用,无法删除」或类似错误 | | ☐ |
| 4.6 | 删除操作期间切换「每页显示条数」 | 删除后页码自动修正,避免出现空页 | | ☐ |
#### 2.4.5 权限与异常场景
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 5.1 | 使用无「新增」权限的账号登录 | 工具栏「新增」按钮不显示或不可点击 | | ☐ |
| 5.2 | 使用无「编辑」权限的账号登录 | 行内「编辑」按钮不显示 | | ☐ |
| 5.3 | 使用无「删除」权限的账号登录 | 行内「删除」按钮不显示 | | ☐ |
| 5.4 | 断网后刷新页面 | 表格显示加载失败或空态DevTools Network 显示请求失败 | | ☐ |
| 5.5 | 后端返回 500 错误(如临时停服) | 顶部红色错误提示(如「操作失败」),不卡死页面 | | ☐ |
| 5.6 | 同时打开两个浏览器标签页,在 A 标签新增数据后B 标签刷新列表 | B 标签列表应能看到 A 标签新增的数据 | | ☐ |
#### 2.4.6 国际化与界面
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 6.1 | 中文状态下打开新增弹框 | 弹框标题、字段标签、按钮文字均为中文 | | ☐ |
| 6.2 | 切换为「English」后再次打开新增弹框 | 弹框标题「Add Material Category」按钮「Confirm / Cancel」 | | ☐ |
| 6.3 | 中文状态下点击删除,确认弹框标题为「提示」 | 确认框标题与按钮文字中文显示 | | ☐ |
| 6.4 | 英文状态下点击删除确认弹框标题为「Tip」 | 确认框英文显示 | | ☐ |
| 6.5 | 列表右上角「帮助」按钮(? 图标) | 鼠标悬停或点击显示「物料类别用于区分原材料和半成品」 | | ☐ |
| 6.6 | 备注字段为空时点击保存 | 提交成功,列表中备注列空白(无 `null` / `undefined` 文本) | | ☐ |
### 2.5 接口契约(用于前后端联调核对)
| 方法 | URL | 旧 method 名 | 入参关键 key | 备注 |
|------|-----|-------------|-------------|------|
| GET | `production_configuration/matetial_model/matetial_category/list` | `production_configuration_matetial_model_matetial_category_list` | `code / name / page_no / page_size` | 列表查询 |
| GET | `…/all` | `…_all` | — | 全部类别(下拉框用,可选) |
| POST | `…/create` | `…_create` | `code / name / remark` | 新增 |
| PUT | `…/edit` | `…_edit` | `id / code / name / remark` | 编辑(`id` 为行主键) |
| DELETE | `…/delete` | `…_delete` | `id: [rowId]` | 删除,参数名 `id` 数组(与旧项目保持一致) |
### 2.6 问题记录
> 测试人员发现问题时填写。每条问题一行,格式:`[编号] [用例编号] [现象] [复现步骤] [期望] [截图/日志] [负责人] [处理状态]`。
| 编号 | 用例 | 现象 | 复现步骤 | 期望 | 截图/日志 | 负责人 | 状态 |
|:---:|:---:|------|---------|------|----------|:----:|:----:|
| | | | | | | | |
### 2.7 备注
- 本页面沿用旧 URL 与后台 method 名,待后台数据库路由表统一更新后统一修改。
- 涉及 `confirmMixin` / `useTableColumns` / `useTableButtons` / `i18nMixin` 等公共 Composable如其他页面出现类似问题先确认是否在迁移组件时有遗漏。
- 若新增 / 编辑成功后接口返回结构变化(`res.data` 包裹层调整),需要同步更新 `fetchData` 的解析逻辑。
---
## 三、物料信息管理Material Master
### 3.1 功能概述
- **一级模块**生产配置Production Master Data
- **二级模块**物料模型Material Model
- **三级模块**物料信息管理Material Master
- **功能说明**:用于维护物料主数据,包括物料编码、名称、所属物料类别、单位、备注等,支持新增、编辑、删除、批量删除、按编码/名称/类别检索。
- **菜单路径**:生产配置 → 物料模型 → 物料信息管理
- **路由地址**`/production_configuration/matetial_model/matetial_management`(迁移阶段沿用旧 URL
- **涉及文件**
- 页面:[src/views/production-master-data/material-model/material-master/index.vue](file:///d:/code/mes/mes-ui/src/views/production-master-data/material-model/material-master/index.vue)
- API[src/api/production-master-data/material-master.js](file:///d:/code/mes/mes-ui/src/api/production-master-data/material-master.js)
- 路由:[src/router/modules/production-master-data.js](file:///d:/code/mes/mes-ui/src/router/modules/production-master-data.js)
- i18n`src/locales/zh-chs.json` & `en.json`key 前缀 `page.production_master_data.material_model.material_master.*`
### 3.2 字段说明
| 字段 | 类型 | 必填 | 长度限制 | 说明 |
|------|------|:----:|---------|------|
| 序号 | 数字 | — | — | 表格自增序号 |
| 物料编码 | 字符串 | ✅ | 1~100 | 唯一标识 |
| 物料名称 | 字符串 | ✅ | 1~100 | 物料中文名 |
| 物料类别 | 下拉 | ✅ | — | 来源于物料类别下拉(依赖「物料类别列表」已迁移) |
| 单位 | 输入/下拉 | ❌ | — | 当前版本以文本框占位;待「计量单位」模块迁移后接入下拉数据源 |
| 备注 | 字符串 | ❌ | — | 多行文本,超过 20 字符鼠标悬停展示全量 |
| 创建人 | 字符串 | — | — | 后端返回 |
| 创建时间 | 日期 | — | — | 后端自动填充 |
| 操作 | — | — | — | 行内「编辑」「删除」按钮 |
### 3.3 前置条件
1. 已登录具备「生产配置 / 物料模型 / 物料信息管理」权限的账号。
2. 已完成「物料类别列表」迁移,「物料类别」下拉数据正常加载(用于新增/编辑时的类别选择)。
3. 后端 `material` 表存在;若为空,可通过本测试用例的「新增」步骤补足。
4. 浏览器地址栏输入 `/production_configuration/matetial_model/matetial_management` 可直接访问。
5. 当前页面右上角语言切换为「中文」切换为「English」后再次验证关键标签。
### 3.4 测试用例
#### 3.4.1 列表与搜索
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 1.1 | 打开「物料信息管理」页面 | 表格自动加载,列表正常显示;表头依次为:序号 / 物料编码 / 物料名称 / 物料类别 / 单位 / 备注 / 创建人 / 创建时间 / 操作 | | ☐ |
| 1.2 | 物料类别下拉可正常展开,选项来源于物料类别数据 | 下拉选项与「物料类别列表」一致,支持搜索过滤 | | ☐ |
| 1.3 | 在「物料编码」输入框输入已存在的关键字,点击「查询」 | 列表仅显示编码模糊匹配的数据,页码回到 1 | | ☐ |
| 1.4 | 在「物料名称」输入框输入已存在的关键字,点击「查询」 | 列表仅显示名称模糊匹配的数据 | | ☐ |
| 1.5 | 在「物料类别」下拉中选择某一项,点击「查询」 | 列表仅显示该类别下的物料 | | ☐ |
| 1.6 | 同时输入编码 + 名称 + 类别后点击「查询」 | 列表为 AND 条件过滤结果 | | ☐ |
| 1.7 | 在搜索框内按 `Enter` 键 | 触发查询,效果与点击「查询」一致 | | ☐ |
| 1.8 | 点击「重置」按钮 | 搜索框清空,列表恢复初始数据,页码回到 1 | | ☐ |
| 1.9 | 翻到第 2 页,点击「重置」 | 页码回到 1列表刷新 | | ☐ |
| 1.10 | 列表行数超过 1 页时,切换「每页显示条数」 | 列表按新分页重新加载,请求参数 `page_size` 同步变化 | | ☐ |
| 1.11 | 切换右上角语言为「English」 | 表头列名翻译正确No. / Material Code / Material Name / Category / Unit / Remark / Created By / Created At / Action | | ☐ |
| 1.12 | 备注长度 > 20 字符时,鼠标悬停单元格 | 弹层显示完整备注内容 | | ☐ |
| 1.13 | 备注长度 <= 20 字符时 | 单元格直接展示文本,不显示弹层 | | ☐ |
| 1.14 | 后端返回空数据 | 表格区域显示空数据占位,分页总数为 0 | | ☐ |
#### 3.4.2 新增物料信息
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 2.1 | 点击工具栏「新增」按钮 | 弹出「新增物料信息」对话框,依次为:物料编码 / 物料名称 / 物料类别 / 单位 / 备注 | | ☐ |
| 2.2 | 编码留空,名称输入「测试物料 A」类别下拉选择「原材料」点击「确定」 | 编码字段红色错误提示「请输入物料编码」 | | ☐ |
| 2.3 | 编码输入「MAT_001」名称留空点击「确定」 | 名称字段红色错误提示「请输入物料名称」 | | ☐ |
| 2.4 | 编码、名称都填写,类别留空,点击「确定」 | 类别字段红色错误提示「请选择物料类别」 | | ☐ |
| 2.5 | 编码输入 101 个字符(如 101 个 `a`),名称输入「测试物料 A」点击「确定」 | 编码字段提示「长度在 1 到 100 个字符」 | | ☐ |
| 2.6 | 名称输入 101 个字符编码输入「MAT_002」点击「确定」 | 名称字段提示「长度在 1 到 100 个字符」 | | ☐ |
| 2.7 | 编码输入已存在的编码,名称输入「重复测试」,点击「确定」 | 提交失败,弹出后端返回的错误提示(如「编码已存在」);列表不刷新 | | ☐ |
| 2.8 | 编码输入「MAT_001」名称输入「测试物料 A」类别选择「原材料」单位输入「个」备注输入「用于产线领料」点击「确定」 | 提交成功,弹框关闭,顶部提示「操作成功」;列表新增一行且所有字段正确展示 | | ☐ |
| 2.9 | 在弹框中点击「取消」 | 弹框关闭,不提交任何数据 | | ☐ |
| 2.10 | 打开新增弹框后点击右上角 × 关闭,再次点击「新增」 | 弹框再次打开时表单已重置 | | ☐ |
| 2.11 | 重复 2.8 步骤的编码「MAT_001」再次提交 | 后端返回「编码已存在」或类似错误,不重复创建 | | ☐ |
#### 3.4.3 编辑物料信息
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 3.1 | 在列表中找到「MAT_001」2.8 创建),点击行内「编辑」 | 弹出「编辑物料信息」对话框,编码 / 名称 / 类别 / 单位 / 备注自动回填 | | ☐ |
| 3.2 | 将名称修改为「测试物料 A1」类别改为「半成品」单位改为「箱」备注改为「用于产线补料」点击「确定」 | 提交成功,弹框关闭,提示「操作成功」;列表行各字段同步更新 | | ☐ |
| 3.3 | 编辑时清空编码并保存 | 编码字段必填提示「请输入物料编码」 | | ☐ |
| 3.4 | 编辑时清空名称并保存 | 名称字段必填提示「请输入物料名称」 | | ☐ |
| 3.5 | 编辑时清空类别并保存 | 类别字段必填提示「请选择物料类别」 | | ☐ |
| 3.6 | 编辑时将编码修改为与另一行相同的值,点击「确定」 | 后端返回「编码已存在」错误 | | ☐ |
| 3.7 | 编辑弹框打开后点击「取消」 | 数据不保存,列表无变化 | | ☐ |
| 3.8 | 编辑后重新打开编辑弹框 | 表单仍展示上一次保存后的数据 | | ☐ |
| 3.9 | 编辑成功后检查「创建时间」字段 | 创建时间未变化(仅首次新增时赋值) | | ☐ |
| 3.10 | 编辑时清空备注并保存 | 提交成功,列表中备注列空白(无 `null` / `undefined` 文本) | | ☐ |
#### 3.4.4 删除与批量删除
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 4.1 | 在列表中找到「MAT_001」点击行内「删除」 | 弹出确认框「确定要执行该操作吗?」,标题为「提示」 | | ☐ |
| 4.2 | 在确认框中点击「取消」 | 删除取消,列表无变化 | | ☐ |
| 4.3 | 在确认框中点击「确定」 | 确认框关闭,顶部提示「操作成功」;该行从列表中消失 | | ☐ |
| 4.4 | 在仅剩 1 条数据的列表上点击「删除」并确认 | 删除成功后,列表变为空,分页回到第 1 页 | | ☐ |
| 4.5 | 不勾选任何数据,直接点击工具栏「批量删除」 | 顶部红色错误提示「请先选择要删除的数据」 | | ☐ |
| 4.6 | 勾选 3 条数据,点击「批量删除」,确认框标题与按钮中文显示 | 弹出确认框「确定要删除所选物料吗?」 | | ☐ |
| 4.7 | 在 4.6 弹出的确认框中点击「确定」 | 3 条数据全部删除,顶部提示「操作成功」;列表刷新 | | ☐ |
| 4.8 | 尝试删除被其他业务(如 BOM引用的物料 | 后端返回「存在引用,无法删除」或类似错误 | | ☐ |
| 4.9 | 删除操作期间切换「每页显示条数」 | 删除后页码自动修正,避免出现空页 | | ☐ |
#### 3.4.5 权限与异常场景
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 5.1 | 使用无「新增」权限的账号登录 | 工具栏「新增」按钮不显示或不可点击 | | ☐ |
| 5.2 | 使用无「编辑」权限的账号登录 | 行内「编辑」按钮不显示 | | ☐ |
| 5.3 | 使用无「删除」权限的账号登录 | 行内「删除」按钮不显示 | | ☐ |
| 5.4 | 使用无「批量删除」权限的账号登录 | 工具栏「批量删除」按钮不显示或不可点击 | | ☐ |
| 5.5 | 断网后刷新页面 | 表格显示加载失败或空态DevTools Network 显示请求失败 | | ☐ |
| 5.6 | 后端返回 500 错误(如临时停服) | 顶部红色错误提示(如「操作失败」),不卡死页面 | | ☐ |
| 5.7 | 物料类别下拉数据加载失败时进入新增弹框 | 类别下拉为空,但仍可正常打开弹框 | | ☐ |
| 5.8 | 同时打开两个浏览器标签页,在 A 标签新增数据后B 标签刷新列表 | B 标签列表应能看到 A 标签新增的数据 | | ☐ |
#### 3.4.6 国际化与界面
| # | 操作步骤 | 预期结果 | 实际结果 | 通过 |
|---|---------|---------|---------|:----:|
| 6.1 | 中文状态下打开新增弹框 | 弹框标题、字段标签、按钮文字均为中文 | | ☐ |
| 6.2 | 切换为「English」后再次打开新增弹框 | 弹框标题「Add Material」按钮「Confirm / Cancel」 | | ☐ |
| 6.3 | 中文状态下点击删除,确认弹框标题为「提示」 | 确认框标题与按钮文字中文显示 | | ☐ |
| 6.4 | 英文状态下点击删除确认弹框标题为「Tip」 | 确认框英文显示 | | ☐ |
| 6.5 | 列表右上角「帮助」按钮(? 图标) | 鼠标悬停或点击显示「物料信息用于维护物料编码、名称、规格等属性」 | | ☐ |
| 6.6 | 中文状态下批量删除无选中数据 | 错误提示「请先选择要删除的数据」 | | ☐ |
| 6.7 | 英文状态下批量删除无选中数据 | 错误提示「Please select data first」 | | ☐ |
### 3.5 接口契约(用于前后端联调核对)
| 方法 | URL | 旧 method 名 | 入参关键 key | 备注 |
|------|-----|-------------|-------------|------|
| GET | `production_configuration/matetial_model/matetial_management/list` | `production_configuration_matetial_model_matetial_management_list` | `code / name / bom_source_category_id / page_no / page_size` | 列表查询 |
| GET | `…/all` | `…_all` | — | 全部物料(下拉框用,可选) |
| POST | `…/create` | `…_create` | `code / name / bom_source_category_id / unit_id / remark` | 新增 |
| PUT | `…/edit` | `…_edit` | `id / code / name / bom_source_category_id / unit_id / remark` | 编辑(`id` 为行主键) |
| DELETE | `…/delete` | `…_delete` | `id: [rowId]` | 单条删除,参数名 `id` 数组(与旧项目保持一致) |
| DELETE | `…/batch_delete` | `…_batch_delete` | `id: [id1, id2, …]` | 批量删除 |
| POST | `…/get_import_template` | `…_get_import_template` | — | 导入模板下载(响应 `blob`),本版本预留 |
| POST | `…/matetial_data_import` | `…_matetial_data_import` | `import_data: JSON.stringify([...])` | 物料数据导入,本版本预留 |
| POST | `…/matetial_data_export_task` | `…_matetial_data_export_task` | — | 物料数据导出任务创建,本版本预留 |
> 说明:本版本优先实现列表 / 新增 / 编辑 / 删除 / 批量删除五大核心功能;导入 / 导出Excel 模板下载、批量导入、导出任务)保留 API 方法和钩子位置,待后续迭代中补齐弹框 UI。
### 3.6 问题记录
> 测试人员发现问题时填写。每条问题一行,格式:`[编号] [用例编号] [现象] [复现步骤] [期望] [截图/日志] [负责人] [处理状态]`。
| 编号 | 用例 | 现象 | 复现步骤 | 期望 | 截图/日志 | 负责人 | 状态 |
|:---:|:---:|------|---------|------|----------|:----:|:----:|
| | | | | | | | |
### 3.7 备注
- 本页面沿用旧 URL 与后台 method 名,待后台数据库路由表统一更新后统一修改。
- 「物料类别」下拉数据由 `getMaterialCategoryAll` 提供,依赖「物料类别列表」功能已迁移完成;如该下拉为空,请先检查该模块是否正常运行。
- 「单位」字段在当前版本以文本框占位,依赖「计量单位」模块迁移后接入下拉数据源(与 BOM 等联动),测试时需在「备注」中注明该功能尚未启用。
- 涉及 `confirmMixin` / `useTableColumns` / `useTableButtons` / `i18nMixin` 等公共 Composable如其他页面出现类似问题先确认是否在迁移组件时有遗漏。
- 备注长度 > 20 字符时使用 `el-popover` 悬停展示全量内容;该交互与旧项目保持一致。
- 若新增 / 编辑成功后接口返回结构变化(`res.data` 包裹层调整),需要同步更新 `fetchData` 的解析逻辑。

161
docs/迁移提示词.md Normal file
View File

@@ -0,0 +1,161 @@
## 任务:迁移旧 CRUD 页面到新版 page-table + page-dialog-form 方案
### 输入
用户会提供一个旧 CRUD 页面的文件路径列表和对照表信息。
---
### 迁移规则(必须严格遵守)
#### 1. 组件方案
- 使用 `<page-table>` + `<page-dialog-form>` 替代旧版 `<sct-base-table>` + `<sct-base-dialog>` + `<SctBaseForm>`
- 使用 `useTableColumns()` 生成列定义(不再手动分配 idx
- 使用 `useTableButtons()` 生成工具栏按钮和行内按钮(不再分开写 buttonList / tableButtonList
- 使用 `i18nMixin(prefix)` 注入 `key()``ckey()` 方法
- 参考文档:[表格组件使用说明.md](/docs/表格组件使用说明.md)
- 参考示例:`src/views/production-master-data/factory-model/factory-area/index.vue`
#### 1.1 特殊弹出框组件迁移(重要)
当旧页面中存在**超出 `page-dialog-form` 能力的弹出框**时(权限分配树、批量导入、关联选择器、详情查看、多步骤向导等),必须遵循以下流程:
##### 第一步:分析旧代码
- **仔细阅读旧项目的弹出框代码**理解其数据结构、交互逻辑、API 调用
- 关注旧代码的数据来源路径(如 `row.menu_admin` 直接从列表获取、还是额外调 API
- 记录旧的参数名、method 名,确保迁移时不遗漏
##### 第二步:提出优化方案
迁移时**不能简单照搬旧代码**,必须结合新版能力提出优化:
| 旧写法 | 优化方向 |
|--------|---------|
| `el-dialog` 内联在页面中 | 抽离为独立组件 → `components/` |
| `sct-base-dialog` + 内联表单 | 独立组件 + `el-drawer`(抽屉式体验更佳) |
| 额外调 API 获取数据(如行数据已包含) | 直接从 `row.xxx` 取值,减少请求 |
| `setTimeout` 硬编码延迟 | 提出来讨论,结合 `v-if` + `$nextTick` 优化 |
| `$parent` / `$refs` 跨组件通信 | 改为 `props` + `$emit` |
示例:角色权限分配迁移优化方案
```
旧方案 优化方案
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
el-dialog 内联 42 行代码 → 独立 PermDrawer 组件components/PermDrawer/index.vue
getRoleMenu API 额外请求 → 直接从 row.menu_admin JSON.parse 获取(列表自带)
setTimeout 1000ms 关闭 → 保留(树渲染需要等待),但抽取到子组件内部
索引页 data 6 个 perm 字段 → 仅 2 个permVisible + permRole
```
##### 第三步:按标准实现
参考 [表格组件使用说明.md 第 13 节](/docs/表格组件使用说明.md#13-特殊弹出框组件规范),严格遵循:
| 规则 | 说明 |
|------|------|
| 目录位置 | `src/views/{模块}/{功能}/components/{英文PascalCase}/index.vue` |
| 文件夹命名 | 英文 PascalCase描述功能`PermDrawer``ImportDialog` |
| 组件通信 | 父→子 `props`(含 `.sync`),子→父 `$emit('saved')`,禁止 `$parent` / `$refs` |
| 主页面数据 | 只存 `visible` Boolean + 业务对象,其余状态在子组件内部 |
##### 第四步:完整案例
参考角色权限分配抽屉的完整迁移:
- 旧代码:`/home/james/WEBMAN-VUE-APP-develop/src/views/system_settings/user_management/role/components/PageMain/index.vue``dialogVisibleGive` + `el-tree`
- 新代码:[`/home/james/WEBMAN-VUE-APP-V2-develop/mes-ui-d2/src/views/system-administration/user-management/role/components/PermDrawer/index.vue`](/src/views/system-administration/user-management/role/components/PermDrawer/index.vue)
- 主页面引用:[`src/views/system-administration/user-management/role/index.vue`](/src/views/system-administration/user-management/role/index.vue#L79-L87)
---
#### 2. i18n 国际化(重要)
- 使用 `mixins: [i18nMixin('完整i18n前缀')]`,不要在每个页面手动定义 `T` 常量和 `tkey()` 方法
- `data()` 中用 `this.key('xxx')` 传完整 i18n key**不要用 `k()` 提前翻译**(翻译由 page-table / page-dialog-form 内部处理,切换语言自动响应)
- 模板搜索区用 `$t(key('xxx'))`,公共 key 用 `$t(ckey('xxx'))`
- 语言包必须中英文同步添加(`zh-chs.json` + `en.json`
- 参考文档:[国际化规则.md](/docs/国际化规则.md)
#### 3. 文件夹命名(重要)
- 文件夹名称遵循 [后台Webman界面截图对照表](/后台Webman界面截图对照表.md) 的 snake_case/kebab-case 命名
- 目录示例:`src/views/production-master-data/factory-model/factory-area/`
- 路由模块:`src/router/modules/production-master-data.js`
- API 文件:`src/api/production-master-data/factory-area.js`
#### 4. 路由 path 和 API BASE URL重要 — 临时方案)
- **路由 path** 和 **API BASE URL** **暂时保留旧项目的命名**,因为后台数据库的路由表还未更新
- 示例:目录按对照表叫 `production-master-data`,但路由 path 保持旧值 `production_configuration`
```js
// src/router/modules/production-master-data.js
path: '/production_configuration', // 旧值暂留
```
```js
// src/api/production-master-data/factory-area.js
const BASE = 'production_configuration/factory_model/factory_area/' // 旧值暂留
```
- 后续统一修改路由后再批量替换
#### 4.1 API 参数名必须对齐旧项目(重要)
- **API 函数入参的 key 名称必须与旧项目保持一致**,不能自行发明参数名
- 例如:旧项目角色菜单接口参数是 `role_id`,不能写成 `id`
```js
// ❌ 错误 — 自行发明参数名
getRoleMenu({ id: this.roleId })
// ✅ 正确 — 与旧项目参数名一致
getRoleMenu({ role_id: this.roleId })
```
- **迁移 API 时必须仔细阅读旧项目接口代码**,逐个核对每个接口的入参 key 名称
- 如果后端报「xxx 不能为空」,首先检查参数 key 是否与旧项目一致
#### 5. 旧 key → 新 key 映射
如果用户提供的是旧页面代码,需要根据对照表做 key 映射。已知映射如下(持续补充):
| 旧 key 前缀 | 新 key 前缀 |
|------------|------------|
| `page.production_configuration.factory_model.factory_area` | `page.production_master_data.factory_model.factory_area` |
| `page.system_settings.user_management.role` | `page.system_administration.user_management.role` |
| `page.system_settings.user_management.user` | `page.system_administration.user_management.user` |
| `page.system_settings.menu_configuration.menu` | `page.system_administration.menu_management.menu_configuration` |
| `page.system_settings.system_assistant.operate_log` | `page.system_administration.system_utilities.operation_logs` |
| `page.system_settings.system_assistant.api_log` | `page.system_administration.system_utilities.api_logs` |
| `page.system_settings.system_assistant.problem_help` | `page.system_administration.system_utilities.problem_help` |
| `page.system_settings.system_monitoring.system.login` | `page.system_administration.system_monitoring.login` |
| `page.production_configuration.matetial_model.*` | `page.production_master_data.material_model.*` |
| `page.planning_production.production_batch_management.batch` | `page.planning_production.batch_management.batch_list` |
| `page.data_middleground.basic_traceability.*` | `page.data_platform.traceability.*` |
#### 6. 处理流程(每迁移一个页面执行以下步骤)
1. **确定对照表位置**:从 [后台Webman界面截图对照表](/后台Webman界面截图对照表.md) 找到对应行的英文名,转换为 snake_case
2. **创建目录结构**`src/views/{一级snake_case}/{二级snake_case}/{三级snake_case}/`
3. **创建 API 文件**`src/api/{一级snake_case}/{二级snake_case}/{三级snake_case}.js`BASE URL 暂用旧值
4. **添加路由模块**`src/router/modules/{一级snake_case}.js`path 暂用旧值
5. **编写页面代码**:使用 page-table + page-dialog-form 方案
6. **添加 i18n**:在 `zh-chs.json` 和 `en.json` 中添加对应 key
7. **验证 JSON 合法性**`node -e "JSON.parse(require('fs').readFileSync('src/locales/zh-chs.json','utf8'))"`
---
### 页面模板(通用 CRUD 页面骨架)
参考 `src/views/production-master-data/factory-model/factory-area/index.vue` 的结构,核心模式:
- **Script**`mixins: [i18nMixin('page.{一}.{二}.{三}')]` + `data()` 中用 `this.key('xxx')` 传 key
- **Template**`<page-table>` 传 columns/data/loading/toolbarButtons/rowButtons/pagination + `<page-dialog-form>` 传 formCols/formData/rules/title
- **Buttons**`useTableButtons({ toolbar: [...], row: [...] }, this.$permission)`
- **Columns**`useTableColumns([...])`
- **Methods**`fetchData / onSearch / onReset / onPageChange / openAdd / openEdit / onDialogSubmit / handleDelete`
- **i18n key 模板**(每个页面至少要有这些):`search / reset / add / edit / delete / operation / add_title / edit_title / code / name / remark / enter_code / enter_name / remark_length / operation_success / confirm / cancel / tip / confirm_delete`
- **搜索条件过多时**参考 [表格组件使用说明.md - 场景 8](/docs/表格组件使用说明.md#场景-8折叠式搜索区搜索条件过多时),使用 `searchExpanded` + `v-show` 实现折叠式搜索区,需额外添加 i18n key`expand`(展开更多/Expand、`collapse`(收起/Collapse
#### 6.1 依赖安装
当迁移涉及新的第三方库时:
1. **包管理器**:本项目使用 **pnpm**,安装命令为 `pnpm add <package-name>`
2. **安装前检查**:先在 `package.json` 中确认依赖是否已存在,避免重复安装
3. **版本兼容**:确保安装的包支持 Vue 2.x本项目为 Vue 2.7
4. **参考标准**[表格组件使用说明.md - 第 11 节](/docs/表格组件使用说明.md#11-依赖安装规范)
---
### 输出要求
- 创建完整的页面文件、路由模块、API 文件
- 在 `zh-chs.json` 和 `en.json` 中添加对应 i18n key中文和英文同步
- 完成后提醒用户验证 JSON 合法性
- 如涉及对照表中已有映射的 key 前缀变更,自动纠正为新的 key 前缀

25
docs/运行提示词.md Normal file
View File

@@ -0,0 +1,25 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD> Ǩ<><C7A8><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>.md <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>˵<EFBFBD><CBB5>.md <20><> <20><>̨Webman<61><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ձ<EFBFBD>.md <20>е<EFBFBD><D0B5><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>С<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ǩ<EFBFBD>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǩ<EFBFBD>ƺ<EFBFBD><C6BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ϸ<EFBFBD>Ĺ<EFBFBD><C4B9>ܲ<EFBFBD><DCB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>ָ<EFBFBD>ϡ<EFBFBD><CFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><E8B0B4><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>в<EFBFBD><D0B2>ԣ<EFBFBD><D4A3>Բ<EFBFBD><D4B2><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>й<EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD>δͨ<CEB4><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>ҪҪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
1. <20>˲<EFBFBD><CBB2><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ķ<EFBFBD>ʽ<EFBFBD><CABD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD>Ǩ<EFBFBD>ƺ󣬽<C6BA><F3A3ACBD>¹<EFBFBD><C2B9>ܵIJ<DCB5><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷŵ<DDB7>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>
2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸҪ<CFB8>أ<EFBFBD>
- <20><><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>
- <20><><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
- <20><>ϸ<EFBFBD>IJ<EFBFBD><C4B2>Բ<EFBFBD><D4B2>裨ÿ<E8A3A8><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ˵<C8B7><CBB5><EFBFBD><EFBFBD>
- Ԥ<>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5A1A2><EFBFBD><EFBFBD>֤<EFBFBD><D6A4>
- ʵ<>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><><CAA7>״̬<D7B4><CCAC><EFBFBD><EFBFBD>
- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>
3. ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD><CCB8><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD>к<EFBFBD><D0BA>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><E0BCAD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>Ȩ<EFBFBD>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>
4. <20>ĵ<EFBFBD><C4B5><EFBFBD>ʽӦ<CABD><D3A6><EFBFBD><EFBFBD><EFBFBD>׶<EFBFBD><D7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>в<EFBFBD><D0B2><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>

39947
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,15 @@
{ {
"name": "d2-admin", "name": "d2-admin",
"version": "1.25.0", "version": "1.25.0",
"packageManager": "pnpm@10.33.0",
"engines": {
"node": ">=20.19.0",
"pnpm": ">=10.33.0 <11"
},
"scripts": { "scripts": {
"serve": "vue-cli-service serve --open", "serve": "vue-cli-service serve --open",
"start": "npm run serve", "start": "pnpm run serve",
"dev": "npm run serve", "dev": "pnpm run serve",
"build": "vue-cli-service build --report", "build": "vue-cli-service build --report",
"build:preview": "NODE_OPTIONS=--max_old_space_size=4096 vue-cli-service build --mode preview", "build:preview": "NODE_OPTIONS=--max_old_space_size=4096 vue-cli-service build --mode preview",
"lint": "vue-cli-service lint --fix", "lint": "vue-cli-service lint --fix",
@@ -20,6 +25,7 @@
"core-js": "^3.24.1", "core-js": "^3.24.1",
"countup.js": "^2.3.2", "countup.js": "^2.3.2",
"dayjs": "^1.11.5", "dayjs": "^1.11.5",
"echarts": "5.1.0",
"element-ui": "^2.15.9", "element-ui": "^2.15.9",
"faker": "^4.1.0", "faker": "^4.1.0",
"flex.css": "^1.1.7", "flex.css": "^1.1.7",
@@ -27,13 +33,15 @@
"github-markdown-css": "^4.0.0", "github-markdown-css": "^4.0.0",
"highlight.js": "^10.7.3", "highlight.js": "^10.7.3",
"hotkeys-js": "^3.9.5", "hotkeys-js": "^3.9.5",
"js-cookie": "^2.2.1", "js-cookie": "3.0.7",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lowdb": "^1.0.0", "lowdb": "^1.0.0",
"marked": "^2.1.3", "marked": "^2.1.3",
"mavon-editor": "^2.10.4",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"qs": "^6.11.0", "qs": "^6.11.0",
"quill": "^1.3.7", "quill": "^1.3.7",
"relation-graph": "2.2.11",
"screenfull": "^5.2.0", "screenfull": "^5.2.0",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",
"ua-parser-js": "^0.8.1", "ua-parser-js": "^0.8.1",
@@ -45,7 +53,8 @@
"vue-router": "^3.6.2", "vue-router": "^3.6.2",
"vue-splitpane": "^1.0.6", "vue-splitpane": "^1.0.6",
"vue-ueditor-wrap": "^2.5.6", "vue-ueditor-wrap": "^2.5.6",
"vuex": "^3.6.2" "vuex": "^3.6.2",
"xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@d2-projects/vue-filename-injector": "^1.1.1", "@d2-projects/vue-filename-injector": "^1.1.1",
@@ -70,8 +79,8 @@
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"less": "^3.13.1", "less": "^3.13.1",
"less-loader": "^7.3.0", "less-loader": "^7.3.0",
"sass": "^1.54.5", "sass": "1.54.5",
"sass-loader": "^10.3.1", "sass-loader": "~10.5.2",
"svg-sprite-loader": "^4.3.0", "svg-sprite-loader": "^4.3.0",
"text-loader": "^0.0.1", "text-loader": "^0.0.1",
"vue-cli-plugin-i18n": "^1.0.1", "vue-cli-plugin-i18n": "^1.0.1",
@@ -87,5 +96,13 @@
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/d2-projects/d2-admin.git" "url": "https://github.com/d2-projects/d2-admin.git"
},
"volta": {
"node": "20.19.0"
},
"pnpm": {
"overrides": {
"@achrinza/node-ipc": ">=9.2.7"
}
} }
} }

15879
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -5,6 +5,7 @@ import { get, isEmpty, merge } from 'lodash'
import qs from 'qs' import qs from 'qs'
import util from '@/libs/util' import util from '@/libs/util'
import store from '@/store' import store from '@/store'
import router from '@/router'
/** /**
* @description 记录和显示错误 * @description 记录和显示错误
@@ -80,20 +81,30 @@ function createService () {
} }
// 有 code 判断为项目接口请求 // 有 code 判断为项目接口请求
let errorMessage = ''
switch (response.data.code) { switch (response.data.code) {
// 返回响应内容
case 0: return response.data.data case 0: return response.data.data
// 例如在 code 401 情况下退回到登录页面 case 401:
case 401: throw new Error('请重新登录') util.cookies.remove('token')
// 根据需要添加其它判断 router.replace({ name: 'login' })
default: throw new Error(`${response.data.msg}: ${response.config.url}`) break
default:
errorMessage = response.data.msg || '请求失败'
break
} }
const businessError = new Error(`${errorMessage}: ${response.config.url}`)
handleError(businessError)
throw businessError
}, },
error => { error => {
const status = get(error, 'response.status') const status = get(error, 'response.status')
switch (status) { switch (status) {
case 400: error.message = '请求错误'; break case 400: error.message = '请求错误'; break
case 401: error.message = '未授权,请登录'; break case 401:
util.cookies.remove('token')
router.replace({ name: 'login' })
error.message = '未授权,请登录'
break
case 403: error.message = '拒绝访问'; break case 403: error.message = '拒绝访问'; break
case 404: error.message = `请求地址出错: ${error.response.config.url}`; break case 404: error.message = `请求地址出错: ${error.response.config.url}`; break
case 408: error.message = '请求超时'; break case 408: error.message = '请求超时'; break
@@ -125,13 +136,15 @@ function createRequest (service) {
const token = util.cookies.get('token') const token = util.cookies.get('token')
const configDefault = { const configDefault = {
headers: { headers: {
Authorization: token,
'Content-Type': get(config, 'headers.Content-Type', 'application/json') 'Content-Type': get(config, 'headers.Content-Type', 'application/json')
}, },
timeout: 5000, timeout: 5000,
baseURL: process.env.VUE_APP_API, baseURL: process.env.VUE_APP_API,
data: {} data: {}
} }
if (token) {
configDefault.headers.Authorization = 'Bearer ' + token
}
const option = merge(configDefault, config) const option = merge(configDefault, config)
// 处理 get 请求的参数 // 处理 get 请求的参数
// 请根据实际需要修改 // 请根据实际需要修改
@@ -141,7 +154,7 @@ function createRequest (service) {
} }
// 当需要以 form 形式发送时 处理发送的数据 // 当需要以 form 形式发送时 处理发送的数据
// 请根据实际需要修改 // 请根据实际需要修改
if (!isEmpty(option.data) && option.headers['Content-Type'] === 'application/x-www-form-urlencoded') { if (!isEmpty(option.data) && option.headers['Content-Type'] === 'application/x-www-form-urlen·coded') {
option.data = stringify(option.data) option.data = stringify(option.data)
} }
return service(option) return service(option)

33
src/api/auth.js Normal file
View File

@@ -0,0 +1,33 @@
import { request } from '@/api/_service'
/**
* 账号登录
* @param {Object} data
* @param {string} data.username
* @param {string} data.password
*/
export function loginAdminUser (data) {
return request({
url: 'login',
method: 'post',
data: {
method: 'login',
platform: 'background',
...data
}
})
}
/**
* 注销当前已登录的账号
*/
export function logoutAdminUser () {
return request({
url: 'logout',
method: 'post',
data: {
method: 'logout',
platform: 'background'
}
})
}

View File

@@ -0,0 +1,43 @@
import { request } from '@/api/_service'
const BASE = 'data_middleground/eagle_eyes/'
function apiParams (method, data = {}) {
return {
method,
platform: 'admin',
...data
}
}
export function getNGWorkstationBatch (data) {
return request({
url: BASE + 'getNGWorkstationBatch',
method: 'get',
params: apiParams('data_middleground_eagle_eyes_getNGWorkstationBatch', data)
})
}
export function getBatchResultParam (data) {
return request({
url: BASE + 'getBatchResultParam',
method: 'get',
params: apiParams('data_middleground_eagle_eyes_getBatchResultParam', data)
})
}
export function analyzeHawkeyeCorrelation (data) {
return request({
url: BASE + 'saveCsvFile',
method: 'get',
params: apiParams('data_middleground_eagle_eyes_saveCsvFile', data)
})
}
export function getDataClassificationByNGCode (data) {
return request({
url: BASE + 'getDataClassificationByNGCode',
method: 'get',
params: apiParams('data_middleground_eagle_eyes_get_data_classification_by_ng_code', data)
})
}

View File

@@ -0,0 +1,23 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/battery_details_report/'
function dataParams (method, data = {}, platform = 'api') {
return { method, platform, ...data }
}
export function getBatteryDetailTitle (data) {
return request({ url: BASE + 'battery_details_title', method: 'post', data: dataParams('production_report_battery_details_title', data) })
}
export function getBatteryDetailList (data) {
return request({ url: BASE + 'battery_details_list', method: 'post', data: dataParams('production_report_battery_details_list', data) })
}
export function getBatteryDetailFlowBatch (data) {
return request({ url: BASE + 'battery_details_flow_batch', method: 'get', params: dataParams('production_report_battery_details_flow_batch', data) })
}
export function createBatteryDetailExportTask (data) {
return request({ url: BASE + 'battery_details_task', method: 'post', data: dataParams('system_exporttask_battery_details_task', data, 'admin') })
}

View File

@@ -0,0 +1,15 @@
import { request } from '@/api/_service'
const BASE = 'report/'
function apiParams (method, data = {}) {
return { method, platform: 'api', ...data }
}
export function getEquipmentHistoryList (data) {
return request({
url: BASE + 'device/log',
method: 'post',
data: apiParams('get.device.status.log', data)
})
}

View File

@@ -0,0 +1,27 @@
import { request } from '@/api/_service'
const BASE = 'data_middleground/basic_traceability/reverse_direction_traceability/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getBackwardTraceabilityData (data) {
return request({
url: BASE + 'get_data',
method: 'get',
params: apiParams('data_middleground_basic_traceability_reverse_direction_traceability_get_data', data)
})
}
export function exportBackwardTraceabilityTree (data) {
return request({
url: BASE + 'export_tree',
method: 'post',
data: apiParams('data_middleground_basic_traceability_reverse_direction_traceability_export_tree', data)
})
}

View File

@@ -0,0 +1,35 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/traceability/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getBatteryCurveRecords (data) {
return request({
url: BASE + 'batterytraceability',
method: 'get',
params: apiParams('planning_production_produce_traceability_batterytraceability', data)
})
}
export function getBatteryCurveData (data) {
return request({
url: BASE + 'curveread',
method: 'get',
params: apiParams('planning_production_produce_traceability_batterycurveread', data)
})
}
export function exportBatteryCurveData (data) {
return request({
url: BASE + 'export',
method: 'get',
params: apiParams('planning_production_produce_traceability_export', data)
})
}

View File

@@ -0,0 +1,31 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/traceability/'
function apiParams (method, data = {}) {
return { method, platform: 'background', ...data }
}
export function getBatteryTraceList (data) {
return request({
url: BASE + 'battery',
method: 'get',
params: apiParams('planning_production_produce_traceability_battery', data)
})
}
export function getBatteryProcessData (data) {
return request({
url: BASE + 'batteryProcess',
method: 'get',
params: apiParams('planning_production_produce_traceability_batteryProcess', data)
})
}
export function cancelBatteryActive (data) {
return request({
url: BASE + 'batteryactive',
method: 'get',
params: apiParams('planning_production_produce_traceability_batteryactive', data)
})
}

View File

@@ -0,0 +1,27 @@
import { request } from '@/api/_service'
const BASE = 'data_middleground/basic_traceability/positive_direction_traceability/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getForwardTraceabilityList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('data_middleground_basic_traceability_positive_direction_traceability_list', data)
})
}
export function createForwardTraceabilityExportTask (data) {
return request({
url: BASE + 'export_task',
method: 'post',
data: apiParams('data_middleground_basic_traceability_positive_direction_traceability_export_task', data)
})
}

View File

@@ -0,0 +1,31 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/traceability/'
function apiParams (method, data = {}) {
return { method, platform: 'background', ...data }
}
export function getTrayTraceList (data) {
return request({
url: BASE + 'tray',
method: 'get',
params: apiParams('planning_production_produce_traceability_tray', data)
})
}
export function getTrayTraceDetail (data) {
return request({
url: BASE + 'traydetail',
method: 'get',
params: apiParams('planning_production_produce_traceability_traydetail', data)
})
}
export function cancelTraceBatteryActive (data) {
return request({
url: BASE + 'batteryactive',
method: 'get',
params: apiParams('planning_production_produce_traceability_batteryactive', data)
})
}

View File

@@ -1,86 +0,0 @@
import { find, map, random } from 'lodash'
import faker from 'faker/locale/zh_CN'
import { requestForMock, mock } from '@/api/_service.js'
import * as tools from '@/api/_tools.js'
const db = [
{ id: '1', name: '用户 1', address: '上海市普陀区金沙江路 1518 弄' },
{ id: '2', name: '用户 2', address: '上海市普陀区金沙江路 1517 弄' },
{ id: '3', name: '用户 3', address: '上海市普陀区金沙江路 1519 弄' },
{ id: '4', name: '用户 4', address: '上海市普陀区金沙江路 1516 弄' }
]
/**
* @description 列表
*/
export function DEMO_MOCK_LIST () {
// 模拟数据
mock
.onAny('/demo/business/issues/142/fetch')
.reply(...tools.responseSuccess({ list: db }))
// 接口请求
return requestForMock({
url: '/demo/business/issues/142/fetch',
method: 'get'
})
}
/**
* @description 详情
* @param {String} id 项目 ID
*/
export function DEMO_MOCK_DETAIL (id) {
// 模拟数据
mock
.onAny('/demo/business/issues/142/detail')
.reply(config => tools.responseSuccess(find(db, { id: config.params.id })))
// 接口请求
return requestForMock({
url: '/demo/business/issues/142/detail',
method: 'get',
params: {
id
}
})
}
/**
* @description 列表
*/
export function DEMO_MOCK_LIST2 (params = {}) {
// 模拟数据
mock
.onAny('/demo/business/table/1/fetch')
.reply(config => tools.responseSuccess({
page: {
total: 1000
},
list: map(Array(config.params.pageSize), () => ({
key: faker.random.uuid(),
value: [10, 100, 200, 500][random(0, 3)],
type: faker.random.boolean(),
admin: faker.name.firstName() + faker.name.lastName(),
adminNote: faker.random.words(),
dateTimeCreat: faker.date.past(),
used: faker.random.boolean(),
dateTimeUse: faker.date.past()
}))
}))
// 接口请求
return requestForMock({
url: '/demo/business/table/1/fetch',
method: 'get',
params
})
}
/**
* @description 错误日志示例 请求一个不存在的地址
*/
export function DEMO_LOG_AJAX () {
// 接口请求
return requestForMock({
url: '/invalid-url',
method: 'get'
})
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_consumables/device_consumables_category/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_consumables_device_consumables_category_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_consumables_device_consumables_category_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_consumables_device_consumables_category_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_consumables_device_consumables_category_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_consumables_device_consumables_category_delete', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'data_export_task', method: 'post', data: params('device_management_device_consumables_device_consumables_category_data_export_task', data) })
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_consumables/device_consumables_items/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_consumables_device_consumables_items_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_consumables_device_consumables_items_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_consumables_device_consumables_items_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_consumables_device_consumables_items_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_consumables_device_consumables_items_delete', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'data_export_task', method: 'post', data: params('device_management_device_consumables_device_consumables_items_data_export_task', data) })
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_consumables/device_consumables_lifetime_management/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_consumables_device_consumables_lifetime_management_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_consumables_device_consumables_lifetime_management_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_consumables_device_consumables_lifetime_management_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_consumables_device_consumables_lifetime_management_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_consumables_device_consumables_lifetime_management_delete', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'data_export_task', method: 'post', data: params('device_management_device_consumables_device_consumables_lifetime_management_data_export_task', data) })
}

View File

@@ -0,0 +1,51 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/device_model/device_category/'
function apiParams (method, data = {}) {
return {
method: `equipment_management_equipment_model_equipment_category_${method}`,
platform: 'background',
...data
}
}
export function getEquipmentCategoryList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('list', data)
})
}
export function getEquipmentCategoryALL (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('all', data)
})
}
export function createEquipmentCategory (data) {
return request({
url: BASE + 'create',
method: 'post',
data: apiParams('create', data)
})
}
export function editEquipmentCategory (data) {
return request({
url: BASE + 'edit',
method: 'put',
data: apiParams('edit', data)
})
}
export function deleteEquipmentCategory (data) {
return request({
url: BASE + 'delete',
method: 'delete',
data: apiParams('delete', data)
})
}

View File

@@ -0,0 +1,33 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/device_model/device_management/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('production_configuration_device_model_device_management_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('production_configuration_device_model_device_management_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('production_configuration_device_model_device_management_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('production_configuration_device_model_device_management_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('production_configuration_device_model_device_management_delete', data) })
}
export function batchDeleteItems (data) {
return request({ url: BASE + 'batch_delete', method: 'delete', data: params('production_configuration_device_model_device_management_batch_delete', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'device_data_export_task', method: 'post', data: params('production_configuration_device_model_device_management_device_export_task', data) })
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_check/device_check_items/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_check_device_check_items_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_check_device_check_items_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_check_device_check_items_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_check_device_check_items_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_check_device_check_items_delete', data) })
}
export function batchDeleteItems (data) {
return request({ url: BASE + 'batch_delete', method: 'delete', data: params('device_management_device_check_device_check_items_batch_delete', data) })
}

View File

@@ -0,0 +1,13 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_check/device_check_items_log/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_check_device_check_items_log_list', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'export', method: 'post', data: params('device_management_device_check_device_check_items_log_export', data) })
}

View File

@@ -0,0 +1,17 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_check/device_check_record/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_check_device_check_record_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create_record', method: 'post', data: params('device_management_device_check_device_check_create_record', data) })
}
export function editItem (data) {
return request({ url: BASE + 'create_record', method: 'put', data: params('device_management_device_check_device_check_create_record', data) })
}

View File

@@ -0,0 +1,25 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_maintain/device_maintain_items_details/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_maintain_device_maintain_items_details_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_maintain_device_maintain_items_details_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_maintain_device_maintain_items_details_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_maintain_device_maintain_items_details_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_maintain_device_maintain_items_details_delete', data) })
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_maintain/device_maintain_items/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_maintain_device_maintain_items_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_maintain_device_maintain_items_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_maintain_device_maintain_items_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_maintain_device_maintain_items_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_maintain_device_maintain_items_delete', data) })
}
export function batchDeleteItems (data) {
return request({ url: BASE + 'batch_delete', method: 'delete', data: params('device_management_device_maintain_device_maintain_items_batch_delete', data) })
}

View File

@@ -0,0 +1,21 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_maintain/device_maintain_items_log/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_maintain_device_maintain_items_log_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_maintain_device_maintain_items_log_list', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_maintain_device_maintain_items_log_edit', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'export', method: 'post', data: params('device_management_device_maintain_device_maintain_items_log_export', data) })
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_repair/device_repair_log/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_repair_device_repair_log_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_repair_device_repair_log_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_repair_device_repair_log_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_repair_device_repair_log_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_repair_device_repair_log_delete', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'create_data_export_task', method: 'post', data: params('device_management_device_repair_device_repair_log_create_data_export_task', data) })
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_repair/device_repair_management/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_repair_device_repair_management_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_repair_device_repair_management_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_repair_device_repair_management_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_repair_device_repair_management_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_repair_device_repair_management_delete', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'create_data_export_task', method: 'post', data: params('device_management_device_repair_device_repair_management_create_data_export_task', data) })
}

View File

@@ -0,0 +1,29 @@
import { request } from '@/api/_service'
const BASE = 'device_management/device_consumables/device_consumables_replace_log/'
function params (method, data = {}) { return { method, platform: 'background', ...data } }
export function getAll (data) {
return request({ url: BASE + 'all', method: 'get', params: params('device_management_device_consumables_device_consumables_replace_log_all', data) })
}
export function getList (data) {
return request({ url: BASE + 'list', method: 'get', params: params('device_management_device_consumables_device_consumables_replace_log_list', data) })
}
export function createItem (data) {
return request({ url: BASE + 'create', method: 'post', data: params('device_management_device_consumables_device_consumables_replace_log_create', data) })
}
export function editItem (data) {
return request({ url: BASE + 'edit', method: 'put', data: params('device_management_device_consumables_device_consumables_replace_log_edit', data) })
}
export function deleteItem (data) {
return request({ url: BASE + 'delete', method: 'delete', data: params('device_management_device_consumables_device_consumables_replace_log_delete', data) })
}
export function createExportTask (data) {
return request({ url: BASE + 'data_export_task', method: 'post', data: params('device_management_device_consumables_device_consumables_replace_log_data_export_task', data) })
}

15
src/api/menu.js Normal file
View File

@@ -0,0 +1,15 @@
import { request } from '@/api/_service'
const urls = 'system_settings/menu_configuration/menu/'
export function getMenuAll (data) {
return request({
url: urls + 'all',
method: 'get',
params: {
method: 'system_settings_menu_configuration_menu_all',
platform: 'background',
...data
}
})
}

View File

@@ -0,0 +1,59 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/pin_check/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getPincheckWorkstation (data) {
return request({
url: BASE + 'workstation',
method: 'get',
params: apiParams('planning_production_produce_pincheck_workstation', data)
})
}
export function getDevicePinCheckList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('planning_production_produce_pincheck_list', data)
})
}
export function getPinCheckDetail (data) {
return request({
url: BASE + 'detail',
method: 'get',
params: apiParams('planning_production_produce_pincheck_detail', data)
})
}
export function setPinCheckClean (data) {
return request({
url: BASE + 'clean',
method: 'get',
params: apiParams('planning_production_produce_pincheck_clean', data)
})
}
export function setPinCheckCleanSingle (data) {
return request({
url: BASE + 'clean_single_channel',
method: 'get',
params: apiParams('planning_production_produce_pincheck_clean_single_channel', data)
})
}
export function getWorkstationSearch (data) {
return request({
url: BASE + 'search',
method: 'get',
params: apiParams('planning_production_produce_pincheck_search', data)
})
}

View File

@@ -0,0 +1,27 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/production_batch_management/report/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getBatchDefectReport (data) {
return request({
url: BASE + 'bad',
method: 'get',
params: apiParams('planning_production_production_batch_management_batch_bad', data)
})
}
export function exportBatchDefectReport (data) {
return request({
url: BASE + 'export',
method: 'get',
params: apiParams('planning_production_production_batch_management_batch_export', data)
})
}

View File

@@ -0,0 +1,59 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/production_batch_management/batch/'
function apiParams (method, data = {}) {
return {
method: `planning_production_production_batch_management_batch_${method}`,
platform: 'background',
...data
}
}
export function getBatchAll (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('all', data)
})
}
export function getBatchList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('list', data)
})
}
export function createBatch (data) {
return request({
url: BASE + 'create',
method: 'post',
data: apiParams('create', data)
})
}
export function editBatch (data) {
return request({
url: BASE + 'edit',
method: 'put',
data: apiParams('edit', data)
})
}
export function deleteBatch (data) {
return request({
url: BASE + 'delete',
method: 'delete',
data: apiParams('delete', data)
})
}
export function getProcessBatch (data) {
return request({
url: BASE + 'getProcessBatch',
method: 'post',
data: apiParams('getProcessBatch', data)
})
}

View File

@@ -0,0 +1,43 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/production_batch_management/batch_tray/'
function apiParams (method, data = {}) {
return {
method: `planning_production_production_batch_management_batch_tray_${method}`,
platform: 'background',
...data
}
}
export function getBatchTrayList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('list', data)
})
}
export function trayUnbinding (data) {
return request({
url: BASE + 'unbinding',
method: 'get',
params: apiParams('unbinding', data)
})
}
export function trayInactivity (data) {
return request({
url: BASE + 'inactivity',
method: 'get',
params: apiParams('inactivity', data)
})
}
export function getBatteryParam (data) {
return request({
url: BASE + 'get_battery_param',
method: 'get',
params: apiParams('get_battery_param', data)
})
}

View File

@@ -0,0 +1,19 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/device_model/device_management/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getDeviceAll (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('production_configuration_device_model_device_management_all', data)
})
}

View File

@@ -0,0 +1,27 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/wip/wip_management/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getWipDataList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('planning_production_wip_wip_management_list', data)
})
}
export function createWipData (data) {
return request({
url: BASE + 'create',
method: 'post',
data: apiParams('planning_production_wip_wip_management_create', data)
})
}

View File

@@ -0,0 +1,27 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/change_battery_process/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function verifyBatteryProcessInfo (data) {
return request({
url: BASE + 'verify',
method: 'get',
params: apiParams('planning_production_produce_change_battery_process_verify', data)
})
}
export function changeBatteryProcess (data) {
return request({
url: BASE + 'change',
method: 'get',
params: apiParams('planning_production_produce_change_battery_process_change', data)
})
}

View File

@@ -0,0 +1,19 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/set_battery_rebatch/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function verifyBatteryRebatchInfo (data) {
return request({
url: BASE + 'verify',
method: 'get',
params: apiParams('planning_production_produce_change_battery_process_verify', data)
})
}

View File

@@ -0,0 +1,67 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/tray_manage/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getTrayManageInfo (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('planning_production_produce_traymanage_list', data)
})
}
export function changeFlowProcess (data) {
return request({
url: BASE + 'change',
method: 'put',
params: apiParams('planning_production_produce_traymanage_change', data)
})
}
export function inactiveTray (data) {
return request({
url: BASE + 'inactive',
method: 'put',
params: apiParams('planning_production_produce_traymanage_inactive', data)
})
}
export function trayNg (data) {
return request({
url: BASE + 'ng',
method: 'put',
params: apiParams('planning_production_produce_traymanage_ng', data)
})
}
export function rangeNgAndRC (data) {
return request({
url: BASE + 'ngrc',
method: 'put',
params: apiParams('planning_production_produce_traymanage_ngrc', data)
})
}
export function rangeFx (data) {
return request({
url: BASE + 'fenx',
method: 'put',
params: apiParams('planning_production_produce_traymanage_fenx', data)
})
}
export function cleanTrayNg (data) {
return request({
url: BASE + 'clean',
method: 'put',
params: apiParams('planning_production_produce_traymanage_clean', data)
})
}

View File

@@ -0,0 +1,51 @@
import { request } from '@/api/_service'
const BASE = 'planning_production/produce/tray_login/'
function apiParams (method, data = {}) {
return {
method,
platform: 'background',
...data
}
}
export function getBatchAll (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('planning_production_produce_traylogin_all', data)
})
}
export function getBatchTrayFormatAll (data) {
return request({
url: BASE + 'trayformat_all',
method: 'get',
params: apiParams('planning_production_produce_trayformat_all', data)
})
}
export function createBatchTrayFormat (data) {
return request({
url: BASE + 'create',
method: 'get',
params: apiParams('planning_production_produce_trayformat_create', data)
})
}
export function deleteBatchTrayFormat (data) {
return request({
url: BASE + 'delete',
method: 'get',
params: apiParams('planning_production_produce_trayformat_delete', data)
})
}
export function checkBatteryid (data) {
return request({
url: BASE + 'check_batteryid',
method: 'get',
params: apiParams('planning_production_produce_trayformat_check_batteryid', data)
})
}

View File

@@ -0,0 +1,56 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/matetial_model/bom/'
const RELATION_BASE = 'production_configuration/matetial_model/bom_relationship/'
function apiParams (method, data = {}) {
return {
method: `production_configuration_matetial_model_bom_${method}`,
platform: 'background',
...data
}
}
function relationApiParams (method, data = {}) {
return {
method: `production_configuration_matetial_model_bom_relationship_${method}`,
platform: 'background',
...data
}
}
export function getBomAll (data) {
return request({ url: BASE + 'all', method: 'get', params: apiParams('all', data) })
}
export function getBomList (data) {
return request({ url: BASE + 'list', method: 'get', params: apiParams('list', data) })
}
export function createBom (data) {
return request({ url: BASE + 'create', method: 'post', data: apiParams('create', data) })
}
export function editBom (data) {
return request({ url: BASE + 'edit', method: 'put', data: apiParams('edit', data) })
}
export function deleteBom (data) {
return request({ url: BASE + 'delete', method: 'delete', data: apiParams('delete', data) })
}
export function getBomRelationshipList (data) {
return request({ url: RELATION_BASE + 'list', method: 'get', params: relationApiParams('list', data) })
}
export function createBomRelationship (data) {
return request({ url: RELATION_BASE + 'create', method: 'post', data: relationApiParams('create', data) })
}
export function editBomRelationship (data) {
return request({ url: RELATION_BASE + 'edit', method: 'put', data: relationApiParams('edit', data) })
}
export function deleteBomRelationship (data) {
return request({ url: RELATION_BASE + 'delete', method: 'delete', data: relationApiParams('delete', data) })
}

View File

@@ -0,0 +1,51 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/technology_model/calculation_script/'
function apiParams (method, data = {}) {
return {
method: `production_configuration_technology_model_calculation_script_${method}`,
platform: 'background',
...data
}
}
export function getCalculationScriptAll (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('all', data)
})
}
export function getCalculationScriptList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('list', data)
})
}
export function createCalculationScript (data) {
return request({
url: BASE + 'create',
method: 'post',
data: apiParams('create', data)
})
}
export function editCalculationScript (data) {
return request({
url: BASE + 'edit',
method: 'put',
data: apiParams('edit', data)
})
}
export function deleteCalculationScript (data) {
return request({
url: BASE + 'delete',
method: 'delete',
data: apiParams('delete', data)
})
}

View File

@@ -0,0 +1,43 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/spc_configuration/binding_scada_node/'
function apiParams (method, data = {}) {
return {
method: `production_master_data_spc_configuration_data_collection_configuration_${method}`,
platform: 'background',
...data
}
}
export function getDataCollectionConfigList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('list', data)
})
}
export function createDataCollectionConfig (data) {
return request({
url: BASE + 'create',
method: 'post',
data: apiParams('create', data)
})
}
export function editDataCollectionConfig (data) {
return request({
url: BASE + 'edit',
method: 'put',
data: apiParams('edit', data)
})
}
export function deleteDataCollectionConfig (data) {
return request({
url: BASE + 'delete',
method: 'delete',
data: apiParams('delete', data)
})
}

View File

@@ -0,0 +1,19 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/device_model/device_category/'
function apiParams (method, data = {}) {
return {
method: `production_configuration_device_model_device_category_${method}`,
platform: 'background',
...data
}
}
export function getDeviceCategoryAll (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('all', data)
})
}

View File

@@ -0,0 +1,51 @@
import { request } from '@/api/_service'
const BASE = 'production_configuration/factory_model/factory_area/'
function apiParams (method, data = {}) {
return {
method: `production_master_data_factory_model_factory_area_${method}`,
platform: 'background',
...data
}
}
export function getFactoryAreaALL (data) {
return request({
url: BASE + 'all',
method: 'get',
params: apiParams('all', data)
})
}
export function getFactoryAreaList (data) {
return request({
url: BASE + 'list',
method: 'get',
params: apiParams('list', data)
})
}
export function createFactoryArea (data) {
return request({
url: BASE + 'create',
method: 'post',
data: apiParams('create', data)
})
}
export function editFactoryArea (data) {
return request({
url: BASE + 'edit',
method: 'put',
data: apiParams('edit', data)
})
}
export function deleteFactoryArea (data) {
return request({
url: BASE + 'delete',
method: 'delete',
data: apiParams('delete', data)
})
}

Some files were not shown because too many files have changed in this diff Show More