307 lines
11 KiB
Markdown
307 lines
11 KiB
Markdown
# 样本质检信息 Tab — 短信通知功能设计
|
||
|
||
> 状态:已实现
|
||
> 日期:2026-06-01
|
||
> 需求来源:样本信息管理页新增「样本质检信息」Tab,质检完成后向客户发送短信(线下复制发送)
|
||
|
||
## 1. 背景与目标
|
||
|
||
### 1.1 现状
|
||
|
||
「样本信息管理」页面(`/#/cell-storage/sample-info`)当前有两个 Tab:
|
||
|
||
| 顺序 | Tab | 能力 |
|
||
|------|-----|------|
|
||
| 1 | 样本接收信息 | 接收结论 + 短信提取/标记通知 |
|
||
| 2 | 样本入库信息 | 入库结论 + 短信提取/标记通知 |
|
||
|
||
业务链路:**接收 → 质检 → 入库**。质检环节完成后同样需要通知客户,但当前缺少对应 Tab 与后端能力。
|
||
|
||
### 1.2 目标
|
||
|
||
在「样本接收信息」与「样本入库信息」之间插入 **样本质检信息** Tab,交互与「样本入库信息」一致:
|
||
|
||
- 筛选 + 分页列表
|
||
- 查看协议单(`ProtocolViewDialog`)
|
||
- **提取短信**(复制到剪贴板)
|
||
- **标记已/未通知**
|
||
|
||
**关键约束**(与现有两个 Tab 一致):系统不自动发短信,仅生成内容供运营线下发送。
|
||
|
||
### 1.3 参考实现
|
||
|
||
| 层级 | 样本入库信息(克隆源) |
|
||
|------|------------------------|
|
||
| 前端 Tab | `StorageEntryInfoTab.vue` |
|
||
| 前端 API | `storage-entry-sms-notification.ts` |
|
||
| 后端 API | `storage_entry_sms_notification.py` |
|
||
| CRUD | `storage_entry_sms_notification.py` |
|
||
| 通知表 | `biz_storage_entry_sms_notification` |
|
||
| 业务数据源 | `biz_storage_release_review` |
|
||
|
||
设计文档参考:`docs/superpowers/specs/2025-05-23-storage-entry-sms-notification-design.md`
|
||
|
||
---
|
||
|
||
## 2. 数据范围
|
||
|
||
### 2.1 主数据源
|
||
|
||
**`biz_qc_work_order`(质检工单)**,筛选条件:
|
||
|
||
| 字段 | 值 | 说明 |
|
||
|------|-----|------|
|
||
| `reception_source` | `cell_storage` | 仅细胞存储协议样本,不含科研捐赠 |
|
||
| `qc_biz_type` | `inbound` | 入库质检(接收后自动创建的工单类型) |
|
||
| `work_order_status` | `ywc` | 工单已完成(所有质检任务均完成) |
|
||
| `del_flag` | `0` | 未删除 |
|
||
|
||
不展示:`dpz`(待配置)、`ypz`(已配置未完成)、`yzf`(已作废)。
|
||
|
||
### 2.2 质检结论(派生字段)
|
||
|
||
工单表无单一「综合结论」字段,需从 **`biz_qc_task`** 派生:
|
||
|
||
```
|
||
若任一已完成任务的 conclusion = 'btg' → 综合结论 = 不通过 (btg)
|
||
否则(全部任务 conclusion = 'tg')→ 综合结论 = 通过 (tg)
|
||
```
|
||
|
||
任务结论码:`tg` / `btg`(与 `status-tag-registry.ts` 中 `qcConclusion` 一致)。
|
||
|
||
### 2.3 质检完成时间(展示字段)
|
||
|
||
取该工单下所有 `task_status = 'ywc'` 任务的 **`completed_time` 最大值**;若无则回退工单 `update_time`(状态变为 `ywc` 时更新)。
|
||
|
||
### 2.4 关联键
|
||
|
||
与现有细胞存储跨表约定一致:**`tenant_no` + `sample_code`** 关联协议样本、当事人信息(参见 OpenSpec `api-conventions` § 细胞存储样本跨表关联键)。
|
||
|
||
联查路径:
|
||
|
||
```
|
||
BizQcWorkOrder
|
||
→ BizProtocolSample (sample_code + tenant_no)
|
||
→ BizCollectionProtocol
|
||
→ BizProtocolPartyCustomer
|
||
→ BizQcSmsNotification (懒创建,qc_work_order_id)
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 方案对比
|
||
|
||
| 方案 | 描述 | 优点 | 缺点 | 建议 |
|
||
|------|------|------|------|------|
|
||
| **A. 全量克隆入库短信模块(推荐)** | 新建 `biz_qc_sms_notification` 表 + CRUD + API + Tab | 与现有模式一致;隔离清晰;改动面可控 | 需新建表与 5+ 文件 | ✅ 采用 |
|
||
| B. 扩展质检工单列表 API | 在 `qc_work_order` 列表加 SMS 字段 | 少一个 API 模块 | 职责混杂;权限与筛选语义不同;改动质检模块风险高 | ❌ |
|
||
| C. 合并到样本接收/入库通知表 | 一张表多类型 | 表少 | 破坏现有独立表设计;联查与模板逻辑耦合 | ❌ |
|
||
|
||
**推荐方案 A**:与 2025-05-23 入库短信设计同一套路,团队已有成熟模板。
|
||
|
||
---
|
||
|
||
## 4. 后端设计
|
||
|
||
### 4.1 新建表 `biz_qc_sms_notification`
|
||
|
||
```sql
|
||
CREATE TABLE biz_qc_sms_notification (
|
||
id VARCHAR(64) NOT NULL COMMENT 'UUID主键',
|
||
qc_work_order_id VARCHAR(64) NOT NULL COMMENT '关联 biz_qc_work_order.id',
|
||
protocol_id VARCHAR(64) DEFAULT NULL COMMENT '冗余协议单ID',
|
||
sms_content VARCHAR(500) DEFAULT NULL COMMENT '生成的短信内容',
|
||
sms_notified TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0=未通知 1=已通知',
|
||
notified_by VARCHAR(64) DEFAULT NULL,
|
||
notified_by_name VARCHAR(64) DEFAULT NULL,
|
||
notified_time DATETIME DEFAULT NULL,
|
||
tenant_no VARCHAR(64) DEFAULT NULL,
|
||
order_num INT DEFAULT 0,
|
||
remark VARCHAR(512) DEFAULT NULL,
|
||
create_by VARCHAR(64) DEFAULT NULL,
|
||
create_dept_id VARCHAR(64) DEFAULT NULL,
|
||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||
update_by VARCHAR(64) DEFAULT NULL,
|
||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
del_flag CHAR(1) DEFAULT '0',
|
||
PRIMARY KEY (id),
|
||
KEY idx_qc_work_order_id (qc_work_order_id),
|
||
KEY idx_tenant_no (tenant_no)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='样本质检短信通知';
|
||
```
|
||
|
||
### 4.2 CRUD 要点(`qc_sms_notification.py`)
|
||
|
||
- **list_notifications**:联查 + 租户隔离 + `apply_data_scope`
|
||
- **懒创建**:列表加载时为已完成工单自动插入 `sms_notified=0` 记录
|
||
- **toggle_notification_status**:标记已/未通知,记录操作人与时间
|
||
- **generate_sms_content**:按综合结论生成模板并持久化到 `sms_content`
|
||
|
||
列表 `_row_to_dict` 返回字段(驼峰):
|
||
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| id | 通知记录 ID |
|
||
| qcWorkOrderId | 质检工单 ID |
|
||
| collectionProtocolId | 协议单 ID |
|
||
| protocolNo / protocolStatus | 协议号与状态 |
|
||
| motherName / newbornName | 当事人 |
|
||
| sampleCode / sampleTypeName | 样本 |
|
||
| qcCompleteTime | 质检完成时间 |
|
||
| qcConclusion / qcConclusionLabel | tg/btg 及中文标签 |
|
||
| smsNotified / smsContent | 通知状态与内容 |
|
||
|
||
### 4.3 短信模板(初稿,待产品确认)
|
||
|
||
```
|
||
通过:尊敬的{母亲}女士,您的样本(编码:{code})已完成质检,结果合格。如有疑问请联系客服。
|
||
不通过:尊敬的{母亲}女士,您的样本(编码:{code})质检未通过。如有疑问请联系客服。
|
||
```
|
||
|
||
变量:`mother_name` ← 当事人表;`code` ← 工单 `sample_code`;日期可选加入完成日期。
|
||
|
||
### 4.4 API 端点
|
||
|
||
前缀 `/api/web/admin`:
|
||
|
||
| 方法 | 路径 | 功能 |
|
||
|------|------|------|
|
||
| GET | `/qc-sms-notifications/list` | 分页列表 |
|
||
| PUT | `/qc-sms-notifications/{id}/toggle-status` | 切换通知状态 |
|
||
| POST | `/qc-sms-notifications/{id}/generate-sms` | 生成短信 |
|
||
|
||
**权限码**(与样本信息管理 Tab 共用,无需新菜单):
|
||
|
||
```python
|
||
require_any_menu_code(
|
||
"cell-storage:sample-info:list",
|
||
"cell-storage:sample-qc-info:list", # 可选:预留独立权限
|
||
)
|
||
```
|
||
|
||
初期建议仅 `cell-storage:sample-info:list`,与入库/接收 API 策略一致。
|
||
|
||
Query 参数:
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| keyword | 协议号/姓名/样本编码 |
|
||
| qcConclusion | `tg` / `btg` |
|
||
| smsNotified | `0` / `1` |
|
||
| qcCompleteTimeStart / qcCompleteTimeEnd | 完成时间范围 |
|
||
|
||
默认时间范围:**近 30 天**(与另外两个 Tab 一致)。
|
||
|
||
---
|
||
|
||
## 5. 前端设计
|
||
|
||
### 5.1 Tab 入口
|
||
|
||
修改 `web-admin/src/views/cell-storage/sample-info/index.vue`:
|
||
|
||
| 顺序 | key | 标题 | 图标建议 |
|
||
|------|-----|------|----------|
|
||
| 1 | sample-reception | 样本接收信息 | Box |
|
||
| 2 | **sample-qc** | **样本质检信息** | **DocumentChecked** |
|
||
| 3 | storage-entry | 样本入库信息 | FolderOpened |
|
||
|
||
`VALID_TABS` 增加 `sample-qc`;样式类由 `--dual` 改为 `--triple`(三 Tab 布局)。
|
||
|
||
### 5.2 新建组件
|
||
|
||
`web-admin/src/views/cell-storage/protocol-audit/SampleQcInfoTab.vue`
|
||
(与 `SampleReceptionInfoTab` / `StorageEntryInfoTab` 同目录,便于复用)
|
||
|
||
**筛选区**:
|
||
|
||
| 字段 | 控件 | 绑定 |
|
||
|------|------|------|
|
||
| 关键词 | el-input | keyword |
|
||
| 质检结论 | el-select | qcConclusion(通过 tg / 不通过 btg) |
|
||
| 通知状态 | el-select | smsNotified |
|
||
| 质检完成时间 | daterange | qcCompleteTimeRange |
|
||
|
||
**表格列**(全部 `min-width`,居中,状态用 `el-tag`):
|
||
|
||
协议号、协议状态、母亲姓名、新生儿姓名、样本编码、样本类型、**质检完成时间**、**质检结论**、通知状态、操作(查看 / 提取短信 / 标记通知)。
|
||
|
||
**查看**:`ProtocolViewDialog`(`show-audit-history` 等同入库 Tab)。
|
||
|
||
### 5.3 新建 API 模块
|
||
|
||
`web-admin/src/api/qc-sms-notification.ts` — 3 个函数,镜像 `storage-entry-sms-notification.ts`。
|
||
|
||
---
|
||
|
||
## 6. 业务流程图
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[样本接收 js] --> B[创建入库质检工单]
|
||
B --> C[配置并执行质检任务]
|
||
C --> D{全部任务完成?}
|
||
D -->|是| E[工单状态 ywc]
|
||
E --> F[样本质检信息 Tab 展示]
|
||
F --> G[提取短信 / 标记已通知]
|
||
G --> H[运营线下发送]
|
||
E --> I[后续入库放行...]
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 边界情况
|
||
|
||
| 场景 | 处理 |
|
||
|------|------|
|
||
| 工单 ywc 但部分任务无 conclusion | 不纳入列表,或结论显示「待确认」;实现时需明确(建议:无 conclusion 不展示) |
|
||
| 科研捐赠样本 | `reception_source != cell_storage` 过滤排除 |
|
||
| 出库/临时质检 | `qc_biz_type != inbound` 过滤排除 |
|
||
| 缺少协议单 | 查看按钮提示,不打开弹窗 |
|
||
| 旧书签 `?tab=sample-qc` | sample-info 页 onMounted 解析 query |
|
||
|
||
---
|
||
|
||
## 8. 文件清单(预估)
|
||
|
||
### 新建
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `docs/sql/biz_qc_sms_notification.sql` | 建表 DDL |
|
||
| `docs/sql/migration-2026-06-01-qc-sms-notification.sql` | 增量迁移 |
|
||
| `backend/app/crud/qc_sms_notification.py` | CRUD |
|
||
| `backend/app/api/qc_sms_notification.py` | API |
|
||
| `web-admin/src/api/qc-sms-notification.ts` | 前端 API |
|
||
| `web-admin/src/views/cell-storage/protocol-audit/SampleQcInfoTab.vue` | Tab 组件 |
|
||
|
||
### 修改
|
||
|
||
| 文件 | 修改 |
|
||
|------|------|
|
||
| `backend/app/models/models.py` | `BizQcSmsNotification` 模型 |
|
||
| `backend/app/api/__init__.py` / `main.py` | 注册路由 |
|
||
| `web-admin/src/views/cell-storage/sample-info/index.vue` | 增加 Tab |
|
||
| `docs/sql/zkxw.sql` | 全量基线同步 |
|
||
|
||
**不做的事**:不自动发短信;不改动质检工单执行逻辑;不修改接收/入库 Tab。
|
||
|
||
---
|
||
|
||
## 9. 待确认项(评审门禁)
|
||
|
||
1. **短信文案**:上述通过/不通过模板是否可用?是否需要包含完成日期?
|
||
2. **列表范围**:是否仅「工单已完成 ywc」?是否还需要展示「进行中 ypz」供提前通知?(建议:仅 ywc,与入库 Tab 只展示终态一致)
|
||
3. **权限**:是否沿用 `cell-storage:sample-info:list`,无需新菜单权限?
|
||
|
||
---
|
||
|
||
## 10. 工作量评估
|
||
|
||
| 模块 | 预估 |
|
||
|------|------|
|
||
| 后端(表+CRUD+API) | 0.5~1 天 |
|
||
| 前端 Tab + API | 0.5 天 |
|
||
| 联调与边界验证 | 0.5 天 |
|
||
| **合计** | **约 1.5~2 天** |
|