272 lines
11 KiB
Markdown
272 lines
11 KiB
Markdown
# 环境检测模块 — 功能设计文档
|
||
|
||
> 日期:2026-06-11
|
||
> 状态:已实现(2026-06-11)
|
||
> 需求来源:质检部门新增环境检测登记能力
|
||
> 已确认:**方案 B — 扁平单表**(一次登记对应一个检测项目)
|
||
> 已确认:**检测人支持多选**,新增时默认选中当前登录用户
|
||
|
||
---
|
||
|
||
## 1. 背景与目标
|
||
|
||
### 1.1 业务背景
|
||
|
||
质检部门需对实验室/洁净区环境进行定期检测并留存记录,包括检测时间、检测人、检测项目、结果描述及检测附件。
|
||
|
||
### 1.2 目标
|
||
|
||
1. 在 **质检基础信息** 下新增菜单 **环境检测项维护**,管理可选检测项目(编码、名称、启用/停用)。
|
||
2. 在 **质检管理** 下新增菜单 **环境检测管理**,支持环境检测信息的登记、查询、编辑、查看与软删除。
|
||
3. 迁移 SQL 预置 6 项初始检测项目,租户可通过维护菜单增删改(停用后新登记不可选,历史记录保留快照)。
|
||
|
||
### 1.3 非目标(一期不做)
|
||
|
||
- 一次登记包含多个检测项目(头 + 明细行模式)
|
||
- 与洁净室主数据(`biz_clean_room`)关联
|
||
- 合格/不合格结论字段、审批流、到期提醒
|
||
- 与样本质检工单/任务联动
|
||
- 小程序端
|
||
|
||
---
|
||
|
||
## 2. 已确认方案
|
||
|
||
| 方案 | 说明 | 结论 |
|
||
|------|------|------|
|
||
| A. 主表 + 明细行 | 一次登记可含多项,每项独立描述与附件 | 未采用 |
|
||
| **B. 扁平单表** | **每条记录 = 一次检测 = 一个检测项目** | **采用** |
|
||
| C. 硬编码项目 | 不做维护菜单 | 未采用 |
|
||
|
||
**方案 B 含义**:用户登记「表面微生物检测」与「沉降菌检测」需分别创建两条记录;检测时间、检测人(可多人)、结果描述、附件均挂在单条记录上。
|
||
|
||
---
|
||
|
||
## 3. 菜单与路由
|
||
|
||
| 菜单 | 父级 | path | 组件 | menuCode |
|
||
|------|------|------|------|----------|
|
||
| 环境检测项维护 | 质检基础信息 `QCB…001` | `env-detect-item` | `views/quality-inspection/env-detect-item/index.vue` | `biz:envDetectItem:list` |
|
||
| 环境检测管理 | 质检管理 `QCM…001` | `env-detect-record` | `views/quality-inspection/env-detect-record/index.vue` | `biz:envDetectRecord:list` |
|
||
|
||
同步文件:
|
||
|
||
- `web-admin/src/router/modules/sqxp.ts`
|
||
- `backend/app/api/menu.py`
|
||
- `docs/sql/migrations/2026-06-11-env-detect.sql`
|
||
- `docs/sql/zkxw.sql`(全量基线,实现阶段更新)
|
||
|
||
---
|
||
|
||
## 4. 数据模型
|
||
|
||
命名空间:`biz_env_detect_*`。均含标准公共字段(`id` UUID、`tenant_no`、`order_num`、`remark`、`create_by`、`create_dept_id`、`create_time`、`update_by`、`update_time`、`del_flag`)。
|
||
|
||
### 4.1 `biz_env_detect_item` — 环境检测项(主数据)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| item_code | VARCHAR(64) | 项目编码,租户内唯一(`del_flag=0`) |
|
||
| item_name | VARCHAR(200) | 项目名称 |
|
||
| status | CHAR(1) | `1` 启用 / `0` 停用 |
|
||
|
||
**索引**:`uk_env_item_tenant_code (tenant_no, item_code, del_flag)`
|
||
|
||
**初始种子数据**(迁移时按租户 `zkxw` 插入,其他租户可自行维护):
|
||
|
||
| item_code | item_name |
|
||
|-----------|-----------|
|
||
| BMWS | 表面微生物检测 |
|
||
| SYFS | 实验室风速检测 |
|
||
| ZWQD | 紫外灯强度检测 |
|
||
| CJJ | 沉降菌检测 |
|
||
| JJZY | 洁净区噪音检测 |
|
||
| XFZL | 洁净区悬浮粒子检测 |
|
||
|
||
### 4.2 `biz_env_detect_record` — 环境检测登记(业务记录)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| record_no | VARCHAR(32) | 登记编号:`HJ` + yyyyMMdd + 4 位日序,租户内唯一 |
|
||
| detect_time | DATETIME | 检测时间(必填) |
|
||
| inspector_ids | VARCHAR(500) | 检测人用户 ID,逗号分隔,至少 1 人(必填) |
|
||
| inspector_names | VARCHAR(500) | 检测人姓名快照,逗号分隔,顺序与 `inspector_ids` 一致 |
|
||
| env_detect_item_id | VARCHAR(64) | 检测项目主数据 ID(必填) |
|
||
| item_code | VARCHAR(64) | 项目编码快照 |
|
||
| item_name | VARCHAR(200) | 项目名称快照 |
|
||
| result_desc | VARCHAR(2000) | 检测结果描述(必填) |
|
||
| attachment_urls | VARCHAR(2000) | 检测附件 URL,逗号分隔(MinIO,可选) |
|
||
|
||
**索引**:
|
||
|
||
- `uk_env_rec_tenant_no (tenant_no, record_no, del_flag)`
|
||
- `idx_env_rec_tenant_time (tenant_no, detect_time, del_flag)`
|
||
- `idx_env_rec_tenant_item (tenant_no, env_detect_item_id, del_flag)`
|
||
|
||
**快照规则**:
|
||
|
||
- 检测项目:创建/更新时从 `biz_env_detect_item` 写入 `item_code`、`item_name`。
|
||
- 检测人:创建/更新时根据 `inspector_ids` 批量查询 `sys_user`,按提交顺序写入 `inspector_names`(`nick_name` 优先,无则 `user_name`)。
|
||
- 主数据或用户改名后,历史记录仍展示保存时的快照。
|
||
|
||
**存储约定**:`inspector_ids` / `inspector_names` 与 `attachment_urls` 相同,采用逗号分隔字符串落库;API 层 `_row_to_dict` 解析为 `inspectorIds: string[]`、`inspectorNames: string[]`,并额外输出 `inspectorDisplay`(姓名以 ` / ` 拼接,供列表列展示)。
|
||
|
||
---
|
||
|
||
## 5. 后端 API
|
||
|
||
路由注册于 `app/api/env_detect.py`(或拆分为 `env_detect_item.py` + `env_detect_record.py`),在 `app/api/__init__.py` 与 `app/main.py` 注册。
|
||
|
||
前缀:`/web/admin/`。租户隔离 + 数据权限 + 软删除,列表默认 `create_time DESC`。
|
||
|
||
### 5.1 环境检测项
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/env-detect-items` | 分页列表(keyword、status) |
|
||
| GET | `/env-detect-items/active` | 启用项全量(登记下拉用,无分页) |
|
||
| GET | `/env-detect-items/{id}` | 详情 |
|
||
| POST | `/env-detect-items` | 新增 |
|
||
| PUT | `/env-detect-items/{id}` | 更新 |
|
||
| DELETE | `/env-detect-items/{id}` | 软删除 |
|
||
|
||
**校验**:`item_code`、`item_name` 必填;编码租户内唯一;已被登记引用的项允许停用,不允许物理删除(软删除前可选:若存在引用则提示或禁止删除,一期采用**允许软删除**但登记下拉仅取 `status=1` 且 `del_flag=0`)。
|
||
|
||
### 5.2 环境检测登记
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/env-detect-records` | 分页列表 |
|
||
| GET | `/env-detect-records/{id}` | 详情 |
|
||
| POST | `/env-detect-records` | 新增(服务端生成 `record_no`) |
|
||
| PUT | `/env-detect-records/{id}` | 更新 |
|
||
| DELETE | `/env-detect-records/{id}` | 软删除 |
|
||
|
||
**列表筛选参数**:`keyword`(编号/检测人姓名/结果描述模糊)、`envDetectItemId`、`inspectorId`(命中 `inspector_ids` 中任一 ID 即返回,MySQL `FIND_IN_SET`)、`detectTimeStart`、`detectTimeEnd`。
|
||
|
||
**创建/更新 Body**:
|
||
|
||
```json
|
||
{
|
||
"detectTime": "2026-06-11 14:30:00",
|
||
"inspectorIds": ["current-user-uuid", "other-user-uuid"],
|
||
"envDetectItemId": "item-uuid",
|
||
"resultDesc": "检测结果描述",
|
||
"attachmentUrls": "url1,url2",
|
||
"remark": ""
|
||
}
|
||
```
|
||
|
||
**检测人校验**:
|
||
|
||
- `inspectorIds` 必填,去重后至少 1 个有效用户 ID。
|
||
- 用户须属于当前租户且未删除;无效 ID 返回 400。
|
||
- 保存时按 `inspectorIds` 数组顺序生成快照,不依赖前端传入姓名。
|
||
|
||
**编号生成**:`HJ` + `yyyyMMdd` + 4 位序,逻辑对齐 `pilot_delivery._generate_delivery_no`。
|
||
|
||
---
|
||
|
||
## 6. 前端设计
|
||
|
||
### 6.1 界面模式
|
||
|
||
| 页面 | 模式 | 参考 |
|
||
|------|------|------|
|
||
| 环境检测项维护 | **P01** | `sample-reception-check-item/index.vue` |
|
||
| 环境检测管理 | **P01** + 附件卡片 | `sample-reception-check-item` + OpenSpec 附件上传卡片 |
|
||
|
||
### 6.2 环境检测项维护
|
||
|
||
- 筛选:关键词(编码/名称)、状态
|
||
- 列表列:序号、项目编码、项目名称、状态 Tag、备注、操作(查看/编辑/删除)
|
||
- 弹窗字段:项目编码、项目名称、状态、备注
|
||
- 筛选区提示:「停用后新登记不再展示,历史记录仍按快照展示。」
|
||
|
||
### 6.3 环境检测管理
|
||
|
||
**筛选**:检测时间范围、检测项目(下拉,启用项)、检测人(用户单选下拉,筛「包含该检测人」的记录)、关键词(编号/结果描述)
|
||
|
||
**列表列**:序号、登记编号、检测时间、检测人(`inspectorDisplay`,多人以 ` / ` 分隔)、检测项目、结果描述(tooltip 截断)、创建时间、操作
|
||
|
||
**新增/编辑弹窗**(`dialog-form-layout`,宽约 640px,`form-grid-2`):
|
||
|
||
| 字段 | 控件 | 必填 |
|
||
|------|------|------|
|
||
| 检测时间 | `el-date-picker` type=datetime | 是 |
|
||
| 检测人 | `el-select` **multiple** + `filterable`,数据源 `fetchUserOptions()` | 是(≥1 人) |
|
||
| 检测项目 | 下拉,数据源 `/env-detect-items/active` | 是 |
|
||
| 检测结果描述 | `el-input` textarea,`form-col-span-2` | 是 |
|
||
| 检测附件 | 附件卡片上传(`fetchUploadAttachment`),`form-col-span-2` | 否 |
|
||
| 备注 | `el-input` textarea,`form-col-span-2` | 否 |
|
||
|
||
**检测人默认与交互**(对齐 `sample-reception` 经手人逻辑,扩展为多选):
|
||
|
||
1. **新增**:打开弹窗时 `inspectorIds` 默认包含 **当前登录用户 ID**;若用户列表中尚无当前用户,先 `ensureCurrentUserInOptions()` 注入选项(参考 `sample-reception/index.vue` `getCurrentUserHandler`)。
|
||
2. **新增默认值**:检测时间默认当前时刻(可选,与样本接收一致)。
|
||
3. 用户可继续勾选其他检测人;可取消当前登录人,但提交前须至少保留 1 人(前后端双重校验)。
|
||
4. **编辑**:回显已保存的 `inspectorIds`;若历史检测人不在下拉列表中,合并进选项以保证展示。
|
||
|
||
**查看**:`SystemViewDialog` 展示 `inspectorDisplay`(或逐人换行);附件区支持预览/下载。
|
||
|
||
**状态 Tag**:本模块无业务状态字段;检测项维护页 `status` 走 `status-tag-registry`。
|
||
|
||
### 6.4 API 模块
|
||
|
||
- `web-admin/src/api/env-detect-item.ts`
|
||
- `web-admin/src/api/env-detect-record.ts`
|
||
|
||
类型字段与后端 `_row_to_dict` 保持一致(camelCase)。
|
||
|
||
---
|
||
|
||
## 7. 权限与菜单 SQL(草案)
|
||
|
||
```sql
|
||
-- 环境检测项维护(父:质检基础信息 QCB00000000000000000000000000001)
|
||
INSERT INTO sys_menu (...) VALUES (
|
||
'71000000000000000000000000000001', '环境检测项维护',
|
||
'QCB00000000000000000000000000001', 'C', 'env-detect-item',
|
||
'/quality-inspection/env-detect-item/index', 'biz:envDetectItem:list', ...
|
||
);
|
||
|
||
-- 环境检测管理(父:质检管理 QCM00000000000000000000000000001)
|
||
INSERT INTO sys_menu (...) VALUES (
|
||
'71000000000000000000000000000002', '环境检测管理',
|
||
'QCM00000000000000000000000000001', 'C', 'env-detect-record',
|
||
'/quality-inspection/env-detect-record/index', 'biz:envDetectRecord:list', ...
|
||
);
|
||
```
|
||
|
||
`order_num`:项维护置于「质检物料库」之前(建议 7);环境检测管理置于「质检工单」之后(建议 3)。
|
||
|
||
---
|
||
|
||
## 8. 实现检查清单
|
||
|
||
- [ ] `python scripts/check_field_consistency.py` 通过(CRUD ↔ Schema ↔ 前端 formData)
|
||
- [ ] `./scripts/update-graph.sh backend` 与 `frontend`(新增模块后)
|
||
- [ ] `App.vue` `panelTitleBarTextRules` 写入「环境检测项列表」「环境检测登记列表」
|
||
- [ ] 手工验证:新增项 → 登记选到 → 编辑快照不变 → 停用项不出现在下拉
|
||
|
||
---
|
||
|
||
## 9. 工作量估时
|
||
|
||
| 层 | 内容 | 估时 |
|
||
|----|------|------|
|
||
| DB | 2 表 + 菜单 + 种子 | 0.5d |
|
||
| Backend | 2 组 CRUD + 编号生成 | 1d |
|
||
| Frontend | 2 个 P01 页 + 附件上传 | 1d |
|
||
| 联调 | 字段一致性 + 手工测试 | 0.5d |
|
||
| **合计** | | **约 3 人天** |
|
||
|
||
---
|
||
|
||
## 10. 变更记录
|
||
|
||
| 日期 | 说明 |
|
||
|------|------|
|
||
| 2026-06-11 | 初稿;用户确认方案 B(扁平单表) |
|
||
| 2026-06-11 | 检测人改为多选;新增默认选中当前登录用户;库表 `inspector_ids` / `inspector_names` |
|