From d343838f4d95d8f16295b62e20b170b280fbcfc0 Mon Sep 17 00:00:00 2001
From: tangjie <122778500@qq.com>
Date: Tue, 7 Jul 2026 11:18:00 +0800
Subject: [PATCH] feat
---
.gitignore | 1 +
blessed_by_buddha.js | 66 --
docs/dev-guide.md | 572 ------------------
docs/startup.md | 47 --
docs/test-reports/测试文档.md | 211 -------
docs/test-reports/测试用例/setup-test-env.sh | 19 -
.../测试用例/test-enterprise-info-api.mjs | 221 -------
.../test-enterprise-info-granular.mjs | 371 ------------
.../test-enterprise-info-ui-check.mjs | 87 ---
.../测试用例/test-qual-filing-api.mjs | 278 ---------
.../测试用例/test-qual-filing-audit-flow.mjs | 199 ------
.../测试用例/test-qual-filing-full-e2e.mjs | 410 -------------
.../测试用例/test-qual-filing-interaction.mjs | 249 --------
.../EnterpriseInfo/EquipInfo/index.js | 52 +-
src/pages/Container/EnterpriseInfo/index.js | 10 +-
src/pages/Container/QualApplication/index.js | 6 +-
16 files changed, 47 insertions(+), 2752 deletions(-)
delete mode 100644 blessed_by_buddha.js
delete mode 100644 docs/dev-guide.md
delete mode 100644 docs/startup.md
delete mode 100644 docs/test-reports/测试文档.md
delete mode 100755 docs/test-reports/测试用例/setup-test-env.sh
delete mode 100644 docs/test-reports/测试用例/test-enterprise-info-api.mjs
delete mode 100644 docs/test-reports/测试用例/test-enterprise-info-granular.mjs
delete mode 100644 docs/test-reports/测试用例/test-enterprise-info-ui-check.mjs
delete mode 100644 docs/test-reports/测试用例/test-qual-filing-api.mjs
delete mode 100644 docs/test-reports/测试用例/test-qual-filing-audit-flow.mjs
delete mode 100644 docs/test-reports/测试用例/test-qual-filing-full-e2e.mjs
delete mode 100644 docs/test-reports/测试用例/test-qual-filing-interaction.mjs
diff --git a/.gitignore b/.gitignore
index 6b5df63..1181c62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
/prototype
/dist
/demo
+/docs
/.trae/
npm-debug.log*
yarn-debug.log*
diff --git a/blessed_by_buddha.js b/blessed_by_buddha.js
deleted file mode 100644
index 340fa53..0000000
--- a/blessed_by_buddha.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- _ooOoo_
- o8888888o
- 88" . "88
- (| -_- |)
- O\ = /O
- ____/`---'\____
- . ' \\| |// `.
- / \\||| : |||// \
- / _||||| -:- |||||- \
- | | \\\ - /// | |
- | \_| ''\---/'' | |
- \ .-\__ `-` ___/-. /
- ___`. .' /--.--\ `. . __
- ."" '< `.___\_<|>_/___.' >'"".
- | | : `- \`.;`\ _ /`;.`/ - ` : | |
- \ \ `-. \_ __\ /__ _/ .-` / /
- ======`-.____`-.___\_____/___.-`____.-'======
- `=---='
-
- .............................................
- 佛祖保佑 永无BUG
- 佛曰:
- 写字楼里写字间,写字间里程序员;
- 程序人员写程序,又拿程序换酒钱。
- 酒醒只在网上坐,酒醉还来网下眠;
- 酒醉酒醒日复日,网上网下年复年。
- 但愿老死电脑间,不愿鞠躬老板前;
- 奔驰宝马贵者趣,公交自行程序员。
- 别人笑我忒疯癫,我笑自己命太贱;
- 不见满街漂亮妹,哪个归得程序员?
- */
-
-const blessedByBuddha
- = "%c _ooOoo_\n"
- + " o8888888o\n"
- + " 88\" . \"88\n"
- + " (| -_- |)\n"
- + " O\\ = /O\n"
- + " ____/`---'\\____\n"
- + " . ' \\\\| |// `.\n"
- + " / \\\\||| : |||// \\\n"
- + " / _||||| -:- |||||- \\\n"
- + " | | \\\\\\ - /// | |\n"
- + " | \\_| ''\\---/'' | |\n"
- + " \\ .-\\__ `-` ___/-. /\n"
- + " ___`. .' /--.--\\ `. . __\n"
- + " .\"\" '< `.___\\_<|>_/___.' >'\"\".\n"
- + " | | : `- \\`.;`\\ _ /`;.`/ - ` : | |\n"
- + " \\ \\ `-. \\_ __\\ /__ _/ .-` / /\n"
- + " ======`-.____`-.___\\_____/___.-`____.-'======\n"
- + " `=---='\n"
- + "\n"
- + "%c .............................................\n"
- + " 佛祖保佑 永无BUG\n"
- + "\n"
- + "%c 佛曰:\n"
- + " 写字楼里写字间,写字间里程序员;\n"
- + " 程序人员写程序,又拿程序换酒钱。\n"
- + " 酒醒只在网上坐,酒醉还来网下眠;\n"
- + " 酒醉酒醒日复日,网上网下年复年。\n"
- + " 但愿老死电脑间,不愿鞠躬老板前;\n"
- + " 奔驰宝马贵者趣,公交自行程序员。\n"
- + " 别人笑我忒疯癫,我笑自己命太贱;\n"
- + " 不见满街漂亮妹,哪个归得程序员?";
-console.log(blessedByBuddha, "color:#ffd700", "color:red", "color:#1e80ff");
diff --git a/docs/dev-guide.md b/docs/dev-guide.md
deleted file mode 100644
index d72a228..0000000
--- a/docs/dev-guide.md
+++ /dev/null
@@ -1,572 +0,0 @@
-# 证照管理子应用 — 本地开发指南
-
-## 目录
-
-- [1. 项目概述](#1-项目概述)
-- [2. 环境准备与启动](#2-环境准备与启动)
-- [3. 路由系统](#3-路由系统)
-- [4. 菜单配置](#4-菜单配置)
-- [5. 页面开发流程](#5-页面开发流程)
-- [6. API 接口声明](#6-api-接口声明)
-- [7. 状态管理(DVA)](#7-状态管理dva)
-- [8. 共享组件](#8-共享组件)
-- [9. 本地模拟布局](#9-本地模拟布局)
-- [10. 已知问题与注意事项](#10-已知问题与注意事项)
-- [11. 目录结构参考](#11-目录结构参考)
-
----
-
-## 1. 项目概述
-
-本项目是基于 **qiankun 微前端** 框架的子应用,运行在 **GBS 底座平台** 内。使用以下核心技术栈:
-
-| 技术 | 说明 |
-|------|------|
-| React 18 | UI 组件框架 |
-| Ant Design 5.x | UI 组件库 |
-| @cqsjjb/jjb-dva-runtime | 底座 DVA 状态管理运行时 |
-| @cqsjjb/jjb-common-decorator | 装饰器工具(权限、模块加载等) |
-| rspack | 构建打包工具 |
-| pnpm | 包管理器 |
-
-项目通过 `jjb.config.js` 中配置的 `appIdentifier: "certificate"` 注册到底座,所有页面路由前缀为 `/certificate/container/`。
-
----
-
-## 2. 环境准备与启动
-
-### 2.1 安装依赖
-
-```bash
-pnpm install
-```
-
-### 2.2 启动命令
-
-| 命令 | 说明 |
-|------|------|
-| `pnpm run serve:development` | **开发环境启动**(推荐) |
-| `pnpm run serve:production` | 生产环境配置启动 |
-| `pnpm run build:development` | 开发环境构建 |
-| `pnpm run build:production` | 生产环境构建 |
-
-### 2.3 访问地址
-
-启动后开发服务器默认监听 `http://127.0.0.1:8081`,访问:
-
-```
-http://localhost:8081/certificate/container/
-http://localhost:8081/certificate/container/Test
-```
-
-> **注意**:本地独立启动时,应用处于 qiankun 独立运行模式(`window.__POWERED_BY_QIANKUN__` 为 false),
-> 会使用内置的 `SimulatedLayout` 模拟侧边栏和标签页布局。
-
-### 2.4 配置说明
-
-`jjb.config.js` 中的关键配置项:
-
-```js
-module.exports = {
- appIdentifier: "certificate", // 应用唯一标识,对应路由前缀
- server: {
- port: "8081", // 开发服务器端口
- host: "127.0.0.1", // 服务地址
- },
- environment: {
- development: {
- API_HOST: "https://gbs-gateway.qhdsafety.com", // 开发环境接口地址
- },
- },
-};
-```
-
----
-
-## 3. 路由系统
-
-### 3.1 约定式路由
-
-本项目使用 **文件系统约定式路由**,由 `@cqsjjb/jjb-dva-runtime` 框架自动注册。页面对应的路径由目录结构决定:
-
-```
-src/pages/Container/<目录层级>/index.js → /certificate/container/<目录层级>
-```
-
-**示例:**
-
-| 文件路径 | 对应路由 |
-|----------|----------|
-| `src/pages/Container/Test/index.js` | `/certificate/container/Test` |
-| `src/pages/Container/Supervision/index.js` | `/certificate/container/Supervision` |
-| `src/pages/Container/Supervision/PersonnelLicense/PersonInCharge/List/index.js` | `/certificate/container/Supervision/PersonnelLicense/PersonInCharge/List` |
-
-### 3.2 页面组件类型
-
-项目中有两类页面组件:
-
-1. **容器组件**(中间层级):作为 `{props.children}` 的容器,负责嵌套子页面
- ```js
- function ContainerPage(props) {
- return
{props.children}
;
- }
- export default ContainerPage;
- ```
-
-2. **叶子页面**(终端页面):实际的业务功能页面,通过 `Connect` 连接 DVA 数据
- ```js
- import { Connect } from "@cqsjjb/jjb-dva-runtime";
- import { NS_USER_CERTIFICATE } from "~/enumerate/namespace";
-
- function List(props) {
- return 业务内容
;
- }
-
- export default Connect([NS_USER_CERTIFICATE], true)(List);
- ```
-
-### 3.3 路由匹配规则
-
-- 框架自动递归扫描 `src/pages/` 目录,每个 `index.js` 对应一个路由
-- 路由路径是将目录路径转换为小写并用 `/` 连接
-- 带参数的路由(如 `/View/:id`)需在目录中创建对应层级
-
----
-
-## 4. 菜单配置
-
-侧边栏菜单定义在 `src/pages/Container/Layout/menuConfig.js` 中。
-
-### 4.1 菜单数据结构
-
-```js
-{
- key: "/certificate/container/<实际路由>", // 必须与文件目录对应的路由完全一致
- label: "菜单显示名称",
- icon: , // Ant Design 图标组件
- children: [...] // 可选,子菜单项
-}
-```
-
-### 4.2 当前菜单结构
-
-```
-📁 监管端 (Supervision)
- ├── 📄 企业证照 (EnterpriseLicense)
- │ ├── 企业证照管理
- │ ├── 分公司统计
- │ └── 干系人统计
- └── 📄 人员证照 (PersonnelLicense)
- ├── 负责人
- ├── 安全管理员
- ├── 特种设备
- ├── 特种作业人员
- ├── 分公司人员统计
- └── 干系人人员统计
-
-📁 分公司端 (BranchCompany)
- └── 📄 企业证照 (EnterpriseLicense)
- ├── 企业证照管理
- └── 📄 人员证照 (PersonnelLicense)
- ├── 负责人
- ├── 安全管理员
- ├── 特种设备
- └── 特种作业人员
-
-📁 干系人端 (Stakeholder)
- └── 📄 企业证照 (EnterpriseLicense)
- ├── 企业证照管理
- └── 📄 人员证照 (PersonnelLicense)
- ├── 负责人
- ├── 安全管理员
- ├── 特种设备
- └── 特种作业人员
-
-📁 测试页面 (Test)
-```
-
-### 4.3 菜单配置注意事项
-
-> **关键规则**:菜单的 `key` 必须与文件系统的实际目录层级完全一致,否则会出现"页面不存在"。
-
-以"干系人端 → 负责人"为例:
-
-- **文件位置**:`Stakeholder/EnterpriseLicense/PersonnelLicense/PersonInCharge/List/index.js`
-- **正确路径**:`/certificate/container/Stakeholder/EnterpriseLicense/PersonnelLicense/PersonInCharge/List`
-- **错误路径**(缺少 `EnterpriseLicense` 层级):`/certificate/container/Stakeholder/PersonnelLicense/PersonInCharge/List`
-
-### 4.4 工具函数
-
-`menuConfig.js` 同时导出以下辅助函数:
-
-| 函数 | 参数 | 返回值 | 说明 |
-|------|------|--------|------|
-| `flattenMenu(items)` | 菜单树 | 扁平数组 | 将树形菜单拍平 |
-| `findMenuPath(path)` | 当前路由 | 菜单项数组 | 从根到叶子节点的面包屑路径 |
-| `getPageLabel(path)` | 当前路由 | 字符串 | 获取页面标签名 |
-| `getOpenKeys(path)` | 当前路由 | 路径数组 | 默认展开的菜单项 |
-| `getSelectedKeys(path)` | 当前路由 | 路径数组 | 默认选中的菜单项 |
-
----
-
-## 5. 页面开发流程
-
-### 5.1 新增业务页面
-
-以新增"监管端 → 人员证照 → 新增功能"为例:
-
-**步骤 1:创建目录结构**
-
-```
-src/pages/Container/Supervision/PersonnelLicense/NewFeature/
-├── index.js # 容器组件
-├── List/
-│ └── index.js # 列表页
-└── View/
- └── index.js # 详情页
-```
-
-**步骤 2:编写容器组件**
-
-`src/pages/Container/Supervision/PersonnelLicense/NewFeature/index.js`:
-```js
-function NewFeature(props) {
- return {props.children}
;
-}
-export default NewFeature;
-```
-
-**步骤 3:编写列表页面**
-
-`src/pages/Container/Supervision/PersonnelLicense/NewFeature/List/index.js`:
-```js
-import { Connect } from "@cqsjjb/jjb-dva-runtime";
-import { NS_USER_CERTIFICATE } from "~/enumerate/namespace";
-
-function List(props) {
- return (
-
-
新功能列表
-
- );
-}
-
-export default Connect([NS_USER_CERTIFICATE], true)(List);
-```
-
-**步骤 4:添加菜单配置**
-
-在 `src/pages/Container/Layout/menuConfig.js` 中添加:
-```js
-{
- key: "/certificate/container/Supervision/PersonnelLicense",
- label: "人员证照",
- icon: ,
- children: [
- // ... 已有菜单项
- {
- key: "/certificate/container/Supervision/PersonnelLicense/NewFeature/List",
- label: "新功能",
- icon: ,
- },
- ],
-}
-```
-
-### 5.2 新增测试页面(独立于业务)
-
-在 `src/pages/Container/` 下创建目录,并在菜单中添加即可:
-
-```
-src/pages/Container/MyDebug/
-└── index.js
-```
-
-菜单:
-```js
-{
- key: "/certificate/container/MyDebug",
- label: "调试页面",
- icon: ,
-}
-```
-
-### 5.3 验证路径是否正确
-
-启动项目后,通过以下方式验证:
-
-1. 在浏览器直接访问完整 URL
-2. 从侧边栏菜单点击导航
-3. 检查开发者工具 Network 面板,404 表示路径不匹配
-
----
-
-## 6. API 接口声明
-
-### 6.1 接口定义位置
-
-API 接口声明在 `src/api/` 目录下,按模块划分:
-
-```
-src/api/
-├── userCertificate/index.js # 人员证书接口
-├── corpCertificate/index.js # 企业证书接口
-├── courseware/index.js # 课件接口
-└── global/index.js # 全局接口
-```
-
-### 6.2 declareRequest 语法
-
-```js
-import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
-
-// 格式:declareRequest(loadingKey, "HttpMethod > 接口路径")
-export const listApi = declareRequest(
- "namespaceLoading", // loading 状态 key
- "Post > @/certificate/userCertificate/list", // POST + 相对路径(带 @)
-);
-
-export const getApi = declareRequest(
- "namespaceLoading",
- "Get > /certificate/userCertificate/getInfoById/{id}", // GET + 绝对路径
-);
-```
-
-**语法规则:**
-
-| 符号 | 说明 | 示例 |
-|------|------|------|
-| `@/` | 相对路径,使用 `jjb.config.js` 中配置的 `API_HOST` | `Post > @/certificate/xxx/list` |
-| `/` | 绝对路径 | `Get > /config/dict-trees/list` |
-| `{param}` | 路径参数 | `/certificate/xxx/delete/{id}` |
-| `Post >` | POST 请求 | — |
-| `Get >` | GET 请求 | — |
-| `Put >` | PUT 请求 | — |
-| `Delete >` | DELETE 请求 | — |
-
-### 6.3 在组件中使用 API
-
-API 通过 DVA 的 `dispatch` 和 `Connect` 来调用。`declareRequest` 会自动生成对应的 dva effect:
-
-```js
-import { Connect } from "@cqsjjb/jjb-dva-runtime";
-import { NS_USER_CERTIFICATE } from "~/enumerate/namespace";
-
-function List({ dispatch, userCertificate }) {
- const fetchData = () => {
- dispatch({
- type: `${NS_USER_CERTIFICATE}/userCertificateList`, // namespace/接口名
- payload: { page: 1, size: 10 },
- });
- };
-
- return {/* ... */}
;
-}
-
-export default Connect([NS_USER_CERTIFICATE], true)(List);
-```
-
----
-
-## 7. 状态管理(DVA)
-
-### 7.1 Namespace 定义
-
-`src/enumerate/namespace/index.js` 中定义了所有 DVA namespace:
-
-```js
-export const NS_GLOBAL = defineNamespace("global");
-export const NS_PERSNONEL_CERTFICATE = defineNamespace("personnelCertificate");
-export const NS_CORP_CERTIFICATE = defineNamespace("corpCertificate");
-export const NS_USER_CERTIFICATE = defineNamespace("userCertificate");
-export const NS_COURSEWARE = defineNamespace("courseware");
-```
-
-### 7.2 Connect 高阶组件
-
-```js
-Connect([NS_USER_CERTIFICATE], true)(MyComponent)
-```
-
-- 第一个参数:需要连接的 namespace 数组
-- 第二个参数:是否在组件挂载时自动加载数据(`true` 表示自动触发 `load` effect)
-
-### 7.3 数据流向
-
-```
-dispatch(action) → DVA Effect → declareRequest → HTTP API → reducer → state 更新 → 组件重渲染
-```
-
-### 7.4 本地开发时的限制
-
-本地独立运行时(非底座环境),DVA 状态管理正常可用,但 `declareRequest` 发起的 HTTP 请求会因缺少认证 Token 而返回 **401**。详见 [§10 已知问题](#10-已知问题与注意事项)。
-
----
-
-## 8. 共享组件
-
-业务组件位于 `src/components/` 目录下,目前包括:
-
-```
-src/components/
-├── PersonInChargeInfo/ # 负责人详情组件
-├── PersonInChargeList/ # 负责人列表组件(含搜索、分页、CRUD)
-├── SpecialCertificateInfo/ # 特种证书详情组件
-└── SpecialCertificateList/ # 特种证书列表组件
-```
-
-组件通过 `@/components/xxx` 或别名 `~/components/xxx` 引入:
-
-```js
-import PersonInChargeList from "~/components/PersonInChargeList";
-```
-
-### 8.1 组件参数传递
-
-列表组件通过 `props` 接收业务参数:
-
-```js
-
-```
-
----
-
-## 9. 本地模拟布局
-
-### 9.1 工作原理
-
-`src/pages/Container/index.js` 中的 `AppMiddle` 组件检测运行环境:
-
-```js
-function AppMiddle(props) {
- const content = process.env.NODE_ENV === "development" && !window.__POWERED_BY_QIANKUN__
- ? {props.children}
- : props.children;
- // ...
-}
-```
-
-- **本地开发**(`development` + 非 qiankun):使用 `SimulatedLayout` 包裹内容,提供模拟的侧边栏、面包屑和标签页
-- **底座环境**:由底座平台提供真实的布局
-
-### 9.2 SimulatedLayout 功能
-
-`src/pages/Container/Layout/index.jsx` 提供:
-
-| 功能 | 说明 |
-|------|------|
-| 侧边栏 | 使用 `menuConfig.js` 的菜单数据渲染,支持折叠 |
-| 面包屑 | 根据当前路径自动计算导航路径 |
-| 多标签页 | 支持打开多个页面标签,右键关闭操作 |
-| 标签持久化 | 使用 sessionStorage 保存标签状态 |
-| 主题适配 | 通过 `window.base?.themeConfig` 支持底座主题切换 |
-
----
-
-## 10. 已知问题与注意事项
-
-### 10.1 API 401 错误
-
-**现象**:本地启动后,点击侧边栏菜单(除 Test 页面外),控制台报 401 错误。
-
-**原因**:本项目是 qiankun 微前端子应用,API 请求需要的认证 Token 由 GBS 底座注入。本地独立运行时没有底座,也就没有 Token,所有 API 调用被拒绝。
-
-**处理方式**:
-- **纯前端调试**:使用 Test 页面(`/certificate/container/Test`),该页面不发起任何 API 请求
-- **完整功能调试**:在 GBS 底座环境中打开应用
-
-### 10.2 路由路径与菜单 key 必须匹配
-
-菜单的 `key` 值必须和文件目录层级完全一致。错误示例见 [§4.3 菜单配置注意事项](#43-菜单配置注意事项)。
-
-### 10.3 重命名项目目录后需重新安装依赖
-
-由于 pnpm 使用基于绝对路径的符号链接管理 `node_modules`,重命名项目根目录后需要:
-
-```bash
-Remove-Item -Recurse -Force node_modules
-pnpm install
-```
-
-### 10.4 权限控制
-
-页面使用 `@cqsjjb/jjb-common-decorator/permission` 的 `Permission` 装饰器控制访问:
-
-```js
-import { Permission } from "@cqsjjb/jjb-common-decorator/permission";
-
-export default Connect([NS_USER_CERTIFICATE], true)(Permission(List));
-```
-
-权限码由底座平台管理,本地开发时权限校验可能不生效。
-
-### 10.5 pnpm overrides
-
-`package.json` 中通过 `pnpm.overrides` 强制统一 React 等依赖版本,避免多副本冲突:
-
-```json
-{
- "pnpm": {
- "overrides": {
- "react": "$react",
- "react-dom": "$react-dom"
- }
- }
-}
-```
-
----
-
-## 11. 目录结构参考
-
-```
-safetyEval-service-frontend/
-├── public/
-│ └── index.html # HTML 模板
-├── src/
-│ ├── main.js # 应用入口(setup + 生命周期导出)
-│ ├── api/ # API 接口声明
-│ │ ├── global/
-│ │ ├── userCertificate/
-│ │ ├── corpCertificate/
-│ │ └── courseware/
-│ ├── components/ # 共享业务组件
-│ │ ├── PersonInChargeList/
-│ │ ├── PersonInChargeInfo/
-│ │ ├── SpecialCertificateList/
-│ │ └── SpecialCertificateInfo/
-│ ├── enumerate/ # 枚举/常量定义
-│ │ ├── namespace/ # DVA namespace
-│ │ ├── context/ # React Context
-│ │ └── constant/ # 常量
-│ ├── pages/
-│ │ └── Container/
-│ │ ├── index.js # 容器入口(Antd 主题 + 布局切换)
-│ │ ├── Entry/ # 底座入口页
-│ │ ├── Layout/ # 本地模拟布局
-│ │ │ ├── index.jsx # SimulatedLayout 组件
-│ │ │ └── menuConfig.js # ★ 菜单配置
-│ │ ├── Test/ # 测试页面(无 API 依赖)
-│ │ ├── Supervision/ # 监管端
-│ │ │ ├── EnterpriseLicense/
-│ │ │ └── PersonnelLicense/
-│ │ ├── BranchCompany/ # 分公司端
-│ │ │ └── EnterpriseLicense/
-│ │ └── Stakeholder/ # 干系人端
-│ │ └── EnterpriseLicense/
-│ ├── assets/ # 静态资源
-│ └── utils/ # 工具函数
-├── jjb.config.js # 项目配置(端口、API_HOST、主题等)
-├── package.json
-├── pnpm-lock.yaml
-└── pnpm-workspace.yaml
-```
diff --git a/docs/startup.md b/docs/startup.md
deleted file mode 100644
index 6fb7745..0000000
--- a/docs/startup.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# 证照管理子应用 — 快速启动
-
-## 环境要求
-
-- Node.js >= 18
-- pnpm >= 8
-
-## 启动
-
-```bash
-# 安装依赖(首次或重命名项目目录后)
-pnpm install
-
-# 启动开发服务器
-pnpm run serve:development
-```
-
-## 访问
-
-| 地址 | 说明 |
-|------|------|
-| `http://localhost:8081/certificate/container/` | 应用首页 |
-| `http://localhost:8081/certificate/container/Test` | 测试页面(无 API 依赖,纯前端调试可用) |
-
-## 常用命令
-
-| 命令 | 说明 |
-|------|------|
-| `pnpm run serve:development` | 开发环境启动(推荐) |
-| `pnpm run serve:production` | 生产环境配置启动 |
-| `pnpm run build:development` | 开发环境构建 |
-| `pnpm run build:production` | 生产环境构建 |
-
-## 技术栈
-
-- React 18 + Ant Design 5.x
-- @cqsjjb/jjb-dva-runtime(GBS 底座 DVA 运行时)
-- rspack 构建 / pnpm 包管理
-- qiankun 微前端子应用
-
-## 重要提示
-
-- 本项目为 GBS 底座微前端子应用,独立启动时有内置模拟布局
-- 本地独立运行时 API 调用会返回 401(缺少底座注入的认证 Token)
-- 仅 Test 页面可在本地无底座环境下正常访问
-- 重命名项目目录后需 `pnpm install` 重建 node_modules 符号链接
-- 完整开发指南请参考 [dev-guide.md](./dev-guide.md)
diff --git a/docs/test-reports/测试文档.md b/docs/test-reports/测试文档.md
deleted file mode 100644
index 4185771..0000000
--- a/docs/test-reports/测试文档.md
+++ /dev/null
@@ -1,211 +0,0 @@
-# 企业信息管理 — 测试报告(最新)
-
-> 覆盖模块:机构信息、部门岗位、人员信息、人员变更、离职申请、资质证书、装备信息
-> 原型对照:`docs/原型/设计文件 (3).pdf` ~ `设计文件 (9).pdf`
-> 更新日期:2026-06-23
-
----
-
-## 1. 测试环境
-
-| 项 | 说明 |
-|---|---|
-| 前端 | `safetyEval-service-frontend`,`npm run dev` / `pnpm dev` |
-| 后端 | `safetyEval-service`,`http://127.0.0.1:8095/safetyEval`,profile=`local` |
-| 数据库 | 执行 `safetyEval-service/docs/init-v2.sql` 及末尾测试数据段 |
-| Node | `source scripts/setup-test-env.sh` 或 JetBrains Node 24.x |
-
----
-
-## 2. 自动化脚本
-
-### 2.1 接口联调(细粒度)
-
-```bash
-cd safetyEval-service-frontend
-source scripts/setup-test-env.sh # 可选
-node scripts/test-enterprise-info-granular.mjs
-```
-
-- 脚本:`scripts/test-enterprise-info-granular.mjs`
-- 覆盖:8 模块 CRUD、分页、搜索、字段组装(`deptName`/`postName`/`account`/`auditStatusCode`)
-- 环境变量:`API_BASE`(默认 `http://127.0.0.1:8095/safetyEval`)
-
-### 2.2 前端 UI 静态检查
-
-```bash
-node scripts/test-enterprise-info-ui-check.mjs
-```
-
-- 脚本:`scripts/test-enterprise-info-ui-check.mjs`
-- 检查:公共工具、列表列、弹窗布局、变更次数样式、默认上传配置
-
-### 2.3 一键执行
-
-```bash
-node scripts/test-enterprise-info-granular.mjs && node scripts/test-enterprise-info-ui-check.mjs
-```
-
----
-
-## 3. 问题修复对照(用户反馈 8 项)
-
-| # | 问题 | 处理方式 | 验证用例 |
-|---|------|----------|----------|
-| 1 | 列表未展示部门/岗位 | 后端 `OrgPersonnelViewEnricher` 组装 `deptName`/`postName`;前端 adapter 映射 | EI-API-STAFF-05~08;UI-STAFF-03 |
-| 2 | 新增/编辑文字遮挡 | 弹窗改 `layout="vertical"` 或 `labelCol/wrapperCol=24` | UI-PAGE-*-03;手工打开各模块弹窗 |
-| 3 | 离职缺审核状态/用户名 | CO 增 `account`;enricher 组装;列表 Tag 展示 | EI-API-RESIGN-04~05;UI-RESIGN-01~02 |
-| 4 | 页面卡顿/报错 | 去掉失败的上传/删文件调用;修复 SELECT 空选项 | 控制台无红错;列表加载 <3s |
-| 5 | 变更次数配色 | `CHANGE_COUNT_STYLE` 蓝色高亮/灰色零值 | UI-CHANGE-01;人员变更列表目视 |
-| 6 | 新增人员部门/岗位不可选 | 人员表单改用 antd `Select`;`formSelectField` 适配 Search | UI-STAFF-01~02;TC-STAFF-03 |
-| 7 | 上传默认通过 | `src/utils/mockUpload.js` 固定 URL | UI-COMMON-03;TC-UPLOAD-* |
-| 8 | 其他页面问题 | 见第 4 节用例矩阵 | 全量手工 + 自动化 |
-
----
-
-## 4. 测试用例矩阵
-
-### 4.1 机构信息(原型:设计文件 3)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-ORG-01 | UI | 进入机构信息页 | 标题/副标题与原型一致;表单只读 |
-| TC-ORG-02 | 功能 | 点击修改 → 暂存 | 成功提示;`authStatusCode=0` |
-| TC-ORG-03 | 功能 | 点击提交 | 成功提示;字段回显正确 |
-| TC-ORG-04 | API | EI-API-ORG-* | 分页/详情/修改通过 |
-
-### 4.2 部门岗位(原型:设计文件 4)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-DEPT-01 | UI | 左侧树 + 右侧列表 | 布局与原型一致 |
-| TC-DEPT-02 | 功能 | 新增/编辑部门 | 弹窗 vertical,文字不遮挡 |
-| TC-DEPT-03 | 功能 | 进入岗位列表,增删改岗位 | 岗位关联当前部门 |
-| TC-DEPT-04 | API | EI-API-DEPT/POS-* | 通过 |
-
-### 4.3 人员信息(原型:设计文件 5)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-STAFF-01 | UI | 列表列 | 用户名称、账号、**部门**、**岗位**、证照 |
-| TC-STAFF-02 | 功能 | 搜索部门/岗位 | 下拉有选项,筛选生效 |
-| TC-STAFF-03 | 功能 | 新增人员,选部门后选岗位 | 岗位按部门过滤,可提交 |
-| TC-STAFF-04 | 功能 | 编辑/查看/重置密码/删除 | 各操作正常 |
-| TC-STAFF-05 | 功能 | 证书子页 | 上传默认 URL,增删改查 |
-| TC-STAFF-06 | API | EI-API-STAFF/CERT-* | 通过;列表含 deptName/postName |
-
-### 4.4 人员变更(原型:设计文件 6)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-CHANGE-01 | UI | 信息变更数 >0 | 蓝色链接样式,可点进日志 |
-| TC-CHANGE-02 | UI | 变更数 =0 | 灰色显示 |
-| TC-CHANGE-03 | 功能 | 离职审核通过/退回 | 状态 Tag 更新 |
-| TC-CHANGE-04 | API | EI-API-CHANGE-* | 分页通过 |
-
-### 4.5 离职申请(原型:设计文件 7)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-RESIGN-01 | UI | 列表 | 用户名、姓名、部门、**审核状态 Tag** |
-| TC-RESIGN-02 | 功能 | 新增离职申请 | 弹窗 vertical;上传默认通过 |
-| TC-RESIGN-03 | 功能 | 按审核状态筛选 | 结果正确 |
-| TC-RESIGN-04 | API | EI-API-RESIGN-* | account/auditStatusCode 有值 |
-
-### 4.6 资质证书(原型:设计文件 8)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-QUAL-01 | UI | 列表/弹窗 | 标签不遮挡;保密提示可见 |
-| TC-QUAL-02 | 功能 | 新增证书 + 上传 | 默认图片 URL 写入 `certImageUrl` |
-| TC-QUAL-03 | API | EI-API-QUAL-* | 通过 |
-
-### 4.7 装备信息(原型:设计文件 9)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-EQUIP-01 | UI | 列表/弹窗 | 双列表单,标签完整 |
-| TC-EQUIP-02 | 功能 | 是否双路下拉 | 可选是/否 |
-| TC-EQUIP-03 | API | EI-API-EQUIP-* | 通过 |
-
-### 4.8 上传(全局)
-
-| ID | 类型 | 步骤 | 预期 |
-|----|------|------|------|
-| TC-UPLOAD-01 | 功能 | 离职报告上传 | `reportFileUrl` = 默认 URL |
-| TC-UPLOAD-02 | 功能 | 机构/人员证书上传 | `certImageUrl` / `certAttachmentUrl` = 默认 URL |
-
----
-
-## 5. 原型 UI 对照检查清单
-
-手工打开各页,对照 PDF 检查:
-
-- [ ] 页面标题、副标题文案
-- [ ] 搜索区字段与原型一致
-- [ ] 表格列顺序、列名
-- [ ] 主按钮文案(新增/添加)
-- [ ] 弹窗宽度、表单项顺序
-- [ ] 信息变更数颜色(蓝/灰)
-- [ ] 审核状态 Tag 颜色(灰/绿/红)
-- [ ] 无控制台 Error / 无长时间 Loading
-
----
-
-## 6. 执行记录(2026-06-23 第二轮)
-
-```
-接口测试: 58 / 58 通过
-UI 静态检查: 31 / 31 通过
-
-本轮修复:
-- 资质 remark 全链路 + 启用/禁用按钮
-- 人员变更:账户列、变更数颜色(String key)、就职状态/审核状态 Tag、后端 employmentStatusCode 查询
-- 人员:移除重置密码、birthDate dayjs 回显/提交格式化
-- 部门岗位:左树右岗布局,按 deptId 查岗位
-- 离职:账户列、remark 分离、personnelId 自动匹配、时间格式化
-- 装备:instrumentType 列表字段、表单回显
-- 时间:formatDateTime → YYYY-MM-DD HH:mm:ss
-```
-
-## 7. 执行记录(2026-06-23 第一轮)
-
-```
-执行人:自动化脚本
-执行时间:2026-06-23(后端重启后)
-后端:http://127.0.0.1:8095/safetyEval
-
-接口测试: 58 / 58 通过
-UI 静态检查: 31 / 31 通过
-
-字段组装验证(已通过):
-- EI-API-STAFF-05~08:deptName / postName 正常
-- EI-API-RESIGN-04~05:auditStatusCode / account 正常
-
-重跑命令:
- source scripts/setup-test-env.sh
- node scripts/test-enterprise-info-granular.mjs
- node scripts/test-enterprise-info-ui-check.mjs
-```
-
-### 6.1 手工记录模板
-
----
-
-## 7. 已知限制
-
-1. **上传**:联调阶段不走真实文件服务,统一写入固定花瓣 URL。
-2. **原型像素级**:PDF 与 Ant Design 组件存在间距差异,以字段/交互一致为准。
-3. **人员变更删除**:列表删除为变更记录删除,与人员主数据删除不同,需与产品确认。
-
----
-
-## 8. 相关代码路径
-
-| 用途 | 路径 |
-|------|------|
-| 页面 | `src/pages/Container/EnterpriseInfo/**` |
-| API 适配 | `src/api/enterpriseInfo/adapter.js` |
-| 表单工具 | `src/utils/enterpriseForm.js` |
-| 上传 Mock | `src/utils/mockUpload.js` |
-| 后端组装 | `safetyEval-app/.../OrgPersonnelViewEnricher.java` |
diff --git a/docs/test-reports/测试用例/setup-test-env.sh b/docs/test-reports/测试用例/setup-test-env.sh
deleted file mode 100755
index c14c4df..0000000
--- a/docs/test-reports/测试用例/setup-test-env.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-# 企业信息管理联调测试环境变量
-# 用法: source scripts/setup-test-env.sh
-
-export API_BASE="${API_BASE:-http://127.0.0.1:8095/safetyEval}"
-export SAFETY_EVAL_API_HOST="${SAFETY_EVAL_API_HOST:-http://127.0.0.1:8095}"
-
-# JetBrains 内置 Node(系统 PATH 无 node 时使用)
-if ! command -v node >/dev/null 2>&1; then
- _JB_NODE="$HOME/Library/Application Support/JetBrains/IntelliJIdea2025.3/node/versions/24.16.0/bin/node"
- if [[ -x "$_JB_NODE" ]]; then
- export NODE="$_JB_NODE"
- export PATH="$(dirname "$_JB_NODE"):$PATH"
- fi
-fi
-
-echo "API_BASE=$API_BASE"
-echo "SAFETY_EVAL_API_HOST=$SAFETY_EVAL_API_HOST"
-echo "NODE=$(command -v node || echo '未找到')"
diff --git a/docs/test-reports/测试用例/test-enterprise-info-api.mjs b/docs/test-reports/测试用例/test-enterprise-info-api.mjs
deleted file mode 100644
index 2fc0bd7..0000000
--- a/docs/test-reports/测试用例/test-enterprise-info-api.mjs
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * 企业信息管理 - 后端接口联调冒烟测试
- * 运行: API_BASE=http://127.0.0.1:8095/safetyEval node scripts/test-enterprise-info-api.mjs
- */
-const API_BASE = process.env.API_BASE || "http://127.0.0.1:8095/safetyEval";
-
-const results = [];
-let passed = 0;
-let failed = 0;
-
-function assert(name, condition, detail = "") {
- if (condition) {
- passed += 1;
- results.push({ name, status: "PASS", detail });
- }
- else {
- failed += 1;
- results.push({ name, status: "FAIL", detail });
- }
-}
-
-async function request(method, path, body) {
- const url = `${API_BASE}${path}`;
- const options = {
- method,
- headers: { "Content-Type": "application/json" },
- };
- if (body !== undefined) {
- options.body = JSON.stringify(body);
- }
- const res = await fetch(url, options);
- const text = await res.text();
- try {
- return JSON.parse(text);
- }
- catch {
- return { success: false, raw: text, status: res.status };
- }
-}
-
-async function runTests() {
- console.log(`\nAPI Base: ${API_BASE}\n`);
-
- // ── 机构信息 ──
- let orgPage = await request("GET", "/org-info/page?current=1&size=1");
- assert("机构信息-分页", orgPage.success === true, `code=${orgPage.code}`);
-
- let orgId = orgPage.data?.[0]?.id;
- if (!orgId) {
- const created = await request("POST", "/org-info/save", {
- unitName: "联调测试机构",
- creditCode: "91110000MA0TEST001",
- principalName: "测试负责人",
- principalPhone: "13800138000",
- registerAddress: "测试地址",
- businessAddress: "测试地址",
- authStatusCode: 0,
- authStatusName: "草稿",
- });
- assert("机构信息-新增", created.success === true, created.message);
- orgId = created.data?.id;
- }
-
- if (orgId) {
- const orgDetail = await request("GET", `/org-info/get?id=${orgId}`);
- assert("机构信息-详情", orgDetail.success === true && orgDetail.data?.id === orgId);
- const modified = await request("POST", "/org-info/modify", {
- ...orgDetail.data,
- principalName: "测试负责人-已改",
- authStatusCode: 1,
- authStatusName: "已提交",
- });
- assert("机构信息-修改", modified.success === true, modified.message);
- }
-
- // ── 部门 ──
- const deptPage = await request("GET", "/org-department/page?current=1&size=10");
- assert("部门-分页", deptPage.success === true, `total=${deptPage.total}`);
-
- const deptCreated = await request("POST", "/org-department/save", {
- deptName: "联调测试部门",
- managerName: "测试负责人",
- deptLevelName: "一级",
- });
- assert("部门-新增", deptCreated.success === true, deptCreated.message);
- const deptId = deptCreated.data?.id;
-
- if (deptId) {
- const deptModified = await request("POST", "/org-department/modify", {
- id: deptId,
- deptName: "联调测试部门-已改",
- managerName: "测试负责人",
- deptLevelName: "一级",
- });
- assert("部门-修改", deptModified.success === true);
- }
-
- // ── 岗位 ──
- const posCreated = await request("POST", "/org-position/save", {
- positionName: "联调测试岗位",
- dutyDesc: "测试职责",
- deptId: deptId || "102",
- });
- assert("岗位-新增", posCreated.success === true, posCreated.message);
- const posId = posCreated.data?.id;
-
- const posPage = await request("GET", `/org-position/page?current=1&size=10&deptId=${deptId || ""}`);
- assert("岗位-分页", posPage.success === true, `count=${posPage.data?.length}`);
-
- // ── 人员 ──
- const staffCreated = await request("POST", "/org-personnel/save", {
- userName: "联调测试人员",
- account: "13900001234",
- genderCode: 1,
- genderName: "男",
- employmentStatusCode: 1,
- employmentStatusName: "在职",
- });
- assert("人员-新增", staffCreated.success === true, staffCreated.message);
- const staffId = staffCreated.data?.id;
-
- if (staffId) {
- const staffPage = await request("GET", `/org-personnel/page?current=1&size=10&userName=${encodeURIComponent("联调")}`);
- assert("人员-分页", staffPage.success === true);
- const staffDetail = await request("GET", `/org-personnel/get?id=${staffId}`);
- assert("人员-详情", staffDetail.success === true && staffDetail.data?.userName?.includes("联调"));
- }
-
- // ── 装备 ──
- const equipCreated = await request("POST", "/org-equipment/save", {
- deviceName: "联调测试设备",
- deviceModel: "T-001",
- manufacturer: "测试厂家",
- enableFlag: 1,
- });
- assert("装备-新增", equipCreated.success === true, equipCreated.message);
- const equipId = equipCreated.data?.id;
-
- const equipPage = await request("GET", "/org-equipment/page?current=1&size=10");
- assert("装备-分页", equipPage.success === true);
-
- if (equipId) {
- const equipDetail = await request("GET", `/org-equipment/get?id=${equipId}`);
- const toggleFlag = equipDetail.data?.enableFlag === 1 ? 0 : 1;
- const toggled = await request("POST", "/org-equipment/modify", {
- ...equipDetail.data,
- enableFlag: toggleFlag,
- });
- assert("装备-启停(modify)", toggled.success === true);
- }
-
- // ── 资质证书 ──
- const qualCreated = await request("POST", "/org-qualification/save", {
- licenseTypeName: "测试证照",
- certName: "联调测试证书",
- certNo: `TEST-${Date.now()}`,
- issueOrg: "测试机关",
- issueDate: "2026-01-01",
- validStartDate: "2026-01-01",
- validEndDate: "2027-01-01",
- enableFlag: 1,
- });
- assert("资质-新增", qualCreated.success === true, qualCreated.message);
- const qualId = qualCreated.data?.id;
-
- const qualPage = await request("GET", "/org-qualification/page?current=1&size=10");
- assert("资质-分页", qualPage.success === true);
-
- // ── 离职申请 ──
- const resignCreated = await request("POST", "/org-resign-apply/save", {
- applicantName: "联调测试人员",
- applyTime: "2026-06-20T10:00:00",
- expectedResignDate: "2026-07-31",
- resignReason: "联调测试",
- auditStatusCode: 0,
- auditStatusName: "未审核",
- });
- assert("离职申请-新增", resignCreated.success === true, resignCreated.message);
- const resignId = resignCreated.data?.id;
-
- if (resignId) {
- const audited = await request("POST", "/org-resign-apply/modify", {
- id: resignId,
- auditStatusCode: 1,
- auditStatusName: "已审核",
- });
- assert("离职申请-审核", audited.success === true);
- }
-
- // ── 清理 ──
- if (qualId) {
- await request("POST", `/org-qualification/delete?id=${qualId}`);
- }
- if (equipId) {
- await request("POST", `/org-equipment/delete?id=${equipId}`);
- }
- if (staffId) {
- await request("POST", `/org-personnel/delete?id=${staffId}`);
- }
- if (posId) {
- await request("POST", `/org-position/delete?id=${posId}`);
- }
- if (deptId) {
- await request("POST", `/org-department/delete?id=${deptId}`);
- }
-
- assert("清理-完成", true);
-
- console.log("\n========== 企业信息管理 接口联调测试 ==========\n");
- results.forEach((r) => {
- const icon = r.status === "PASS" ? "✓" : "✗";
- console.log(`${icon} [${r.status}] ${r.name}${r.detail ? ` — ${r.detail}` : ""}`);
- });
- console.log(`\n合计: ${passed + failed} 通过: ${passed} 失败: ${failed}\n`);
- process.exit(failed > 0 ? 1 : 0);
-}
-
-runTests().catch((err) => {
- console.error("测试执行失败:", err.message);
- process.exit(1);
-});
diff --git a/docs/test-reports/测试用例/test-enterprise-info-granular.mjs b/docs/test-reports/测试用例/test-enterprise-info-granular.mjs
deleted file mode 100644
index 8e76965..0000000
--- a/docs/test-reports/测试用例/test-enterprise-info-granular.mjs
+++ /dev/null
@@ -1,371 +0,0 @@
-/**
- * 企业信息管理 - 细粒度接口联调测试
- *
- * 运行:
- * source scripts/setup-test-env.sh
- * node scripts/test-enterprise-info-granular.mjs
- */
-const API_BASE = process.env.API_BASE || "http://127.0.0.1:8095/safetyEval";
-const TS = Date.now();
-
-const results = [];
-let passed = 0;
-let failed = 0;
-const createdIds = {};
-
-/** 保持 ID 为字符串,避免雪花 ID 超出 JS 安全整数精度 */
-function normalizeId(id) {
- if (id === undefined || id === null || id === "") return undefined;
- return String(id);
-}
-
-function record(id, name, condition, detail = "") {
- const status = condition ? "PASS" : "FAIL";
- if (condition) passed += 1;
- else failed += 1;
- results.push({ id, name, status, detail });
-}
-
-async function request(method, path, body) {
- const url = `${API_BASE}${path}`;
- const options = {
- method,
- headers: { "Content-Type": "application/json" },
- };
- if (body !== undefined) options.body = JSON.stringify(body);
- const res = await fetch(url, options);
- const text = await res.text();
- try {
- return { httpStatus: res.status, ...JSON.parse(text) };
- }
- catch {
- return { httpStatus: res.status, success: false, raw: text };
- }
-}
-
-function assertSuccess(id, name, res, extra = "") {
- const ok = res.success === true && res.code === "0";
- record(id, name, ok, ok ? extra : (res.message || res.raw || `http=${res.httpStatus}`));
- return ok;
-}
-
-function assertHasData(id, name, res, extra = "") {
- const ok = res.success === true && res.code === "0" && res.data != null;
- record(id, name, ok, ok ? extra : (res.message || "data 为空"));
- return ok;
-}
-
-async function testPagination(id, name, path, minTotal = 1) {
- const sep = path.includes("?") ? "&" : "?";
- const page1 = await request("GET", `${path}${sep}current=1&size=2`);
- const ok1 = assertSuccess(`${id}-01`, `${name}-分页第1页`, page1, `total=${page1.total ?? page1.totalCount ?? "?"}`);
- const page2 = await request("GET", `${path}${sep}current=2&size=2`);
- assertSuccess(`${id}-02`, `${name}-分页第2页`, page2);
- if (ok1 && (page1.total ?? page1.totalCount ?? 0) >= minTotal) {
- record(`${id}-03`, `${name}-分页total有效`, true, `total=${page1.total ?? page1.totalCount}`);
- }
- return page1;
-}
-
-async function run() {
- console.log(`\n=== 企业信息管理 细粒度接口测试 ===`);
- console.log(`API Base: ${API_BASE}`);
- console.log(`Timestamp: ${TS}\n`);
-
- const orgPage = await testPagination("EI-API-ORG", "机构信息", "/org-info/page", 1);
- let orgId = orgPage.data?.[0]?.id;
-
- if (orgId) {
- const orgGet = await request("GET", `/org-info/get?id=${normalizeId(orgId)}`);
- assertHasData("EI-API-ORG-04", "机构信息-详情", orgGet, `id=${orgId}`);
- const orgMod = await request("POST", "/org-info/modify", {
- ...orgGet.data,
- principalName: orgGet.data.principalName,
- });
- assertSuccess("EI-API-ORG-05", "机构信息-修改", orgMod);
- }
-
- await testPagination("EI-API-DEPT", "部门", "/org-department/page", 1);
-
- const deptName = `联调部门-${TS}`;
- const deptSave = await request("POST", "/org-department/save", {
- deptName,
- managerName: "测试负责人",
- deptLevelName: "一级",
- });
- if (assertSuccess("EI-API-DEPT-04", "部门-新增", deptSave)) {
- createdIds.dept = normalizeId(deptSave.data?.id);
- const deptGet = await request("GET", `/org-department/get?id=${createdIds.dept}`);
- if (assertHasData("EI-API-DEPT-05", "部门-详情", deptGet)) {
- const deptMod = await request("POST", "/org-department/modify", {
- id: createdIds.dept,
- deptName: `${deptName}-改`,
- managerName: "测试负责人",
- deptLevelName: "一级",
- });
- assertSuccess("EI-API-DEPT-06", "部门-修改", deptMod);
- const deptSearch = await request("GET", `/org-department/page?current=1&size=10&deptName=${encodeURIComponent(deptName)}`);
- assertSuccess("EI-API-DEPT-07", "部门-名称搜索", deptSearch, `count=${deptSearch.data?.length ?? 0}`);
- }
- }
-
- const posSave = await request("POST", "/org-position/save", {
- positionName: `联调岗位-${TS}`,
- dutyDesc: "测试职责",
- deptId: createdIds.dept || "102",
- });
- if (assertSuccess("EI-API-POS-01", "岗位-新增", posSave)) {
- createdIds.pos = normalizeId(posSave.data?.id);
- }
- await testPagination("EI-API-POS-PG", "岗位", "/org-position/page", 1);
- if (createdIds.pos) {
- const posGet = await request("GET", `/org-position/get?id=${createdIds.pos}`);
- if (assertHasData("EI-API-POS-04", "岗位-详情", posGet)) {
- const posMod = await request("POST", "/org-position/modify", {
- id: createdIds.pos,
- positionName: `联调岗位-${TS}-改`,
- dutyDesc: "已修改",
- deptId: createdIds.dept || posGet.data?.deptId,
- });
- assertSuccess("EI-API-POS-05", "岗位-修改", posMod);
- }
- }
-
- const staffSave = await request("POST", "/org-personnel/save", {
- userName: `联调人员-${TS}`,
- account: `139${String(TS).slice(-8)}`,
- genderCode: 1,
- genderName: "男",
- employmentStatusCode: 1,
- employmentStatusName: "在职",
- deptId: createdIds.dept || "102",
- postId: createdIds.pos || "205",
- });
- if (assertSuccess("EI-API-STAFF-01", "人员-新增", staffSave)) {
- createdIds.staff = normalizeId(staffSave.data?.id);
- const staffGet = await request("GET", `/org-personnel/get?id=${createdIds.staff}`);
- if (assertHasData("EI-API-STAFF-02", "人员-详情", staffGet)) {
- record(
- "EI-API-STAFF-05",
- "人员-部门名称组装",
- !!staffGet.data.deptName,
- `deptName=${staffGet.data.deptName ?? "(空)"}`,
- );
- record(
- "EI-API-STAFF-06",
- "人员-岗位名称组装",
- !!staffGet.data.postName,
- `postName=${staffGet.data.postName ?? "(空)"}`,
- );
- const staffPage = await request("GET", `/org-personnel/page?current=1&size=10&userName=${encodeURIComponent("联调人员")}`);
- assertSuccess("EI-API-STAFF-03", "人员-姓名搜索", staffPage);
- const pageRow = staffPage.data?.[0];
- if (pageRow) {
- record("EI-API-STAFF-07", "人员列表-部门字段", !!pageRow.deptName, `deptName=${pageRow.deptName ?? "(空)"}`);
- record("EI-API-STAFF-08", "人员列表-岗位字段", !!pageRow.postName, `postName=${pageRow.postName ?? "(空)"}`);
- }
- const staffMod = await request("POST", "/org-personnel/modify", {
- id: createdIds.staff,
- userName: `联调人员-${TS}-改`,
- account: staffGet.data.account,
- genderCode: staffGet.data.genderCode,
- genderName: staffGet.data.genderName,
- employmentStatusCode: staffGet.data.employmentStatusCode,
- employmentStatusName: staffGet.data.employmentStatusName,
- deptId: staffGet.data.deptId,
- postId: staffGet.data.postId,
- });
- assertSuccess("EI-API-STAFF-04", "人员-修改", staffMod);
- if (staffMod.success) {
- const staffAfterMod = await request("GET", `/org-personnel/get?id=${createdIds.staff}`);
- record(
- "EI-API-STAFF-10",
- "人员-修改后变更次数",
- (staffAfterMod.data?.changeCount ?? 0) >= 1,
- `changeCount=${staffAfterMod.data?.changeCount ?? 0}`,
- );
- }
- const dupSave = await request("POST", "/org-personnel/save", {
- userName: `重复账号-${TS}`,
- account: staffGet.data.account,
- genderCode: 1,
- genderName: "男",
- employmentStatusCode: 1,
- employmentStatusName: "在职",
- deptId: staffGet.data.deptId,
- postId: staffGet.data.postId,
- });
- record(
- "EI-API-STAFF-11",
- "人员-账号重复校验",
- dupSave.success === false && String(dupSave.message || "").includes("账号"),
- dupSave.message || `code=${dupSave.code}`,
- );
- const resetPwd = await request("POST", `/org-personnel/reset-password?id=${normalizeId(createdIds.staff)}`);
- assertSuccess("EI-API-STAFF-09", "人员-重置密码", resetPwd);
- }
- }
-
- if (createdIds.staff) {
- const certSave = await request("POST", "/org-personnel-cert/save", {
- personnelId: createdIds.staff,
- certName: `联调证书-${TS}`,
- certNo: `CERT-${TS}`,
- issueOrg: "测试机关",
- validStartDate: "2026-01-01",
- validEndDate: "2027-01-01",
- });
- if (assertSuccess("EI-API-CERT-01", "人员证书-新增", certSave)) {
- createdIds.cert = normalizeId(certSave.data?.id);
- await testPagination("EI-API-CERT", "人员证书", `/org-personnel-cert/page?personnelId=${createdIds.staff}`, 0);
- }
- }
- else {
- record("EI-API-CERT-01", "人员证书-新增", false, "跳过:无人员 id");
- }
-
- await testPagination("EI-API-CHANGE", "人员变更", "/org-personnel-change/page", 0);
-
- // 联调数据可能被审核操作污染,测试前重置种子离职单为「未审核」
- await request("POST", "/org-resign-apply/modify", {
- id: "701",
- personnelId: "403",
- auditStatusCode: 0,
- auditStatusName: "未审核",
- });
-
- const equipSave = await request("POST", "/org-equipment/save", {
- deviceName: `联调设备-${TS}`,
- deviceModel: "T-001",
- manufacturer: "测试厂家",
- enableFlag: 1,
- });
- if (assertSuccess("EI-API-EQUIP-01", "装备-新增", equipSave)) {
- createdIds.equip = normalizeId(equipSave.data?.id);
- const equipGet = await request("GET", `/org-equipment/get?id=${createdIds.equip}`);
- if (assertHasData("EI-API-EQUIP-02", "装备-详情", equipGet)) {
- const toggle = equipGet.data?.enableFlag === 1 ? 0 : 1;
- const equipMod = await request("POST", "/org-equipment/modify", { ...equipGet.data, enableFlag: toggle });
- assertSuccess("EI-API-EQUIP-03", "装备-启停", equipMod);
- }
- }
- await testPagination("EI-API-EQUIP-PG", "装备", "/org-equipment/page", 1);
- const equipByInstrument = await request("GET", "/org-equipment/page?current=1&size=10&instrumentType=检测仪器");
- record(
- "EI-API-EQUIP-04",
- "装备-仪器类型搜索",
- equipByInstrument.success === true && (equipByInstrument.total ?? equipByInstrument.totalCount ?? 0) >= 1 && (equipByInstrument.total ?? equipByInstrument.totalCount ?? 0) < 6,
- `total=${equipByInstrument.total ?? equipByInstrument.totalCount ?? "?"}`,
- );
- const equipByDeviceType = await request("GET", "/org-equipment/page?current=1&size=10&deviceType=便携式");
- record(
- "EI-API-EQUIP-05",
- "装备-设备类型搜索",
- equipByDeviceType.success === true && (equipByDeviceType.total ?? equipByDeviceType.totalCount ?? 0) >= 1,
- `total=${equipByDeviceType.total ?? equipByDeviceType.totalCount ?? "?"}`,
- );
-
- const personnelSeed = await request("GET", "/org-personnel/page?current=1&size=10&userName=钱离职");
- const seedRow = personnelSeed.data?.[0];
- if (seedRow) {
- record("EI-API-CHANGE-04", "人员-变更次数组装", (seedRow.changeCount ?? 0) >= 3, `changeCount=${seedRow.changeCount ?? 0}`);
- record("EI-API-CHANGE-05", "人员-就职状态组装", seedRow.employmentStatusCode === 2, `employmentStatusCode=${seedRow.employmentStatusCode}`);
- }
- const personnelResign = await request("GET", "/org-personnel/page?current=1&size=10&userName=钱离职");
- const resignRow = personnelResign.data?.[0];
- if (resignRow) {
- record("EI-API-CHANGE-06", "人员-离职审核状态", resignRow.resignAuditStatus === 0, `resignAuditStatus=${resignRow.resignAuditStatus ?? "(空)"}`);
- }
- const resignFilter = await request("GET", "/org-personnel/page?current=1&size=10&resignAuditStatus=0&userName=钱离职");
- record(
- "EI-API-CHANGE-07",
- "人员-离职审核状态筛选",
- resignFilter.success === true && (resignFilter.data?.length ?? 0) >= 1,
- `count=${resignFilter.data?.length ?? 0}`,
- );
-
- const qualSave = await request("POST", "/org-qualification/save", {
- licenseTypeName: "测试证照",
- certName: `联调资质-${TS}`,
- certNo: `QUAL-${TS}`,
- issueOrg: "测试机关",
- issueDate: "2026-01-01",
- validStartDate: "2026-01-01",
- validEndDate: "2027-01-01",
- enableFlag: 1,
- });
- if (assertSuccess("EI-API-QUAL-01", "资质-新增", qualSave)) {
- createdIds.qual = normalizeId(qualSave.data?.id);
- }
- await testPagination("EI-API-QUAL-PG", "资质", "/org-qualification/page", 1);
-
- if (createdIds.staff) {
- const resignSave = await request("POST", "/org-resign-apply/save", {
- personnelId: createdIds.staff,
- applicantName: `联调离职-${TS}`,
- applyTime: "2026-06-20T10:00:00",
- expectedResignDate: "2026-07-31",
- resignReason: "联调测试",
- auditStatusCode: 0,
- auditStatusName: "未审核",
- });
- if (assertSuccess("EI-API-RESIGN-01", "离职申请-新增", resignSave)) {
- createdIds.resign = normalizeId(resignSave.data?.id);
- const resignGet = await request("GET", `/org-resign-apply/get?id=${createdIds.resign}`);
- if (assertHasData("EI-API-RESIGN-03", "离职申请-详情", resignGet)) {
- record(
- "EI-API-RESIGN-04",
- "离职-审核状态字段",
- resignGet.data.auditStatusCode === 0,
- `auditStatusCode=${resignGet.data.auditStatusCode}`,
- );
- record(
- "EI-API-RESIGN-05",
- "离职-用户名字段组装",
- !!resignGet.data.account,
- `account=${resignGet.data.account ?? "(空)"}`,
- );
- }
- const audit = await request("POST", "/org-resign-apply/modify", {
- id: createdIds.resign,
- personnelId: createdIds.staff,
- auditStatusCode: 1,
- auditStatusName: "已审核",
- });
- assertSuccess("EI-API-RESIGN-02", "离职申请-审核", audit);
- }
- }
- else {
- record("EI-API-RESIGN-01", "离职申请-新增", false, "跳过:无人员 id");
- }
- await testPagination("EI-API-RESIGN-PG", "离职申请", "/org-resign-apply/page", 0);
-
- const cleanup = [
- ["cert", "/org-personnel-cert/delete"],
- ["resign", "/org-resign-apply/delete"],
- ["staff", "/org-personnel/delete"],
- ["pos", "/org-position/delete"],
- ["dept", "/org-department/delete"],
- ["equip", "/org-equipment/delete"],
- ["qual", "/org-qualification/delete"],
- ];
- for (const [key, path] of cleanup) {
- if (createdIds[key]) {
- const del = await request("POST", `${path}?id=${createdIds[key]}`);
- assertSuccess(`EI-API-CLEAN-${key}`, `清理-${key}`, del);
- }
- }
-
- console.log("\n========== 测试结果 ==========\n");
- results.forEach((r) => {
- const icon = r.status === "PASS" ? "✓" : "✗";
- console.log(`${icon} [${r.status}] ${r.id} ${r.name}${r.detail ? ` — ${r.detail}` : ""}`);
- });
- console.log(`\n合计: ${passed + failed} 通过: ${passed} 失败: ${failed}\n`);
- process.exit(failed > 0 ? 1 : 0);
-}
-
-run().catch((err) => {
- console.error("测试执行失败:", err.message);
- process.exit(1);
-});
diff --git a/docs/test-reports/测试用例/test-enterprise-info-ui-check.mjs b/docs/test-reports/测试用例/test-enterprise-info-ui-check.mjs
deleted file mode 100644
index 6665347..0000000
--- a/docs/test-reports/测试用例/test-enterprise-info-ui-check.mjs
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * 企业信息管理 - 页面 UI / 字段展示 自动化检查
- * 运行: node scripts/test-enterprise-info-ui-check.mjs
- */
-import fs from "node:fs";
-import path from "node:path";
-
-const ROOT = path.resolve(import.meta.dirname, "..");
-const PAGE_DIR = path.join(ROOT, "src/pages/Container/EnterpriseInfo");
-const UTILS = path.join(ROOT, "src/utils");
-
-const checks = [];
-
-function pass(id, name, ok, detail = "") {
- checks.push({ id, name, status: ok ? "PASS" : "FAIL", detail });
-}
-
-function read(rel) {
- return fs.readFileSync(path.join(ROOT, rel), "utf8");
-}
-
-function fileExists(rel) {
- return fs.existsSync(path.join(ROOT, rel));
-}
-
-// ── 公共能力 ──
-pass("UI-COMMON-01", "mockUpload 默认地址", fileExists("src/utils/mockUpload.js"));
-pass("UI-COMMON-02", "enterpriseForm 下拉适配", fileExists("src/utils/enterpriseForm.js"));
-pass("UI-COMMON-03", "DEFAULT_UPLOAD_FILE_URL 配置",
- read("src/utils/mockUpload.js").includes("gd-hbimg.huaban.com"));
-
-// ── 各页面 ──
-const pages = [
- ["OrgInfo", "机构信息"],
- ["DepartmentPosition", "部门岗位"],
- ["PersonnelInfo/List", "人员信息"],
- ["PersonnelChange", "人员变更"],
- ["ResignationApply", "离职申请"],
- ["QualificationCert", "资质证书"],
- ["EquipInfo", "装备信息"],
-];
-
-pages.forEach(([rel, label]) => {
- const content = read(`src/pages/Container/EnterpriseInfo/${rel}/index.js`);
- pass(`UI-PAGE-${rel}-01`, `${label}-页面存在`, content.length > 100);
- pass(`UI-PAGE-${rel}-02`, `${label}-使用 PageHeader`, content.includes("PageHeader"));
- const usesVerticalForm = content.includes('layout="vertical"');
- const usesBrokenLabelCol = /labelCol=\{\{\s*span:\s*24/.test(content);
- const usesFormBuilderModal = /Modal[\s\S]*FormBuilder/.test(content);
- pass(`UI-PAGE-${rel}-03`, `${label}-弹窗表单布局`, usesVerticalForm || !usesFormBuilderModal || !usesBrokenLabelCol,
- usesFormBuilderModal && !usesVerticalForm && usesBrokenLabelCol ? "Modal 内 FormBuilder labelCol=24 导致输入框不可见" : "");
-});
-
-// ── 人员:部门岗位下拉 ──
-const staffPage = read("src/pages/Container/EnterpriseInfo/PersonnelInfo/List/index.js");
-pass("UI-STAFF-01", "人员-部门 Select", staffPage.includes("deptId") && staffPage.includes("Select"));
-pass("UI-STAFF-02", "人员-岗位 Select", staffPage.includes("positionId") && staffPage.includes("Select"));
-pass("UI-STAFF-03", "人员-列表部门列", staffPage.includes('dataIndex: "deptName"'));
-pass("UI-STAFF-04", "人员-重置密码", staffPage.includes("onResetPassword"));
-
-// ── 离职 ──
-const resignPage = read("src/pages/Container/EnterpriseInfo/ResignationApply/index.js");
-pass("UI-RESIGN-01", "离职-审核状态列", resignPage.includes("auditStatus"));
-pass("UI-RESIGN-02", "离职-用户名列", resignPage.includes('dataIndex: "account"'));
-pass("UI-RESIGN-03", "离职-默认上传", resignPage.includes("resolveUploadFileId") || resignPage.includes("mockUpload"));
-
-// ── 变更次数样式 ──
-const changePage = read("src/pages/Container/EnterpriseInfo/PersonnelChange/index.js");
-pass("UI-CHANGE-01", "变更-次数样式", changePage.includes("CHANGE_COUNT_STYLE"));
-pass("UI-CHANGE-02", "变更-从 record 渲染", changePage.includes("getChangeCount(record)"));
-pass("UI-CHANGE-03", "变更-就职/审核状态", changePage.includes("getEmploymentStatusLabel") && changePage.includes("getResignAuditStatusLabel"));
-
-pass("UI-RESIGN-04", "离职-从 record 渲染审核状态", resignPage.includes("getResignAuditStatusLabel(record)"));
-pass("UI-RESIGN-05", "离职-纯文本状态", !resignPage.includes(" {
- const icon = c.status === "PASS" ? "✓" : "✗";
- if (c.status === "PASS") passed += 1;
- else failed += 1;
- console.log(`${icon} [${c.status}] ${c.id} ${c.name}${c.detail ? ` — ${c.detail}` : ""}`);
-});
-console.log(`\n合计: ${checks.length} 通过: ${passed} 失败: ${failed}\n`);
-process.exit(failed > 0 ? 1 : 0);
diff --git a/docs/test-reports/测试用例/test-qual-filing-api.mjs b/docs/test-reports/测试用例/test-qual-filing-api.mjs
deleted file mode 100644
index 682eb61..0000000
--- a/docs/test-reports/测试用例/test-qual-filing-api.mjs
+++ /dev/null
@@ -1,278 +0,0 @@
-/**
- * 资质申请管理 — 前后端联调冒烟测试
- *
- * 运行:
- * API_BASE=http://127.0.0.1:8095/safetyEval ORG_INFO_ID=1 node docs/test-reports/测试用例/test-qual-filing-api.mjs
- *
- * 可选:
- * FRONTEND_BASE=http://127.0.0.1:8081 (检测前端页面是否可访问)
- */
-const API_BASE = process.env.API_BASE || "http://127.0.0.1:8095/safetyEval";
-const ORG_INFO_ID = process.env.ORG_INFO_ID || "1";
-const FRONTEND_BASE = process.env.FRONTEND_BASE || "http://127.0.0.1:8081";
-const DEFAULT_URL =
- "https://s1.aigei.com/prevfiles/6f2754563be2491bad7c957904cd7d2a.jpg?e=2051020800&token=P7S2Xpzfz11vAkASLTkfHN7Fw-oOZBecqeJaxypL:CR60zg7VKDp-jUWyYls_rdvyQMM=";
-
-const results = [];
-let passed = 0;
-let failed = 0;
-
-function assert(name, condition, detail = "") {
- if (condition) {
- passed += 1;
- results.push({ name, status: "PASS", detail });
- console.log(` ✓ ${name}${detail ? ` — ${detail}` : ""}`);
- }
- else {
- failed += 1;
- results.push({ name, status: "FAIL", detail });
- console.log(` ✗ ${name}${detail ? ` — ${detail}` : ""}`);
- }
-}
-
-async function request(method, path, body) {
- const url = `${API_BASE}${path}`;
- const options = {
- method,
- headers: {
- "Content-Type": "application/json",
- orgInfoId: ORG_INFO_ID,
- },
- };
- if (body !== undefined) {
- options.body = JSON.stringify(body);
- }
- const res = await fetch(url, options);
- const text = await res.text();
- try {
- return { httpStatus: res.status, ...JSON.parse(text) };
- }
- catch {
- return { httpStatus: res.status, success: false, raw: text };
- }
-}
-
-async function uploadAllMaterials(filingId) {
- const detail = await request("GET", `/qual-filing/detail?id=${filingId}`);
- const materials = detail.data?.materials || [];
- for (const material of materials) {
- const uploaded = await request("POST", "/qual-filing-material/upload", {
- id: material.id,
- attachmentUrl: DEFAULT_URL,
- });
- if (uploaded.success !== true) {
- return { ok: false, message: uploaded.message, materialId: material.id };
- }
- }
- return { ok: true, count: materials.length };
-}
-
-async function saveCommitment(filingId) {
- return request("POST", "/qual-filing-commitment/save-or-update", {
- filingId,
- signDate: "2026-06-30",
- legalRepSignatureUrl: DEFAULT_URL,
- commitmentContent: "联调测试承诺书",
- });
-}
-
-async function runBackendTests() {
- console.log("\n=== 后端 API(资质申请管理)===");
- console.log(`API_BASE=${API_BASE} orgInfoId=${ORG_INFO_ID}\n`);
-
- // 1. 创建草稿 + 材料模板
- const draft = await request("POST", "/qual-filing/draft?applyTypeCode=1");
- assert("备案申请-创建草稿", draft.success === true && draft.data?.id, draft.message || `id=${draft.data?.id}`);
- const filingId = draft.data?.id;
- if (!filingId) {
- return null;
- }
-
- const initTpl = await request("POST", `/qual-filing-material/init-template?filingId=${filingId}`);
- assert("备案申请-初始化材料模板", initTpl.success === true, initTpl.message);
-
- const detail1 = await request("GET", `/qual-filing/detail?id=${filingId}`);
- assert("备案申请-详情含10项材料", detail1.data?.materials?.length === 10, `count=${detail1.data?.materials?.length}`);
-
- // 2. 暂存基本信息
- const saved = await request("POST", "/qual-filing/save-draft", {
- id: filingId,
- filingUnitName: "脚本联调评价机构",
- filingTerritoryName: "渝北区",
- filingTerritoryCode: "渝北区",
- businessScope: "化工",
- });
- assert("备案申请-暂存基本信息", saved.success === true, saved.message);
-
- // 3. 备案申请分页(applyTypeCode=1)
- const appPage = await request("GET", `/qual-filing/page?current=1&size=20&applyTypeCode=1`);
- const appTypes = new Set((appPage.data || []).map((row) => row.applyTypeCode));
- assert(
- "备案申请-分页仅 applyType=1",
- appPage.success === true && appTypes.size <= 1 && (appTypes.size === 0 || appTypes.has(1)),
- `types=${[...appTypes].join(",")} total=${appPage.total}`,
- );
-
- // 4. 上传材料 + 承诺书 + 提交
- const uploadRes = await uploadAllMaterials(filingId);
- assert("备案申请-上传全部材料", uploadRes.ok === true, uploadRes.message || `count=${uploadRes.count}`);
-
- const commitment = await saveCommitment(filingId);
- assert("备案申请-保存承诺书", commitment.success === true, commitment.message);
-
- const submit = await request("POST", `/qual-filing/submit?id=${filingId}`);
- assert(
- "备案申请-提交审核",
- submit.success === true && submit.data?.filingStatusCode === 2,
- submit.message || submit.data?.filingStatusName,
- );
-
- // 5. 审核通过 → 生成已备案记录
- const approve = await request("POST", `/qual-filing/approve?id=${filingId}`);
- assert(
- "备案申请-审核通过",
- approve.success === true && approve.data?.filingStatusCode === 1 && approve.data?.filingStatusName === "已备案",
- approve.message || approve.data?.filingStatusName,
- );
-
- const filedPage = await request("GET", "/qual-filing/filed/page?current=1&size=20");
- const filedTypes = new Set((filedPage.data || []).map((row) => row.applyTypeCode));
- const filedStatuses = new Set((filedPage.data || []).map((row) => row.filingStatusCode));
- assert(
- "已备案-分页仅 applyType=3",
- filedPage.success === true && [...filedTypes].every((t) => t === 3),
- `types=${[...filedTypes].join(",")} count=${filedPage.data?.length}`,
- );
- assert(
- "已备案-默认不含暂存",
- ![...filedStatuses].includes(5),
- `statuses=${[...filedStatuses].join(",")}`,
- );
-
- const originFilingId = filedPage.data?.[0]?.id;
- assert("已备案-存在记录", !!originFilingId, `originId=${originFilingId}`);
-
- // 6. 已备案填报草稿
- const filedDraft = await request("POST", "/qual-filing/filed/draft");
- assert("已备案-创建填报草稿", filedDraft.success === true && filedDraft.data?.id, filedDraft.message);
- assert(
- "已备案-填报草稿为暂存",
- filedDraft.data?.filingStatusCode === 5,
- filedDraft.data?.filingStatusName,
- );
-
- const changePage = await request("GET", "/qual-filing/change/page?current=1&size=20");
- const changeStatuses = new Set((changePage.data || []).map((row) => row.filingStatusCode));
- assert(
- "备案变更-列表仅已备案/变更审核中",
- changePage.success === true && [...changeStatuses].every((s) => s === 1 || s === 4),
- `statuses=${[...changeStatuses].join(",")}`,
- );
-
- if (!originFilingId) {
- return filingId;
- }
-
- // 7. 备案变更
- const changeStart = await request("POST", `/qual-filing-change/start?originFilingId=${originFilingId}`);
- const draftFilingId = changeStart.data;
- assert("备案变更-发起变更", changeStart.success === true && draftFilingId, `draftId=${draftFilingId}`);
-
- if (draftFilingId) {
- await request("POST", "/qual-filing/save-draft", {
- id: draftFilingId,
- businessScope: "化工, 矿山",
- });
- await uploadAllMaterials(draftFilingId);
- await saveCommitment(draftFilingId);
-
- const changeSubmit = await request("POST", "/qual-filing-change/submit", { draftFilingId });
- assert("备案变更-提交", changeSubmit.success === true, changeSubmit.message);
-
- const history = await request("GET", `/qual-filing-change/history?originFilingId=${originFilingId}`);
- assert(
- "备案变更-历史明细",
- history.success === true && (history.data?.changeCount ?? 0) >= 1,
- `changeCount=${history.data?.changeCount} records=${history.data?.records?.length}`,
- );
- }
-
- // 8. 人员/装备批量引入(有数据则测)
- const personnelPage = await request("GET", "/org-personnel/page?current=1&size=1");
- const personnelId = personnelPage.data?.[0]?.id;
- if (personnelId) {
- const newDraft = await request("POST", "/qual-filing/draft?applyTypeCode=1");
- const pid = newDraft.data?.id;
- const batchP = await request("POST", "/qual-filing-personnel/batch-add-from-org", {
- filingId: pid,
- sourcePersonnelIds: [personnelId],
- });
- assert("备案人员-批量引入", batchP.success === true, batchP.message);
- }
- else {
- assert("备案人员-批量引入", true, "跳过:无企业人员数据");
- }
-
- const equipPage = await request("GET", "/org-equipment/page?current=1&size=1");
- const equipId = equipPage.data?.[0]?.id;
- if (equipId) {
- const newDraft2 = await request("POST", "/qual-filing/draft?applyTypeCode=1");
- const eid = newDraft2.data?.id;
- const batchE = await request("POST", "/qual-filing-equipment/batch-add-from-org", {
- filingId: eid,
- sourceEquipmentIds: [equipId],
- });
- assert("备案装备-批量引入", batchE.success === true, batchE.message);
- }
- else {
- assert("备案装备-批量引入", true, "跳过:无企业装备数据");
- }
-
- return filingId;
-}
-
-async function runFrontendSmokeTests() {
- console.log("\n=== 前端页面可访问性 ===");
- console.log(`FRONTEND_BASE=${FRONTEND_BASE}\n`);
-
- const pages = [
- ["/certificate/container/qualApplication/filingApplication/list", "资质备案申请列表"],
- ["/certificate/container/qualApplication/filedManage/list", "已备案资质管理列表"],
- ["/certificate/container/qualApplication/filingChange/list", "备案变更管理列表"],
- ];
-
- for (const [path, label] of pages) {
- try {
- const res = await fetch(`${FRONTEND_BASE}${path}`, { method: "GET" });
- assert(`前端-${label}`, res.status === 200, `HTTP ${res.status}`);
- }
- catch (err) {
- assert(`前端-${label}`, false, err.message);
- }
- }
-}
-
-async function main() {
- console.log("资质申请管理 — 联调冒烟测试");
- try {
- await runBackendTests();
- }
- catch (err) {
- failed += 1;
- console.error("\n后端测试异常:", err);
- }
-
- try {
- await runFrontendSmokeTests();
- }
- catch (err) {
- console.warn("\n前端页面检测跳过:", err.message);
- }
-
- console.log(`\n=== 结果: ${passed} 通过, ${failed} 失败 ===\n`);
- if (failed > 0) {
- process.exit(1);
- }
-}
-
-main();
diff --git a/docs/test-reports/测试用例/test-qual-filing-audit-flow.mjs b/docs/test-reports/测试用例/test-qual-filing-audit-flow.mjs
deleted file mode 100644
index 0be789d..0000000
--- a/docs/test-reports/测试用例/test-qual-filing-audit-flow.mjs
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * 资质申请管理 — 三模块审核接口 + 整体流程联调
- *
- * 运行:
- * API_BASE=http://127.0.0.1:8095/safetyEval ORG_INFO_ID=1 node docs/test-reports/测试用例/test-qual-filing-audit-flow.mjs
- */
-const API_BASE = process.env.API_BASE || "http://127.0.0.1:8095/safetyEval";
-const ORG_INFO_ID = process.env.ORG_INFO_ID || "1";
-const DEFAULT_URL =
- "https://s1.aigei.com/prevfiles/6f2754563be2491bad7c957904cd7d2a.jpg?e=2051020800&token=P7S2Xpzfz11vAkASLTkfHN7Fw-oOZBecqeJaxypL:CR60zg7VKDp-jUWyYls_rdvyQMM=";
-
-let passed = 0;
-let failed = 0;
-
-function ok(name, cond, detail = "") {
- if (cond) {
- passed += 1;
- console.log(` ✓ ${name}${detail ? ` — ${detail}` : ""}`);
- }
- else {
- failed += 1;
- console.log(` ✗ ${name}${detail ? ` — ${detail}` : ""}`);
- }
-}
-
-async function api(method, path, body) {
- const res = await fetch(`${API_BASE}${path}`, {
- method,
- headers: { "Content-Type": "application/json", orgInfoId: ORG_INFO_ID },
- body: body !== undefined ? JSON.stringify(body) : undefined,
- });
- const text = await res.text();
- try {
- return { httpStatus: res.status, ...JSON.parse(text) };
- }
- catch {
- return { httpStatus: res.status, success: false, raw: text };
- }
-}
-
-async function uploadAllMaterials(filingId) {
- const detail = await api("GET", `/qual-filing/detail?id=${filingId}`);
- for (const m of detail.data?.materials || []) {
- if (!m.attachmentUrl) {
- await api("POST", "/qual-filing-material/upload", { id: m.id, attachmentUrl: DEFAULT_URL });
- }
- }
-}
-
-async function saveCommitment(filingId) {
- return api("POST", "/qual-filing-commitment/save-or-update", {
- filingId,
- signDate: "2026-06-30",
- legalRepSignatureUrl: DEFAULT_URL,
- commitmentContent: "审核流程联调测试承诺书",
- });
-}
-
-async function persistMinimal(filingId) {
- await api("POST", "/qual-filing/save-draft", {
- id: filingId,
- filingUnitName: "审核流程测试机构",
- filingTerritoryName: "渝北区",
- businessScope: "化工",
- });
- await api("POST", `/qual-filing-material/init-template?filingId=${filingId}`);
- await uploadAllMaterials(filingId);
- await saveCommitment(filingId);
-}
-
-async function testModule1ApplicationAudit() {
- console.log("\n=== 模块1:资质备案申请(提交 + 审核) ===");
-
- const draft = await api("POST", "/qual-filing/draft?applyTypeCode=1");
- const filingId = draft.data?.id;
- ok("1.创建申请草稿", draft.success && filingId, `id=${filingId}`);
- if (!filingId) {
- return null;
- }
-
- await persistMinimal(filingId);
-
- const submit = await api("POST", `/qual-filing/submit?id=${filingId}`);
- ok("2.提交审核 POST /qual-filing/submit", submit.success && submit.data?.filingStatusCode === 2, submit.data?.filingStatusName);
-
- const approve = await api("POST", `/qual-filing/approve?id=${filingId}`);
- ok(
- "3.审核通过 POST /qual-filing/approve",
- approve.success && approve.data?.filingStatusCode === 1,
- approve.data?.filingStatusName,
- );
-
- const filedPage = await api("GET", "/qual-filing/filed/page?current=1&size=5");
- const master = (filedPage.data || []).find((r) => r.filingStatusCode === 1);
- ok("4.审核后生成已备案主记录", !!master, master ? `masterId=${master.id}` : "filed/page 无已备案");
-
- return { applicationId: filingId, masterId: master?.id };
-}
-
-async function testModule2FiledManageAudit(masterId) {
- console.log("\n=== 模块2:已备案资质管理(填报提交 + 审核) ===");
- if (!masterId) {
- ok("跳过-无已备案主记录", false);
- return masterId;
- }
-
- const filedDraft = await api("POST", "/qual-filing/filed/draft");
- const draftId = filedDraft.data?.id;
- ok("1.创建填报草稿 POST /qual-filing/filed/draft", filedDraft.success && draftId, `id=${draftId}`);
- if (!draftId) {
- return masterId;
- }
-
- await persistMinimal(draftId);
-
- const submit = await api("POST", `/qual-filing/submit?id=${draftId}`);
- ok("2.提交填报审核 POST /qual-filing/submit", submit.success && submit.data?.filingStatusCode === 2, submit.data?.filingStatusName);
-
- const approve = await api("POST", `/qual-filing/approve?id=${draftId}`);
- ok(
- "3.填报审核通过 POST /qual-filing/approve",
- approve.success && approve.data?.filingStatusCode === 1,
- approve.data?.filingStatusName,
- );
-
- return masterId;
-}
-
-async function testModule3ChangeAudit(originId) {
- console.log("\n=== 模块3:备案变更管理(变更提交 + 审核) ===");
- if (!originId) {
- ok("跳过-无变更源记录", false);
- return;
- }
-
- const originBefore = await api("GET", `/qual-filing/get?id=${originId}`);
- ok("1.变更源为已备案", originBefore.data?.filingStatusCode === 1, originBefore.data?.filingStatusName);
-
- const start = await api("POST", `/qual-filing-change/start?originFilingId=${originId}`);
- const changeDraftId = start.data;
- ok("2.发起变更 POST /qual-filing-change/start", start.success && changeDraftId, `draftId=${changeDraftId}`);
- if (!changeDraftId) {
- return;
- }
-
- await api("POST", "/qual-filing/save-draft", {
- id: changeDraftId,
- businessScope: "化工, 矿山采选业",
- unitIntro: "变更后业务范围说明",
- });
- await uploadAllMaterials(changeDraftId);
- await saveCommitment(changeDraftId);
-
- const changeSubmit = await api("POST", "/qual-filing-change/submit", { draftFilingId: changeDraftId });
- ok("3.提交变更审核 POST /qual-filing-change/submit", changeSubmit.success === true, changeSubmit.message);
-
- const changePage = await api(
- "GET",
- `/qual-filing-change/page?current=1&size=5&originFilingId=${originId}&filingStatusCode=2`,
- );
- const pendingChange = (changePage.data || [])[0];
- const changeId = pendingChange?.id;
- ok("4.查询待审变更单 GET /qual-filing-change/page", !!changeId, `changeId=${changeId}`);
-
- if (!changeId) {
- return;
- }
-
- const changeApprove = await api("POST", `/qual-filing-change/approve?changeId=${changeId}`);
- ok("5.变更审核通过 POST /qual-filing-change/approve", changeApprove.success === true, changeApprove.message);
-
- const originAfter = await api("GET", `/qual-filing/get?id=${originId}`);
- ok(
- "6.变更通过后主记录恢复已备案",
- originAfter.data?.filingStatusCode === 1,
- originAfter.data?.filingStatusName,
- );
- ok(
- "7.变更内容已生效",
- (originAfter.data?.businessScope || "").includes("矿山"),
- originAfter.data?.businessScope,
- );
-}
-
-async function main() {
- console.log("资质申请管理 — 三模块审核接口整体流程测试");
- console.log(`API_BASE=${API_BASE} orgInfoId=${ORG_INFO_ID}`);
-
- const ctx = await testModule1ApplicationAudit();
- const masterId = await testModule2FiledManageAudit(ctx?.masterId);
- await testModule3ChangeAudit(masterId);
-
- console.log(`\n=== 结果: ${passed} 通过, ${failed} 失败 ===`);
- if (failed > 0) {
- process.exitCode = 1;
- }
-}
-
-await main();
diff --git a/docs/test-reports/测试用例/test-qual-filing-full-e2e.mjs b/docs/test-reports/测试用例/test-qual-filing-full-e2e.mjs
deleted file mode 100644
index 8b90bd6..0000000
--- a/docs/test-reports/测试用例/test-qual-filing-full-e2e.mjs
+++ /dev/null
@@ -1,410 +0,0 @@
-/**
- * 资质申请管理 — 三模块完整流程联调(模拟前端 persist 链路)
- *
- * 运行: node docs/test-reports/测试用例/test-qual-filing-full-e2e.mjs
- */
-import path from "node:path";
-import { fileURLToPath } from "node:url";
-
-const __dirname = path.dirname(fileURLToPath(import.meta.url));
-const ROOT = path.resolve(__dirname, "../../..");
-
-const API_BASE = process.env.API_BASE || "http://127.0.0.1:8095/safetyEval";
-const ORG_INFO_ID = process.env.ORG_INFO_ID || "1";
-const DEFAULT_URL =
- "https://s1.aigei.com/prevfiles/6f2754563be2491bad7c957904cd7d2a.jpg?e=2051020800&token=P7S2Xpzfz11vAkASLTkfHN7Fw-oOZBecqeJaxypL:CR60zg7VKDp-jUWyYls_rdvyQMM=";
-
-const issues = [];
-let passed = 0;
-let failed = 0;
-const ctx = {};
-
-function log(step, msg) {
- console.log(`[${step}] ${msg}`);
-}
-
-function pass(name, detail = "") {
- passed += 1;
- console.log(` ✓ ${name}${detail ? ` — ${detail}` : ""}`);
-}
-
-function fail(name, detail = "") {
- failed += 1;
- console.log(` ✗ ${name}${detail ? ` — ${detail}` : ""}`);
-}
-
-function recordIssue(module, severity, title, detail) {
- issues.push({ module, severity, title, detail });
-}
-
-async function api(method, apiPath, body) {
- const res = await fetch(`${API_BASE}${apiPath}`, {
- method,
- headers: { "Content-Type": "application/json", orgInfoId: ORG_INFO_ID },
- body: body !== undefined ? JSON.stringify(body) : undefined,
- });
- const text = await res.text();
- try {
- return { httpStatus: res.status, ...JSON.parse(text) };
- }
- catch {
- return { httpStatus: res.status, success: false, raw: text };
- }
-}
-
-async function uploadAllMaterials(filingId) {
- const detail = await api("GET", `/qual-filing/detail?id=${filingId}`);
- for (const m of detail.data?.materials || []) {
- if (!m.attachmentUrl) {
- await api("POST", "/qual-filing-material/upload", { id: m.id, attachmentUrl: DEFAULT_URL });
- }
- }
-}
-
-const FORMAL_BASIC = {
- filingTerritoryName: "渝北区",
- filingTerritoryCode: "渝北区",
- filingUnitName: "重庆渝安安全评价技术有限公司",
- filingUnitTypeCode: "本地单位",
- filingUnitTypeName: "本地单位",
- businessScope: "石油加工业,化学原料、化学品及医药制造业",
- registerAddress: "重庆市渝北区黄山大道中段88号",
- officeAddress: "重庆市渝北区黄山大道中段88号安全评价大厦12层",
- creditCode: "91500000MA5U8K9X2L",
- qualCertNo: "AQPJ-渝-2024-0018",
- legalPersonPhone: "王建国 / 023-67891234",
- contactPhone: "陈晓明 / 13912345678",
- infoDisclosureUrl: "https://www.yuan-an-safety.com/disclosure",
- fixedAssetAmount: 1580,
- workplaceArea: 1860,
- archiveRoomArea: 120,
- fulltimeEvaluatorCount: 32,
- registeredEngineerCount: 12,
- unitIntro: "本公司成立于2018年,主要从事安全评价、安全技术服务,具备独立法人资格。",
- attachmentUrl: DEFAULT_URL,
-};
-
-async function persistLikeFrontend(filingId, mode = "application") {
- const saveRes = await api("POST", "/qual-filing/save-draft", { id: filingId, ...FORMAL_BASIC });
- if (!saveRes.success) {
- throw new Error(saveRes.message || "save-draft failed");
- }
-
- await api("POST", `/qual-filing-material/init-template?filingId=${filingId}`);
- await uploadAllMaterials(filingId);
-
- const commitmentContent =
- "本人是王建国是重庆渝安安全评价技术有限公司法定代表人,现代表我单位承诺如下:本单位提交的资质备案申请材料真实、准确、完整。";
- await api("POST", "/qual-filing-commitment/save-or-update", {
- filingId,
- signDate: "2026-06-30",
- legalRepSignatureUrl: DEFAULT_URL,
- commitmentContent,
- });
-
- const personnelPage = await api("GET", "/org-personnel/page?current=1&size=20");
- const personnelIds = (personnelPage.data || []).map((p) => p.id).filter(Boolean);
- if (personnelIds.length) {
- await api("POST", "/qual-filing-personnel/batch-add-from-org", {
- filingId,
- sourcePersonnelIds: personnelIds,
- });
- }
-
- const equipPage = await api("GET", "/org-equipment/page?current=1&size=20");
- const equipIds = (equipPage.data || []).map((e) => e.id).filter(Boolean);
- if (equipIds.length) {
- await api("POST", "/qual-filing-equipment/batch-add-from-org", {
- filingId,
- sourceEquipmentIds: equipIds,
- });
- }
-
- return api("GET", `/qual-filing/detail?id=${filingId}`);
-}
-
-// ── 模块1:资质备案申请 ──
-async function testModule1Application() {
- console.log("\n=== 模块1:资质备案申请 ===");
-
- const existingPage = await api("GET", "/qual-filing/page?current=1&size=5&applyTypeCode=1&filingStatusCode=5");
- let filingId = existingPage.data?.[0]?.id;
-
- if (filingId) {
- pass("复用已有暂存记录", `id=${filingId}`);
- }
- else {
- const draft = await api("POST", "/qual-filing/draft?applyTypeCode=1");
- filingId = draft.data?.id;
- if (draft.success && filingId) {
- pass("新建申请草稿", `id=${filingId}`);
- }
- else {
- fail("新建申请草稿", draft.message);
- return;
- }
- }
-
- ctx.applicationId = filingId;
-
- const detailRes = await persistLikeFrontend(filingId);
- const detail = detailRes.data || {};
- pass("暂存-基本信息", detail.filingUnitName);
- pass("暂存-材料10项已上传", (detail.materials || []).every((m) => m.uploadStatusCode === 2));
- pass("暂存-承诺书", !!detail.commitment?.commitmentContent);
- pass("暂存-人员", `count=${(detail.personnelList || []).length}`);
- pass("暂存-装备", `count=${(detail.equipmentList || []).length}`);
-
- const listRes = await api("GET", "/qual-filing/page?current=1&size=20&applyTypeCode=1");
- const inList = (listRes.data || []).some((r) => String(r.id) === String(filingId));
- if (inList && detail.filingStatusCode === 5) {
- pass("列表-暂存记录可见", detail.filingStatusName);
- }
- else {
- fail("列表-暂存记录可见", `status=${detail.filingStatusCode}`);
- }
-
- const reload = await api("GET", `/qual-filing/detail?id=${filingId}`);
- if (reload.data?.businessScope?.includes("化学")) {
- pass("回显-修改后业务范围");
- }
- else {
- fail("回显-修改后业务范围");
- }
-
- const verifyMod = await import(path.join(ROOT, "src/pages/Container/QualApplication/filingVerify.js"));
- const verifyResult = verifyMod.verifyFilingPrerequisites({
- ...FORMAL_BASIC,
- materials: reload.data?.materials || [],
- personnelList: reload.data?.personnelList || [],
- equipmentList: reload.data?.equipmentList || [],
- });
- if (!verifyResult.passed) {
- const failedItems = verifyResult.items.filter((i) => !i.passed).map((i) => i.label);
- recordIssue(
- "资质备案申请",
- "阻塞",
- "前端提交核验:人员数量/结构未通过",
- `当前机构人员 ${(reload.data?.personnelList || []).length} 人,核验失败项:${failedItems.join("、")}。用户要求测试阶段暂不判断此项,但前端「提交申请」确认按钮仍被禁用。`,
- );
- pass("前端核验-预期失败(人员不足)", failedItems.join(","));
- }
- else {
- pass("前端核验-全部通过");
- }
-
- const submit = await api("POST", `/qual-filing/submit?id=${filingId}`);
- if (submit.success && submit.data?.filingStatusCode === 2) {
- pass("后端提交-进入审核中", submit.data.filingStatusName);
- }
- else {
- fail("后端提交", submit.message);
- recordIssue("资质备案申请", "阻塞", "后端提交失败", submit.message || JSON.stringify(submit));
- return;
- }
-
- const approve = await api("POST", `/qual-filing/approve?id=${filingId}`);
- if (approve.success && approve.data?.filingStatusCode === 1) {
- pass("审核通过-已备案", approve.data.filingStatusName);
- ctx.approvedApplicationId = filingId;
- }
- else {
- fail("审核通过", approve.message || approve.data?.filingStatusName);
- }
-}
-
-// ── 模块2:已备案资质管理 ──
-async function testModule2FiledManage() {
- console.log("\n=== 模块2:已备案资质管理 ===");
-
- const filedPage = await api("GET", "/qual-filing/filed/page?current=1&size=20");
- const filedList = filedPage.data || [];
- if (filedList.length > 0) {
- pass("已备案列表有数据", `count=${filedList.length}`);
- ctx.originFiledId = filedList[0].id;
- }
- else {
- fail("已备案列表有数据", "审核通过后应出现 applyType=3 记录");
- recordIssue("已备案资质管理", "阻塞", "审核通过后已备案列表为空", "需确认 approve 是否创建 filed 记录");
- return;
- }
-
- const origin = filedList[0];
- if (origin.applyTypeCode === 3) {
- pass("已备案记录类型", origin.applyTypeName);
- }
- else {
- fail("已备案记录类型", `applyTypeCode=${origin.applyTypeCode}`);
- }
-
- const filedDraft = await api("POST", "/qual-filing/filed/draft");
- const filedDraftId = filedDraft.data?.id;
- if (!filedDraft.success || !filedDraftId) {
- fail("资质备案填报-创建草稿", filedDraft.message);
- return;
- }
- pass("资质备案填报-创建草稿", `id=${filedDraftId}`);
- ctx.filedDraftId = filedDraftId;
-
- const saveRes = await persistLikeFrontend(filedDraftId);
- const detail = saveRes.data || {};
- if (detail.filingStatusCode === 5 && detail.applyTypeCode === 3) {
- pass("填报暂存", `${detail.filingStatusName} applyType=${detail.applyTypeCode}`);
- }
- else {
- fail("填报暂存", `status=${detail.filingStatusCode} type=${detail.applyTypeCode}`);
- }
-
- const filedPageDefault = await api("GET", "/qual-filing/filed/page?current=1&size=20");
- const draftInDefaultList = (filedPageDefault.data || []).some((r) => String(r.id) === String(filedDraftId));
- if (!draftInDefaultList) {
- pass("已备案列表-默认不含填报暂存");
- }
- else {
- fail("已备案列表-默认不含填报暂存");
- recordIssue("已备案资质管理", "一般", "填报暂存不应出现在默认已备案列表", `draftId=${filedDraftId}`);
- }
-
- const filedPageDraftFilter = await api("GET", "/qual-filing/filed/page?current=1&size=20&filingStatusCode=5");
- const draftInFilteredList = (filedPageDraftFilter.data || []).some((r) => String(r.id) === String(filedDraftId));
- if (draftInFilteredList) {
- pass("已备案列表-显式筛选暂存可见");
- }
- else {
- fail("已备案列表-显式筛选暂存可见", `draftId=${filedDraftId}`);
- }
-}
-
-// ── 模块3:备案变更管理 ──
-async function testModule3FilingChange() {
- console.log("\n=== 模块3:备案变更管理 ===");
-
- const originId = ctx.originFiledId;
- if (!originId) {
- fail("发起变更", "无已备案 origin 记录");
- return;
- }
-
- const changePage = await api("GET", "/qual-filing/change/page?current=1&size=20");
- const changeList = changePage.data || [];
- if (changeList.length > 0) {
- pass("变更列表有数据", `count=${changeList.length}`);
- }
- else {
- fail("变更列表有数据", "应有已备案记录");
- }
-
- const origin = changeList.find((r) => String(r.id) === String(originId)) || changeList[0];
- if (!origin) {
- fail("变更源记录", "未找到");
- return;
- }
-
- if (origin.filingStatusCode === 4) {
- recordIssue("备案变更管理", "阻塞", "已备案记录处于变更审核中", "无法再次发起变更");
- fail("可发起变更", "状态=变更审核中");
- return;
- }
- pass("可发起变更", origin.filingStatusName);
-
- const start = await api("POST", `/qual-filing-change/start?originFilingId=${originId}`);
- const draftId = start.data?.draftFilingId || start.data;
- if (!start.success || !draftId) {
- fail("发起变更", start.message);
- return;
- }
- pass("发起变更", `draftId=${draftId}`);
- ctx.changeDraftId = draftId;
-
- const changeBasic = {
- ...FORMAL_BASIC,
- businessScope: "石油加工业,化学原料、化学品及医药制造业;金属、非金属矿及其他矿采选业",
- unitIntro: "变更后:新增矿山采选业安全评价业务范围。",
- };
- await api("POST", "/qual-filing/save-draft", { id: draftId, ...changeBasic });
- await uploadAllMaterials(draftId);
- await api("POST", "/qual-filing-commitment/save-or-update", {
- filingId: draftId,
- signDate: "2026-06-30",
- legalRepSignatureUrl: DEFAULT_URL,
- commitmentContent: "变更备案承诺书",
- });
-
- const changeDetail = await api("GET", `/qual-filing/detail?id=${draftId}`);
- if (changeDetail.data?.businessScope?.includes("矿采选业")) {
- pass("变更草稿-业务范围已修改");
- }
- else {
- fail("变更草稿-业务范围已修改", changeDetail.data?.businessScope);
- }
-
- const changeSubmit = await api("POST", "/qual-filing-change/submit", { draftFilingId: draftId });
- if (changeSubmit.success) {
- pass("提交变更", "success");
- }
- else {
- fail("提交变更", changeSubmit.message);
- recordIssue("备案变更管理", "阻塞", "变更提交失败", changeSubmit.message);
- return;
- }
-
- const history = await api("GET", `/qual-filing-change/history?originFilingId=${originId}`);
- const changeCount = history.data?.changeCount ?? 0;
- if (history.success && changeCount > 0) {
- pass("变更历史", `changeCount=${changeCount}`);
- }
- else {
- fail("变更历史", `count=${changeCount}`);
- }
-
- const changeAfter = await api("GET", "/qual-filing/change/page?current=1&size=20");
- const updated = (changeAfter.data || []).find((r) => String(r.id) === String(originId));
- if (updated?.changeCount > 0) {
- pass("变更列表-变更次数更新", `${updated.filingStatusName} count=${updated.changeCount}`);
- }
- else {
- fail("变更列表-变更次数更新");
- recordIssue("备案变更管理", "一般", "变更列表变更次数未更新", `originId=${originId}`);
- }
-}
-
-async function checkDataQuality() {
- console.log("\n=== 数据质量检查 ===");
- const personnelPage = await api("GET", "/org-personnel/page?current=1&size=10");
- const missingName = (personnelPage.data || []).filter((p) => !p.personName && !p.staffName);
- if (missingName.length) {
- recordIssue(
- "通用",
- "一般",
- "机构人员主数据姓名为空",
- `${missingName.length} 条人员记录 personName/staffName 为空,表单人员列表可能显示空白。`,
- );
- pass("人员主数据-姓名缺失(已知)", `count=${missingName.length}`);
- }
-}
-
-async function main() {
- console.log("资质申请管理 — 三模块完整流程联调");
- console.log(`API=${API_BASE} orgInfoId=${ORG_INFO_ID}\n`);
-
- await checkDataQuality();
- await testModule1Application();
- await testModule2FiledManage();
- await testModule3FilingChange();
-
- console.log(`\n=== 结果: ${passed} 通过, ${failed} 失败 ===`);
- console.log(`=== 问题记录: ${issues.length} 条 ===\n`);
- for (const [i, issue] of issues.entries()) {
- console.log(`${i + 1}. [${issue.module}] [${issue.severity}] ${issue.title}`);
- console.log(` ${issue.detail}\n`);
- }
-
- return { passed, failed, issues, ctx };
-}
-
-const result = await main();
-if (result.failed > 0) {
- process.exitCode = 1;
-}
-
-export default result;
diff --git a/docs/test-reports/测试用例/test-qual-filing-interaction.mjs b/docs/test-reports/测试用例/test-qual-filing-interaction.mjs
deleted file mode 100644
index 1c23be3..0000000
--- a/docs/test-reports/测试用例/test-qual-filing-interaction.mjs
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- * 资质申请管理 — 页面交互逻辑 + 后端联调全链路测试
- *
- * 覆盖本次改造:
- * - 新建申请不预调 draft(列表 API 计数不变)
- * - 暂存后入库并可回显
- * - 材料前端模板 + 暂存时 init-template
- * - 提交前核验(全通过/有失败)
- * - 前端路由 bundle 检测
- *
- * 运行:
- * node docs/test-reports/测试用例/test-qual-filing-interaction.mjs
- */
-import fs from "node:fs";
-import path from "node:path";
-import { fileURLToPath } from "node:url";
-
-const __dirname = path.dirname(fileURLToPath(import.meta.url));
-const ROOT = path.resolve(__dirname, "../../..");
-
-const API_BASE = process.env.API_BASE || "http://127.0.0.1:8095/safetyEval";
-const ORG_INFO_ID = process.env.ORG_INFO_ID || "1";
-const FRONTEND_BASE = process.env.FRONTEND_BASE || "http://127.0.0.1:8081";
-const DEFAULT_URL =
- "https://s1.aigei.com/prevfiles/6f2754563be2491bad7c957904cd7d2a.jpg?e=2051020800&token=P7S2Xpzfz11vAkASLTkfHN7Fw-oOZBecqeJaxypL:CR60zg7VKDp-jUWyYls_rdvyQMM=";
-
-let passed = 0;
-let failed = 0;
-
-function assert(name, condition, detail = "") {
- if (condition) {
- passed += 1;
- console.log(` ✓ ${name}${detail ? ` — ${detail}` : ""}`);
- }
- else {
- failed += 1;
- console.log(` ✗ ${name}${detail ? ` — ${detail}` : ""}`);
- }
-}
-
-async function api(method, path, body) {
- const res = await fetch(`${API_BASE}${path}`, {
- method,
- headers: { "Content-Type": "application/json", orgInfoId: ORG_INFO_ID },
- body: body !== undefined ? JSON.stringify(body) : undefined,
- });
- const text = await res.text();
- try {
- return { httpStatus: res.status, ...JSON.parse(text) };
- }
- catch {
- return { httpStatus: res.status, success: false, raw: text };
- }
-}
-
-function readSrc(rel) {
- return fs.readFileSync(path.join(ROOT, rel), "utf8");
-}
-
-// ── 静态:新建不预调后端 ──
-function testStaticNoPreCreate() {
- console.log("\n=== 静态检查:新建不预调后端 ===");
- const listPage = readSrc("src/pages/Container/QualApplication/FilingApplication/List/index.js");
- assert("列表-申请备案不调 qualFilingDraft", !listPage.includes("qualFilingDraft"));
- assert("列表-申请备案不调 init-template", !listPage.includes("qualFilingMaterialInitTemplate"));
- assert("列表-直接跳转表单", listPage.includes("goFilingForm({ mode: FILING_FORM_MODE.APPLICATION })"));
-
- const formPage = readSrc("src/pages/Container/QualApplication/FilingForm/index.js");
- assert("表单-存在 persistFilingToBackend", formPage.includes("persistFilingToBackend"));
- assert("表单-存在核验弹窗", formPage.includes("PrerequisiteVerifyModal"));
- assert("表单-存在 session 本地草稿", formPage.includes("saveLocalDraft"));
- assert("表单-材料本地更新", formPage.includes("uploadStatusName: \"已上传\""));
-
- const basicStep = readSrc("src/pages/Container/QualApplication/FilingForm/components/BasicInfoStep.jsx");
- assert("基本信息-证照类型选项", basicStep.includes("QUALIFICATION_INDUSTRY_OPTIONS"));
-
- const commitment = readSrc("src/pages/Container/QualApplication/FilingForm/components/CommitmentStep.jsx");
- assert("承诺书-法定代表人下拉", commitment.includes("legalRepPersonnelId"));
- assert("承诺书-动态填充文本", commitment.includes("COMMITMENT_PARAGRAPHS"));
-
- assert("材料模板-10项", readSrc("src/pages/Container/QualApplication/filingMaterialTemplate.js").includes("sortOrder: 10"));
-}
-
-// ── 核验逻辑 ──
-async function testVerifyLogic() {
- console.log("\n=== 核验逻辑 ===");
- const verifyMod = await import(path.join(ROOT, "src/pages/Container/QualApplication/filingVerify.js"));
- const { verifyFilingPrerequisites } = verifyMod;
-
- const failDetail = {
- fixedAssetAmount: 500,
- workplaceArea: 500,
- personnelList: [],
- equipmentList: [],
- materials: [{ sortOrder: 10, attachmentUrl: null }],
- };
- const failResult = verifyFilingPrerequisites(failDetail);
- assert("核验-不完整时应失败", failResult.passed === false, `items=${failResult.items.length}`);
-
- const passDetail = {
- fixedAssetAmount: 1200,
- workplaceArea: 1200,
- equipmentList: [{ id: 1 }],
- materials: [{ sortOrder: 10, attachmentUrl: DEFAULT_URL }],
- personnelList: Array.from({ length: 25 }, (_, i) => ({
- personName: `P${i}`,
- registerEngineerFlag: i < 8 ? 1 : 0,
- titleName: i < 8 ? "高级" : "中级",
- positionName: i === 0 ? "负责人" : i === 1 ? "技术负责人" : i === 2 ? "质量负责人" : "工程师",
- workExperience: "在本行业工作五年",
- })),
- };
- const passResult = verifyFilingPrerequisites(passDetail);
- assert("核验-完整数据应通过", passResult.passed === true);
-}
-
-// ── 模拟前端 persist 全链路 ──
-async function testPersistFlow() {
- console.log("\n=== 交互链路:暂存入库 + 回显 ===");
-
- const beforePage = await api("GET", "/qual-filing/page?current=1&size=1&applyTypeCode=1");
- const beforeTotal = beforePage.total ?? 0;
-
- // 模拟用户填写后点暂存(等同 persistFilingToBackend)
- const draft = await api("POST", "/qual-filing/draft?applyTypeCode=1");
- assert("暂存-创建草稿", draft.success === true && draft.data?.id, `id=${draft.data?.id}`);
- const filingId = draft.data?.id;
- if (!filingId) {
- return;
- }
-
- const saveBasic = await api("POST", "/qual-filing/save-draft", {
- id: filingId,
- businessScope: "石油加工业,化学原料、化学品及医药制造业",
- filingTerritoryName: "渝北区",
- filingTerritoryCode: "渝北区",
- filingUnitName: "交互测试评价机构",
- fixedAssetAmount: 1200,
- workplaceArea: 1500,
- });
- assert("暂存-基本信息", saveBasic.success === true, saveBasic.message);
-
- await api("POST", `/qual-filing-material/init-template?filingId=${filingId}`);
- const detailAfterInit = await api("GET", `/qual-filing/detail?id=${filingId}`);
- assert("暂存-材料模板10项", detailAfterInit.data?.materials?.length === 10);
-
- for (const material of detailAfterInit.data.materials || []) {
- await api("POST", "/qual-filing-material/upload", {
- id: material.id,
- attachmentUrl: DEFAULT_URL,
- });
- }
-
- const commitmentContent = "本人是郑远平是交互测试评价机构法定代表人,现代表我单位承诺如下:";
- await api("POST", "/qual-filing-commitment/save-or-update", {
- filingId,
- signDate: "2026-06-30",
- legalRepSignatureUrl: DEFAULT_URL,
- commitmentContent,
- });
-
- const personnelPage = await api("GET", "/org-personnel/page?current=1&size=5");
- const personnelIds = (personnelPage.data || []).map((p) => p.id).filter(Boolean);
- if (personnelIds.length) {
- await api("POST", "/qual-filing-personnel/batch-add-from-org", {
- filingId,
- sourcePersonnelIds: personnelIds.slice(0, 2),
- });
- }
-
- const equipPage = await api("GET", "/org-equipment/page?current=1&size=5");
- const equipIds = (equipPage.data || []).map((e) => e.id).filter(Boolean);
- if (equipIds.length) {
- await api("POST", "/qual-filing-equipment/batch-add-from-org", {
- filingId,
- sourceEquipmentIds: equipIds.slice(0, 1),
- });
- }
-
- const reloaded = await api("GET", `/qual-filing/detail?id=${filingId}`);
- assert("回显-业务范围", reloaded.data?.businessScope?.includes("化学"), reloaded.data?.businessScope);
- assert("回显-材料已上传", (reloaded.data?.materials || []).every((m) => m.uploadStatusCode === 2));
- assert("回显-承诺书", !!reloaded.data?.commitment?.commitmentContent);
- assert("回显-人员", (reloaded.data?.personnelList || []).length >= 1 || personnelIds.length === 0);
- assert("回显-装备", (reloaded.data?.equipmentList || []).length >= 1 || equipIds.length === 0);
-
- const afterPage = await api("GET", "/qual-filing/page?current=1&size=20&applyTypeCode=1");
- assert("列表-暂存后总数增加", (afterPage.total ?? 0) >= beforeTotal + 1, `before=${beforeTotal} after=${afterPage.total}`);
-
- // 提交应进入审核中
- const submit = await api("POST", `/qual-filing/submit?id=${filingId}`);
- assert("提交-进入审核中", submit.success === true && submit.data?.filingStatusCode === 2, submit.data?.filingStatusName);
-}
-
-// ── 前端 bundle / 路由 ──
-async function testFrontendBundle() {
- console.log("\n=== 前端页面 bundle 检测 ===");
- const pages = [
- ["/certificate/container/qualApplication/filingApplication/list", "资质备案申请列表"],
- ["/certificate/container/qualApplication/filedManage/list", "已备案资质管理"],
- ["/certificate/container/qualApplication/filingChange/list", "备案变更管理"],
- ["/certificate/container/qualApplication/filingForm?mode=application", "备案表单(无id)"],
- ["/certificate/container/qualApplication/filingForm?mode=application&id=1", "备案表单(有id)"],
- ];
-
- for (const [route, label] of pages) {
- const res = await fetch(`${FRONTEND_BASE}${route}`);
- assert(`HTTP-${label}`, res.status === 200, String(res.status));
- }
-
- const html = await (await fetch(`${FRONTEND_BASE}/certificate/`)).text();
- const jsMatch = html.match(/src="(\/certificate\/static\/js\/main\.[^"]+\.js)"/);
- assert("前端-main.js 可解析", !!jsMatch);
- if (jsMatch) {
- const js = await (await fetch(`${FRONTEND_BASE}${jsMatch[1]}`)).text();
- const markers = [
- "FilingApplicationListPage",
- "qualApplication/filingApplication/list",
- "PrerequisiteVerifyModal",
- "QUALIFICATION_INDUSTRY_OPTIONS",
- "persistFilingToBackend",
- "verifyFilingPrerequisites",
- "legalRepPersonnelId",
- ];
- for (const marker of markers) {
- assert(`Bundle-${marker}`, js.includes(marker));
- }
- }
-}
-
-async function main() {
- console.log("资质申请管理 — 页面交互 + 后端全链路测试");
- console.log(`API_BASE=${API_BASE} FRONTEND=${FRONTEND_BASE} orgInfoId=${ORG_INFO_ID}`);
-
- testStaticNoPreCreate();
- await testVerifyLogic();
- await testPersistFlow();
- await testFrontendBundle();
-
- console.log(`\n=== 结果: ${passed} 通过, ${failed} 失败 ===\n`);
- if (failed > 0) {
- process.exit(1);
- }
-}
-
-main().catch((err) => {
- console.error(err);
- process.exit(1);
-});
diff --git a/src/pages/Container/EnterpriseInfo/EquipInfo/index.js b/src/pages/Container/EnterpriseInfo/EquipInfo/index.js
index 5423c37..532aed7 100644
--- a/src/pages/Container/EnterpriseInfo/EquipInfo/index.js
+++ b/src/pages/Container/EnterpriseInfo/EquipInfo/index.js
@@ -118,19 +118,29 @@ function EquipInfoPage(props) {
allowClear
/>
,
-
-
+
+ style={{ width: "100%" }}
+ >
+ 分析仪器
+ 检测仪器
+ 采样设备
+ 物理仪器
+
,
-
+ style={{ width: "100%" }}
+ >
+ 固定式
+ 便携式
+
,
-
+
@@ -380,7 +395,10 @@ function EquipFormModal({
label="设备类型"
rules={[{ required: true, message: "请选择设备类型" }]}
>
-
+
@@ -439,8 +457,12 @@ function EquipFormModal({
-
-
+
+
@@ -503,7 +525,7 @@ function EquipViewModal({ open, currentId, equipInfoGet, onCancel }) {
{info.deviceModel}
- {info.instrumentType}
+ {info.instrumentTypeName}
{info.deviceType}
@@ -521,7 +543,7 @@ function EquipViewModal({ open, currentId, equipInfoGet, onCancel }) {
{info.calibrationInitValue}
- {info.fieldCalibrationType}
+ {info.fieldCalibrationTypeName}
{DUAL_CHANNEL_MAP[info.dualChannelFlag] ?? "-"}
diff --git a/src/pages/Container/EnterpriseInfo/index.js b/src/pages/Container/EnterpriseInfo/index.js
index e113348..a5b7e60 100644
--- a/src/pages/Container/EnterpriseInfo/index.js
+++ b/src/pages/Container/EnterpriseInfo/index.js
@@ -5,21 +5,21 @@ import { Skeleton } from "antd";
/** 资质申请管理模块入口:需先有机构信息 */
function EnterpriseInfo(props) {
-
const [orgInfoId, setOrgInfoId] = useState(
sessionStorage.getItem("orgInfoId"),
);
useEffect(() => {
if (!orgInfoId) {
props.orgInfoGet().then((res) => {
- setOrgInfoId(res?.data?.id);
- sessionStorage.setItem("orgInfoId", res?.data?.id);
+ if (res?.data?.id) {
+ setOrgInfoId(res?.data?.id);
+ sessionStorage.setItem("orgInfoId", res?.data?.id);
+ }
});
}
}, []);
-
- if(props.location.pathname.includes('EnterpriseInfo/OrgInfo')){
+ if (props.location.pathname.includes("EnterpriseInfo/OrgInfo")) {
return props.children;
}
diff --git a/src/pages/Container/QualApplication/index.js b/src/pages/Container/QualApplication/index.js
index 60b848d..c465633 100644
--- a/src/pages/Container/QualApplication/index.js
+++ b/src/pages/Container/QualApplication/index.js
@@ -11,8 +11,10 @@ function QualApplication(props) {
useEffect(() => {
if (!orgInfoId) {
props.orgInfoGet().then((res) => {
- setOrgInfoId(res?.data?.id);
- sessionStorage.setItem("orgInfoId", res?.data?.id);
+ if (res?.data?.id) {
+ setOrgInfoId(res?.data?.id);
+ sessionStorage.setItem("orgInfoId", res?.data?.id);
+ }
});
}
}, []);