feat:数据质量筛选规则需求整理
This commit is contained in:
@@ -0,0 +1,966 @@
|
||||
# 异常事件数据质量控制规则说明书
|
||||
|
||||
> **文档版本**:v1.0
|
||||
> **编写日期**:2026-07-28
|
||||
> **适用范围**:系统管理、健康咨询、应急就医、健康体检、营养管理、健康监测(共 6 个业务板块)
|
||||
> **执行主体**:数据中台(于数据同步环节内嵌执行质量校验)
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
- [一、文档概述](#一文档概述)
|
||||
- [二、系统脏数据类型定义](#二系统脏数据类型定义)
|
||||
- [三、脏数据与结果异常的边界](#三脏数据与结果异常的边界)
|
||||
- [四、数据中台质量校验流程](#四数据中台质量校验流程)
|
||||
- [五、各模块检测规则](#五各模块检测规则)
|
||||
- [5.1 系统管理](#51-系统管理)
|
||||
- [5.2 健康咨询](#52-健康咨询)
|
||||
- [5.3 应急就医](#53-应急就医)
|
||||
- [5.4 健康体检](#54-健康体检)
|
||||
- [5.5 营养管理](#55-营养管理)
|
||||
- [5.6 健康监测](#56-健康监测)
|
||||
- [六、附录](#六附录)
|
||||
|
||||
---
|
||||
|
||||
## 一、文档概述
|
||||
|
||||
### 1.1 编写目的
|
||||
|
||||
本文档定义平台各业务板块"系统脏数据"的统一质量校验规则,作为数据中台实现自动化数据质量检测(DQC, Data Quality Check)的依据。核心目标:
|
||||
|
||||
1. **统一标准**:收敛各板块原型和研发文档中分散、不一致的脏数据类型定义,建立全平台统一的异常分类体系
|
||||
2. **明确边界**:厘清"系统脏数据"与"结果异常"的判定标准,确保两类异常各归其位
|
||||
3. **指导落地**:为数据中台在 CDC / 增量同步链路中嵌入质量校验提供规则输入
|
||||
|
||||
### 1.2 适用范围
|
||||
|
||||
| 板块 | 管理端模块 | 当前状态 |
|
||||
|------|-----------|---------|
|
||||
| 健康咨询 | `web-admin/health-consult/` | 原型已定稿,后端已部分实现 |
|
||||
| 应急就医 | `web-admin/emergency-dispatch/` | 原型已定稿,后端有占位 |
|
||||
| 健康体检 | `web-admin/health-checkup/` | 原型已定稿 |
|
||||
| 营养管理 | `web-admin/nutrition/` | 原型已定稿,后端已部分实现 |
|
||||
| 健康监测 | `web-admin/health-monitor/` | 原型已定稿 |
|
||||
| 系统管理 | `platform-java/platform-system/` | 后端已实现 |
|
||||
|
||||
### 1.3 术语定义
|
||||
|
||||
| 术语 | 定义 |
|
||||
|------|------|
|
||||
| **系统脏数据** | 写入数据库后,因其字段值违反数据完整性约束(非空、格式、取值范围、外键关联、唯一性、逻辑一致性)而不可信或不可用的数据记录 |
|
||||
| **结果异常** | 数据本身在存储层面合法、完整,但所反映的业务结果偏离正常范围(如超时未关闭、评分异常偏低、指标超出医学参考范围等),属于业务流程或健康结果的异常,**不属于系统脏数据范畴** |
|
||||
| **数据中台 DQC** | Data Quality Check,在数据同步管道(CDC 或定时增量)中内嵌执行的数据质量校验环节 |
|
||||
| **CDC** | Change Data Capture,基于数据库变更日志的实时增量数据捕获机制 |
|
||||
|
||||
---
|
||||
|
||||
## 二、系统脏数据类型定义
|
||||
|
||||
全平台统一使用以下 6 种脏数据类型。各板块的具体检测规则均以此分类为准。
|
||||
|
||||
### 2.1 类型一览
|
||||
|
||||
| 编码 | 类型名称 | 判定标准 | 严重级别 |
|
||||
|------|----------|----------|:--:|
|
||||
| D01 | **数据缺失** | 业务规则要求非空的字段,其值为 NULL 或空字符串 | 高 |
|
||||
| D02 | **格式违规** | 字段值不符合预定义的格式规范(正则、JSON Schema、日期格式等) | 高 |
|
||||
| D03 | **取值越界** | 字段值超出物理极限或逻辑合理范围(含连续数值越界和离散枚举越界) | 高 |
|
||||
| D04 | **逻辑冲突** | 同一记录内多个字段之间,或存在业务关联的多条记录之间,字段值存在不可调和的逻辑矛盾 | 高 |
|
||||
| D05 | **关联断裂** | 外键字段值非空,但其引用的目标记录在关联表中不存在(孤儿记录) | 中 |
|
||||
| D06 | **数据重复** | 违反业务唯一性约束,存在多条本应唯一的记录 | 中 |
|
||||
|
||||
### 2.2 各类型详细定义
|
||||
|
||||
#### D01 — 数据缺失
|
||||
|
||||
**定义**:业务语义上必须具备值的字段,在数据库层面为 NULL 或等效空值。
|
||||
|
||||
**判定逻辑**:
|
||||
- 单字段规则:`field IS NULL OR field = ''`
|
||||
- 组合规则:同一记录内多个关联字段全部为空(如身高、体重、腰围三者均为空)
|
||||
|
||||
**典型示例**:
|
||||
- 用户档案中姓名为空
|
||||
- 订单主表中订单编号为空
|
||||
- 体检报告中检查结果值为空
|
||||
- 设备编码为空
|
||||
|
||||
**注意事项**:
|
||||
- 允许为空的字段(如选填的备注、非必填的附件URL)不在检测范围
|
||||
- 需结合业务规则确认哪些字段为"必填",不能仅凭数据库 DDL 的 `NOT NULL` 约束判断(有些字段在 DDL 层面允许 NULL,但业务上必须具备值)
|
||||
|
||||
---
|
||||
|
||||
#### D02 — 格式违规
|
||||
|
||||
**定义**:字段值已填充,但其字符串形式不符合约定的格式规范。
|
||||
|
||||
**判定逻辑**:
|
||||
- 正则匹配失败(手机号、身份证号、邮箱等)
|
||||
- JSON/XML 解析失败(如 `questions_json`、`nutrition_summary` 等)
|
||||
- 日期/时间字符串无法按预期格式解析
|
||||
- URL 格式不合法
|
||||
|
||||
**典型示例**:
|
||||
- 手机号字段值为 `"abc123"` 或长度不为 11 位
|
||||
- 常规体检指标数据出现汉字,空腹血糖值 `"无记录"`
|
||||
- 问卷 JSON 字段 `parse()` 抛出异常
|
||||
- 日期字段值为 `"2026-13-40"`(无效日期)
|
||||
- 生活习惯标记字段不符合 `state,score,fullmark` 格式
|
||||
|
||||
**注意事项**:
|
||||
- 格式校验的正则表达式需与业务端输入校验规则保持一致
|
||||
- 对于允许自由文本的字段(如备注、描述),不执行格式校验
|
||||
|
||||
---
|
||||
|
||||
#### D03 — 取值越界
|
||||
|
||||
**定义**:字段值已填充且格式合法,但数值大小或枚举编码超出了物理/逻辑合理范围。
|
||||
|
||||
**判定逻辑**:
|
||||
- 连续数值越界:`value < min OR value > max`(min/max 基于人体生理极限或业务规则)
|
||||
- 离散枚举越界:`value NOT IN (enum_set)`(enum_set 为字段的合法枚举值集合)
|
||||
|
||||
**典型示例**:
|
||||
- BMI 值为 85.3 或 -5(合理范围 10~80)
|
||||
- 收缩压为 350 mmHg(合理范围 50~300)
|
||||
- 库存数量为 -100(不应为负)
|
||||
- 性别字段值为 3(枚举仅 1=男 / 2=女)
|
||||
- 人群分类字段值为 `"X"`(枚举仅 A/B/C/D/E)
|
||||
- 经纬度超出中国版图范围,北纬4°-53°33′,东经135°5′-73°40′
|
||||
|
||||
#### 统一取值越界参考标准
|
||||
|
||||
以下为跨模块通用的数值边界定义。各模块检测规则中的对应阈值统一以此表为准,避免同一业务含义的字段在不同模块中出现不一致的校验边界。
|
||||
|
||||
**人体测量类**
|
||||
|
||||
| 字段 | 单位 | 下限 | 上限 | 说明 |
|
||||
|------|------|:--:|:--:|------|
|
||||
| 身高 | cm | 50 | 250 | 低于50cm不具备成年人体征,高于250cm超出人类身高纪录 |
|
||||
| 体重 | kg | 20 | 300 | 低于20kg不具备成年人体征,300kg为临床极端值上限 |
|
||||
| BMI | — | 10 | 80 | 10以下为生命维持极限,80以上为世界纪录的约3倍 |
|
||||
| 体脂率 | % | 2 | 60 | 2%为男性必需脂肪下限,60%超出临床病态肥胖上限 |
|
||||
| 腰围 | cm | 30 | 200 | 30cm为新生儿水平,200cm超出临床极端值 |
|
||||
| 年龄 | 岁 | 0 | 150 | 0岁为出生当年,150岁超出人类寿命极限 |
|
||||
|
||||
**生命体征类**
|
||||
|
||||
| 字段 | 单位 | 下限 | 上限 | 说明 |
|
||||
|------|------|:--:|:--:|------|
|
||||
| 收缩压 | mmHg | 50 | 300 | 50mmHg为濒危休克值,300mmHg超出血压计量程 |
|
||||
| 舒张压 | mmHg | 30 | 200 | 30mmHg为濒危休克值,200mmHg超出临床极端值 |
|
||||
| 心率 | bpm | 20 | 300 | 20bpm为深度休眠/濒危值,300bpm超出心室颤动极限 |
|
||||
| 血氧饱和度 | % | 50 | 100 | 50%以下为致命性低氧,100%为理论饱和上限 |
|
||||
| 体温 | ℃ | 30 | 45 | 30℃为致命性低温,45℃超出人体存活上限 |
|
||||
| 空腹血糖 | mmol/L | 0 | 50 | 0为理论下界,50mmol/L超出临床极端高值 |
|
||||
|
||||
**时间度量类**
|
||||
|
||||
| 字段 | 单位 | 下限 | 上限 | 说明 |
|
||||
|------|------|:--:|:--:|------|
|
||||
| 睡眠时长 | 分钟 | 0 | 1440 | 0为未睡眠,1440为一天总分钟数 |
|
||||
|
||||
**地理坐标类**
|
||||
|
||||
| 字段 | 单位 | 下限 | 上限 | 说明 |
|
||||
|------|------|:--:|:--:|------|
|
||||
| 经度(中国境内) | 度 | 73 | 136 | 东经73°40′(新疆阿克赛钦)~ 东经135°5′(黑龙江抚远),取整 |
|
||||
| 纬度(中国境内) | 度 | 4 | 54 | 北纬4°(南沙群岛曾母暗沙)~ 北纬53°33′(黑龙江漠河),取整 |
|
||||
|
||||
**评分与占比类**
|
||||
|
||||
| 字段 | 单位 | 下限 | 上限 | 说明 |
|
||||
|------|------|:--:|:--:|------|
|
||||
| 评分(5分制) | 分 | 0 | 5 | 适用于专家评分、咨询评分等五级评分体系 |
|
||||
| 百分比 | % | 0 | 100 | 适用于回复率、电量百分比、完成率等百分比字段 |
|
||||
| pH 值 | — | 0 | 14 | 水溶液酸碱度理论范围 |
|
||||
|
||||
**与格式违规的区别**:
|
||||
- 格式违规关注"值的形态"(如"abc"不是数字)
|
||||
- 取值越界关注"值的量级"(如 999 是合法数字但超出了合理上限)
|
||||
|
||||
---
|
||||
|
||||
#### D04 — 逻辑冲突
|
||||
|
||||
**定义**:单条记录内多个字段之间存在不可调和的值矛盾,或多条关联记录之间的汇总/引用关系不成立。
|
||||
|
||||
**判定逻辑**:
|
||||
- 同一行内两字段比较(如 `end_time < start_time`、`sbp < dbp`)
|
||||
- 一对多汇总不一致(如 `total_amount != SUM(subtotal)`)
|
||||
- 状态与时间戳矛盾(如状态=已完成但 end_time 为空)
|
||||
- 标记与明细不一致(如 is_exception=1 但所有子项指标均正常)
|
||||
|
||||
**典型示例**:
|
||||
- 咨询结束时间早于开始时间
|
||||
- 订单总金额不等于明细小计之和
|
||||
- 会话状态为"进行中"但结束时间已填充
|
||||
- 收缩压(110)低于舒张压(85)
|
||||
- 睡眠时长 + 运动时长 > 1440 分钟(超过一天)
|
||||
|
||||
**注意事项**:
|
||||
- 逻辑冲突规则需要深入理解业务语义,建议由产品经理与研发联合确认
|
||||
- 统计类字段(如 `statics_num`)与源表记录数的一致性校验属于此类,但因实时性要求低,可在每日全量对账时执行
|
||||
|
||||
---
|
||||
|
||||
#### D05 — 关联断裂
|
||||
|
||||
**定义**:记录中的外键字段指向了一个在关联表中已不存在的 ID。
|
||||
|
||||
**判定逻辑**:
|
||||
- `foreign_key IS NOT NULL AND foreign_key NOT IN (SELECT id FROM referenced_table)`
|
||||
|
||||
**典型示例**:
|
||||
- 咨询记录中的 `expert_id` 在专家表中不存在(专家已删除)
|
||||
- 订单中的 `user_id` 在用户表中不存在
|
||||
- 评价记录中的 `consult_id` 在咨询表中不存在
|
||||
- AED 设备部署点位关联的应急中心 ID 无效
|
||||
|
||||
**注意事项**:
|
||||
- 仅在外键值非空时检测(允许 NULL 的外键不触发此规则,因为 NULL 表示"未关联"而非"关联无效")
|
||||
- 软删除场景需确认关联表的过滤条件(如 `del_falg IS NULL`)
|
||||
|
||||
---
|
||||
|
||||
#### D06 — 数据重复
|
||||
|
||||
**定义**:同一业务实体在违反唯一性约束的情况下出现了多条记录。
|
||||
|
||||
**判定逻辑**:
|
||||
- 按业务唯一键分组计数:`COUNT(*) > 1 GROUP BY business_unique_key`
|
||||
|
||||
**典型示例**:
|
||||
- 同一用户同一年度存在多条活跃人群分类记录
|
||||
- 同一员工同一活动重复报名
|
||||
- 同一设备同一时间点存在多条监测数据记录
|
||||
- 同一用户同一天存在多条营养分析结果记录
|
||||
|
||||
**注意事项**:
|
||||
- 业务唯一键 ≠ 数据库唯一索引。需根据业务语义定义去重维度
|
||||
- 区分"合理的多条记录"(如一个用户多次咨询)与"异常的多条记录"(如一个用户同一时刻两条档案)
|
||||
|
||||
---
|
||||
|
||||
## 三、脏数据与结果异常的边界
|
||||
|
||||
### 3.1 判定原则
|
||||
|
||||
> **核心原则**:系统脏数据关注"数据本身是否合法",结果异常关注"业务结果是否正常"。前者是数据质量的范畴,后者是业务监控的范畴。
|
||||
|
||||
### 3.2 边界对照表
|
||||
|
||||
| 场景 | 数据是否合法 | 分类 | 理由 |
|
||||
|------|:--:|------|------|
|
||||
| 血压值为 -50 mmHg | 否 | **脏数据 (D03)** | 数值超出物理极限 |
|
||||
| JSON 字段解析失败 | 否 | **脏数据 (D02)** | 格式不符合规范 |
|
||||
| 员工编号为空 | 否 | **脏数据 (D01)** | 必填字段缺失 |
|
||||
| 订单关联的用户已删除 | 否 | **脏数据 (D05)** | 外键关联失效 |
|
||||
| 同一用户同日两条档案 | 否 | **脏数据 (D06)** | 违反唯一性约束 |
|
||||
| 收缩压 110 < 舒张压 85 | 否 | **脏数据 (D04)** | 字段间逻辑矛盾 |
|
||||
| 血压值 185/110 mmHg | **是** | 结果异常 | 值在物理范围内,但超出医学正常参考范围 |
|
||||
| 工单创建后 7 天未关闭 | **是** | 结果异常 | 状态值和时长均合法,属业务流程超时 |
|
||||
| 专家评分 1.5 分(满分 5) | **是** | 结果异常 | 评分值在合法范围内,属服务质量问题 |
|
||||
| 咨询会话超过 60 分钟 | **是** | 结果异常 | 时长值合法,属服务效率问题 |
|
||||
| 设备超过 3 天未上报数据 | **是** | 结果异常 | 数据本身无异常,属设备离线告警 |
|
||||
| ICU 患者血糖 22 mmol/L | **是** | 结果异常 | 值本身合法,属危急值预警 |
|
||||
|
||||
### 3.3 典型易混淆场景澄清
|
||||
|
||||
**场景一:咨询时长异常**
|
||||
|
||||
研发文档中健康咨询模块的 `exception_type=1`(咨询时长异常 > 60 分钟)被归类为系统脏数据,实为**结果异常**。`duration_minutes` 字段的值 61、120 等在格式和范围内均合法,只是反映了"这个咨询用时很长"这一业务事实——这是服务质量监控指标,不是数据质量问题。
|
||||
|
||||
**场景二:任务状态卡住**
|
||||
|
||||
研发文档中多处出现 `status = 处理中 超过 24 小时` 的规则。若状态字段值本身合法(确实为"处理中"),则属于结果异常(任务卡住);但若状态值与时间戳存在矛盾(如状态=已完成但 end_time 为空),则为脏数据(D04 逻辑冲突)。
|
||||
|
||||
**场景三:评价分数极低**
|
||||
|
||||
评分字段值 1 在 1~5 范围内合法,属于结果异常(服务评价差)。只有当 score 值超出 1~5 范围时,才属于脏数据(D03 取值越界)。
|
||||
|
||||
---
|
||||
|
||||
## 四、数据中台质量校验流程
|
||||
|
||||
### 4.1 整体架构
|
||||
|
||||
系统脏数据的检测由数据中台统一执行,不依赖各业务服务自行实现定时任务。质量校验嵌入在数据中台从业务数据库同步数据的管道中,实现"同步即校验"。
|
||||
|
||||
```
|
||||
┌──────────────┐ CDC/增量同步 ┌────────────────────┐
|
||||
│ 业务数据库 │ ──────────────────> │ 数据中台 │
|
||||
│ (postgreSQL) │ │ │
|
||||
│ │ │ ┌──────────────┐ │
|
||||
│ health_ │ │ │ DQC 规则引擎 │ │
|
||||
│ consult │ │ │ (同步即校验) │ │
|
||||
│ emergency │ │ └──────┬───────┘ │
|
||||
│ exam │ │ │ │
|
||||
│ nutrition │ │ ┌────▼───────┐ │
|
||||
│ monitor │ │ │ 脏数据存储库 │ │
|
||||
│ weight │ │ │ (汇总查询) │ │
|
||||
│ ... │ │ └────────────┘ │
|
||||
└──────────────┘ └────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 校验触发时机
|
||||
|
||||
| 同步模式 | 触发时机 | 适用场景 |
|
||||
|----------|----------|----------|
|
||||
| **CDC 实时同步** | 每捕获一条 INSERT/UPDATE 变更事件,即对该记录执行 DQC 规则校验 | 数据缺失、格式违规、取值越界、逻辑冲突(单行)、枚举非法 |
|
||||
| **增量批次同步** | 每个批次(如每 5 分钟一批)同步完成后,对批次内记录执行跨表校验 | 关联断裂 |
|
||||
| **每日全量对账** | 每日凌晨,对全量/增量数据进行汇总级校验 | 逻辑冲突(汇总不一致)、数据重复 |
|
||||
|
||||
### 4.3 校验管线
|
||||
|
||||
```
|
||||
数据变更事件 (CDC Event)
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ 1. 字段映射 │ 将业务表字段映射为标准 DQC 字段模型
|
||||
└────────┬────────┘
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ 2. 规则匹配 │ 根据「表名.字段名」匹配对应 DQC 规则集
|
||||
└────────┬────────┘
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ 3. 规则执行 │ 逐条执行规则 → 输出 (通过 / 不通过 + 异常详情)
|
||||
└────────┬────────┘
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ 4. 结果路由 │ 通过 → 数据入仓
|
||||
│ │ 不通过 → 写入脏数据表 + 同步告警(可选)
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### 4.4 脏数据记录模型
|
||||
|
||||
校验发现脏数据后,统一写入以下结构的异常记录:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|--------------------|------|------------------------------------------------------------------------|
|
||||
| `id` | bigint | 主键 |
|
||||
| `module` | varchar | 业务板块(health_consult / emergency / exam / nutrition / monitor / weight) |
|
||||
| `dirty_type` | varchar | 脏数据类型编码(D01 ~ D06) |
|
||||
| `table_name` | varchar | 来源表名 |
|
||||
| `table_desc` | varchar | 业务表描述(设备主表、咨询记录表、应急工单表等) |
|
||||
| `field_name` | varchar | 异常字段名(多字段时用逗号分隔) |
|
||||
| `record_id` | varchar | 异常记录的主键/业务编号 |
|
||||
| `abnormal_value` | text | 异常值 |
|
||||
| `rule_description` | text | 触发的规则描述 |
|
||||
| `detected_at` | datetime | 检测时间 |
|
||||
| `data_created_at` | datetime | 异常数据的业务产生时间(来自源表时间戳字段) |
|
||||
| `status` | varchar | 处理状态(待处理 / 已忽略 / 已修复) |
|
||||
|
||||
### 4.5 告警与处置
|
||||
|
||||
- **系统脏数据查询**:在各业务版块下的异常事件-系统脏数据中提供脏查询功能
|
||||
- **实时告警(暂不实现)**:D01~D03 类型(数据缺失、格式违规、取值越界)发现后即时推送告警,通知对应板块的数据负责人
|
||||
- **定时报告(暂不实现)**:D04~D06 类型(逻辑冲突、关联断裂、数据重复)汇总至每日数据质量日报,统一呈现
|
||||
- **处置闭环((暂不实现))**:业务端通过"异常事件 → 系统脏数据"页面查看、筛选、导出,确认后可标记为"已忽略"或修复源数据后自动复检清除
|
||||
|
||||
---
|
||||
|
||||
## 五、各模块检测规则
|
||||
|
||||
> 以下规则按「业务域 → 表 → 规则明细」三层结构组织,每个模块统一格式。
|
||||
|
||||
### 5.1 系统管理
|
||||
|
||||
#### 涉及数据表
|
||||
|
||||
系统管理是平台的基础支撑模块,管理用户、角色、组织架构、字典、配置等核心公共数据。以下仅列出直接影响业务数据完整性的核心校验表。
|
||||
|
||||
| 业务子域 | 核心表 | 关键校验字段 |
|
||||
|----------|--------|-------------|
|
||||
| 用户与角色 | `sys_user`, `sys_user_extend`, `sys_role`, `sys_user_role` | username, workNo, phone, idCard, sex, status, accountStatus, personType, birthday, height, weight, bmi, roleName, roleCode |
|
||||
| 组织机构 | `sys_depart` | departName, orgCode, orgCategory, orgType, status, lng, lat, parentId |
|
||||
| 字典与配置 | `sys_dict`, `sys_dict_item`, `sys_config` | name, code, itemName, itemValue, configKey, configName |
|
||||
|
||||
#### 检测规则
|
||||
|
||||
**sys_user(用户信息)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S01-D01 | 登录账号缺失 | `username` | `IS NULL OR = ''` |
|
||||
| S01-D01 | 工号缺失 | `workNo` | `IS NULL OR = ''` |
|
||||
| S01-D02 | 手机号格式不合法 | `phone` | 不匹配 11 位手机号正则(如 `"888"` 或非数字字符) |
|
||||
| S01-D02 | 身份证号格式不合法 | `idCard` | 长度不为 18 位,或含非法字符,或校验位不通过 |
|
||||
| S01-D03 | 性别枚举越界 | `sex` | `NOT IN (0, 1, 2)`(0=未知, 1=男, 2=女) |
|
||||
| S01-D03 | 员工状态枚举越界 | `status` | `NOT IN (1, 2, 3)`(1=在岗, 2=封存, 3=注销) |
|
||||
| S01-D03 | 账号状态枚举越界 | `accountStatus` | `NOT IN (0, 1)`(0=锁定, 1=激活) |
|
||||
| S01-D03 | 用户类型枚举越界 | `personType` | `NOT IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)` |
|
||||
| S01-D03 | 生日为未来日期 | `birthday` | `birthday > CURRENT_DATE` |
|
||||
| S01-D06 | 工号重复 | `workNo` | 存在多条记录使用同一工号(排除已逻辑删除记录) |
|
||||
|
||||
**sys_role(角色)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S02-D01 | 角色名称缺失 | `roleName` | `IS NULL OR = ''` |
|
||||
| S02-D01 | 角色编码缺失 | `roleCode` | `IS NULL OR = ''` |
|
||||
| S02-D03 | 角色类型枚举越界 | `roleType` | `NOT IN (0, 1)`(0=自定义, 1=系统内置) |
|
||||
| S02-D06 | 角色编码重复 | `roleCode` | 存在多条记录使用同一角色编码 |
|
||||
|
||||
**sys_user_role(用户角色关联)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S03-D05 | 关联用户不存在 | `userId` | 引用的用户不存在 |
|
||||
| S03-D05 | 关联角色不存在 | `roleId` | 引用的角色不存在 |
|
||||
| S03-D06 | 用户角色重复分配 | `userId`, `roleId` | 同一用户被重复分配同一角色 |
|
||||
|
||||
**sys_depart(组织机构)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S04-D01 | 机构名称缺失 | `departName` | `IS NULL OR = ''` |
|
||||
| S04-D01 | 机构编码缺失 | `orgCode` | `IS NULL OR = ''` |
|
||||
| S04-D03 | 机构类别枚举越界 | `orgCategory` | `NOT IN ('1', '2', '3')`(1=公司, 2=组织机构, 3=岗位) |
|
||||
| S04-D03 | 机构类型枚举越界 | `orgType` | `NOT IN ('1', '2')`(1=一级部门, 2=子部门) |
|
||||
| S04-D03 | 状态枚举越界 | `status` | `NOT IN ('0', '1')`(0=不启用, 1=启用) |
|
||||
| S04-D03 | 经纬度超出国内范围 | `lng`, `lat` | `lng < 73 OR lng > 136 OR lat < 4 OR lat > 54`(含 (0,0) 未初始化场景) |
|
||||
| S04-D04 | 父机构指向自身 | `id`, `parentId` | `id = parentId` |
|
||||
| S04-D05 | 关联父机构不存在 | `parentId` | 引用的父机构不存在 |
|
||||
| S04-D06 | 机构编码重复 | `orgCode` | 存在多条记录使用同一机构编码 |
|
||||
|
||||
**sys_dict(字典主表)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S05-D01 | 字典名称缺失 | `name` | `IS NULL OR = ''` |
|
||||
| S05-D01 | 字典编码缺失 | `code` | `IS NULL OR = ''` |
|
||||
| S05-D06 | 字典编码重复 | `code` | 存在多条记录使用同一字典编码 |
|
||||
|
||||
**sys_dict_item(字典项)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S06-D01 | 字典项名称缺失 | `itemName` | `IS NULL OR = ''` |
|
||||
| S06-D01 | 字典项值缺失 | `itemValue` | `IS NULL OR = ''` |
|
||||
| S06-D03 | 字典项状态枚举越界 | `status` | `NOT IN (0, 1)`(0=不启用, 1=启用) |
|
||||
| S06-D05 | 关联字典不存在 | `dictId` | 引用的字典不存在 |
|
||||
| S06-D06 | 同一字典下字典项值重复 | `dictId`, `itemValue` | 同一字典下存在重复的字典项值 |
|
||||
|
||||
**sys_config(参数配置)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S07-D01 | 配置名称缺失 | `configName` | `IS NULL OR = ''` |
|
||||
| S07-D01 | 配置键缺失 | `configKey` | `IS NULL OR = ''` |
|
||||
| S07-D06 | 配置键重复 | `configKey` | 存在多条记录使用同一配置键 |
|
||||
|
||||
**sys_user_extend(用户扩展信息)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| S08-D03 | 身高越界 | `height` | `< 50 OR > 250` (cm) |
|
||||
| S08-D03 | 体重越界 | `weight` | `< 20 OR > 300` (kg) |
|
||||
| S08-D03 | BMI 越界 | `bmi` | `< 10 OR > 80` |
|
||||
| S08-D05 | 关联用户不存在 | `userId` | 引用的用户不存在 |
|
||||
|
||||
---
|
||||
|
||||
### 5.2 健康咨询
|
||||
|
||||
#### 涉及数据表
|
||||
|
||||
| 表名 | 说明 | 核心校验字段 |
|
||||
|------|------|-------------|
|
||||
| `con_consult` | 咨询会话主表 | consult_no, consult_type, content_status, session_status, start_time, end_time, duration_minutes, cost, expert_id, member_id |
|
||||
| `con_expert` | 专家信息表 | expert_no, expert_type, overall_merit, response_rate, reg_date, off_date, hospital_id, dept_id |
|
||||
| `con_evaluate` | 咨询评价表 | score, consult_id, expert_id |
|
||||
| `con_family_member` | 家庭成员表 | member_name, birthday, height, weight, sex |
|
||||
| `con_medical_record` | 病历档案表 | medical_describe, duration_type |
|
||||
| `con_im_message` | IM 消息记录表 | msg_content, msg_type, consult_id |
|
||||
| `con_expert_schedule_rule` | 专家排班规则表 | week_day, period, start_time, end_time, capacity |
|
||||
| `con_settle_main` | 结算主表 | settle_status, com_fee_per_month |
|
||||
|
||||
#### 检测规则
|
||||
|
||||
**con_consult(咨询会话)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| C01-D01 | 咨询单号缺失 | `consult_no` | `IS NULL OR = ''` |
|
||||
| C01-D03 | 咨询类型枚举越界 | `consult_type` | `NOT IN (1, 2)` |
|
||||
| C01-D03 | 内容状态枚举越界 | `content_status` | `NOT IN (1,2,3,4,5,6,7,8)` |
|
||||
| C01-D03 | 咨询费用为负数 | `cost` | `< 0` |
|
||||
| C01-D04 | 结束时间早于开始时间 | `start_time`, `end_time` | 结束时间早于开始时间 |
|
||||
| C01-D04 | 会话进行中但已有结束时间 | `session_status`, `end_time` | 会话状态为进行中但已有结束时间 |
|
||||
| C01-D04 | 内容已完成但无结束时间 | `content_status`, `end_time` | 内容已完成但无结束时间 |
|
||||
| C01-D04 | 已拒绝但无拒绝原因 | `content_status`, `reject_reason` | 已拒绝但未填写拒绝原因 |
|
||||
| C01-D05 | 关联专家不存在 | `expert_id` | 引用的专家不存在 |
|
||||
| C01-D05 | 关联咨询人不存在 | `member_id` | 引用的家庭成员不存在 |
|
||||
|
||||
**con_expert(专家信息)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| C02-D01 | 专家编号缺失 | `expert_no` | `IS NULL OR = ''` |
|
||||
| C02-D03 | 专家类型枚举越界 | `expert_type` | `NOT IN (1, 2, 3)` |
|
||||
| C02-D03 | 综合评分越界 | `overall_merit` | `< 0 OR > 5` |
|
||||
| C02-D03 | 回复率越界 | `response_rate` | `< 0 OR > 100` |
|
||||
| C02-D04 | 离职日期早于入职日期 | `reg_date`, `off_date` | 离职日期早于入职日期 |
|
||||
| C02-D05 | 关联医院不存在 | `hospital_id` | 引用的医院不存在 |
|
||||
| C02-D05 | 关联科室不存在 | `dept_id` | 引用的科室不存在 |
|
||||
|
||||
**con_evaluate(咨询评价)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| C03-D03 | 评分越界 | `score` | `< 0 OR > 5` |
|
||||
| C03-D05 | 关联咨询不存在 | `consult_id` | 引用的咨询记录不存在 |
|
||||
| C03-D05 | 关联专家不存在 | `expert_id` | 引用的专家不存在 |
|
||||
|
||||
**con_family_member(家庭成员)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| C04-D03 | 身高越界 | `height` | `< 50 OR > 250` |
|
||||
| C04-D03 | 体重越界 | `weight` | `< 20 OR > 300` |
|
||||
| C04-D03 | 性别枚举越界 | `sex` | `NOT IN (1, 2)` |
|
||||
| C04-D03 | 生日为未来日期 | `birthday` | `birthday > CURRENT_DATE` |
|
||||
|
||||
**con_medical_record(病历档案)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| C05-D01 | 病情描述缺失 | `medical_describe` | `IS NULL OR = ''` |
|
||||
| C05-D03 | 持续时间类型枚举越界 | `duration_type` | `NOT IN (1, 2, 3, 4)` |
|
||||
|
||||
**con_im_message(IM 消息)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| C06-D01 | 消息内容缺失(非撤回消息) | `msg_content` | 消息内容为空且消息类型非撤回 |
|
||||
| C06-D03 | 消息类型枚举越界 | `msg_type` | `NOT IN (1, 2, 3, 4)` |
|
||||
| C06-D05 | 关联咨询不存在 | `consult_id` | 引用的咨询记录不存在 |
|
||||
|
||||
**con_expert_schedule_rule(排班规则)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| C07-D03 | 星期枚举越界 | `week_day` | `NOT IN (1,2,3,4,5,6,7)` |
|
||||
| C07-D03 | 时段枚举越界 | `period` | `NOT IN (1, 2, 3, 4)` |
|
||||
| C07-D03 | 接诊人数为负数 | `capacity` | `< 0` |
|
||||
| C07-D04 | 排班结束时间早于开始时间 | `start_time`, `end_time` | `end_time < start_time` |
|
||||
|
||||
---
|
||||
|
||||
### 5.3 应急就医
|
||||
|
||||
#### 涉及数据表
|
||||
|
||||
| 表名 | 说明 | 核心校验字段 |
|
||||
|------|------|-------------|
|
||||
| `em_emergency_order` | 应急工单 | order_no, status, location_lat, location_lng, closed_at |
|
||||
| `em_call_record` | 通话记录 | incoming_phone, match_status, order_id, begin_time, end_time, answer_status, duration |
|
||||
| `em_aed_device` | AED 设备 | battery_level, battery_status |
|
||||
| `em_aed_deploy_point` | AED 部署点位 | longitude, latitude |
|
||||
| `em_aed_latest` | AED 最新状态 | battery_power |
|
||||
| `em_aed_maintenance` | AED 维护记录 | maintenance_date |
|
||||
| `em_user_profile` | 应急人员档案 | cert_number, license_number, station_status |
|
||||
| `em_ambulance` | 救护车 | plate_no, status |
|
||||
| `em_emergency_center` | 应急中心 | longitude, latitude, center_phone, status |
|
||||
| `em_emergency_center_call_record` | 应急中心通话 | call_id, employee_id, begin_time, end_time |
|
||||
| `em_emergency_center_call_join` | 通话参与人 | employee_id, call_record_id |
|
||||
|
||||
#### 检测规则
|
||||
|
||||
**em_call_record(通话记录)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E01-D02 | 来电号码格式不合法 | `incoming_phone` | 不匹配手机号/座机号正则 |
|
||||
| E01-D03 | 通话时长负数 | `duration` | `< 0` |
|
||||
| E01-D04 | 结束时间早于开始时间 | `begin_time`, `end_time` | 结束时间早于开始时间 |
|
||||
| E01-D04 | 已接听但通话时长为 0 | `answer_status`, `duration` | 已接听但通话时长为零 |
|
||||
| E01-D05 | 关联工单不存在 | `order_id` | 引用的应急工单不存在 |
|
||||
|
||||
**em_aed_device / em_aed_latest(AED 设备)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E02-D03 | 电池电量百分比越界 | `battery_level` | 电池电量百分比不在 0~100 范围内 |
|
||||
| E02-D03 | 电池状态枚举越界 | `battery_status` | 不在预定义电池状态枚举集合内 |
|
||||
|
||||
**em_aed_deploy_point(AED 部署点位)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E03-D03 | GPS 坐标超出国内范围 | `longitude`, `latitude` | `longitude < 73 OR longitude > 136 OR latitude < 4 OR latitude > 54` |
|
||||
| E03-D01 | GPS 坐标为 (0, 0) 或 NULL | `longitude`, `latitude` | GPS 坐标为空值或为 (0, 0) |
|
||||
| E03-D05 | 关联应急中心不存在 | 中心关联字段 | 引用的应急中心不存在 |
|
||||
|
||||
**em_aed_maintenance(AED 维护记录)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E04-D03 | 维护日期为未来日期 | `maintenance_date` | `maintenance_date > CURRENT_DATE` |
|
||||
| E04-D01 | 设备缺少维护记录 | — | 设备已部署超过阈值天数且无维护记录 |
|
||||
|
||||
**em_emergency_order(应急工单)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E05-D01 | 工单编号缺失 | `order_no` | `IS NULL OR = ''` |
|
||||
| E05-D03 | GPS 坐标超出国内范围 | `location_lat`, `location_lng` | 同 E03-D03 |
|
||||
| E05-D04 | 已关闭但无关闭时间 | `status`, `closed_at` | 已关闭但无关闭时间 |
|
||||
|
||||
**em_user_profile(应急人员档案)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E06-D01 | 证书编号缺失 | `cert_number` | `IS NULL OR = ''` |
|
||||
| E06-D03 | 驻场状态枚举越界 | `station_status` | 不在预定义状态枚举集合内 |
|
||||
|
||||
**em_ambulance(救护车)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E07-D01 | 车牌号缺失 | `plate_no` | `IS NULL OR = ''` |
|
||||
| E07-D03 | 车辆状态枚举越界 | `status` | 不在预定义状态枚举集合内 |
|
||||
|
||||
**em_emergency_center_call_record(应急中心通话)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| E08-D04 | 结束时间早于开始时间 | `begin_time`, `end_time` | 结束时间早于开始时间 |
|
||||
| E08-D01 | 通话ID缺失 | `call_id` | `IS NULL OR = ''` |
|
||||
|
||||
---
|
||||
|
||||
### 5.4 健康体检
|
||||
|
||||
#### 涉及数据表
|
||||
|
||||
| 表名 | 说明 | 核心校验字段 |
|
||||
|------|------|-------------|
|
||||
| `exam_appointment` | 体检预约 | phone, employee_id, appointment_date, hospital_id, status |
|
||||
| `employee_archive` | 员工档案 | id_card, name, gender, birth_date |
|
||||
| `exam_report` | 体检报告 | report_status, employee_id, exam_date, hospital_id |
|
||||
| `exam_item_result` | 体检项目结果 | result_value, item_code, reference_range, is_abnormal, exam_report_id |
|
||||
| `exam_standard_item` | 体检基本项目 | item_code, item_name, is_key_indicator, has_reference |
|
||||
| `exam_hospital_item` | 医院体检项目 | hospital_id, item_code, linked_standard_item_id |
|
||||
| `exam_hospital` | 医院信息 | hospital_name, address, enable_occupational |
|
||||
| `exam_report_template` | 报告模板 | template_name, version, status |
|
||||
| `exam_plan` | 体检计划 | plan_name, year, date_range, hospital_id, status |
|
||||
| `exam_quota` | 体检名额 | plan_id, unit_id, total_quota, used_quota |
|
||||
|
||||
#### 检测规则
|
||||
|
||||
**exam_appointment(体检预约)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H01-D02 | 手机号格式不合法 | `phone` | 不匹配 11 位手机号正则(如 `"888"` 或非数字字符) |
|
||||
| H01-D01 | 预约员工ID缺失 | `employee_id` | `IS NULL OR = ''` |
|
||||
| H01-D03 | 预约日期为过去年份(录入错误) | `appointment_date` | 年份早于 2020 或晚于当前年份+2 |
|
||||
| H01-D05 | 关联医院不存在 | `hospital_id` | 引用的医院不存在 |
|
||||
|
||||
**employee_archive(员工档案)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H02-D02 | 身份证号格式不合法 | `id_card` | 长度不为 18 位,或含非法字符,或校验位不通过 |
|
||||
| H02-D01 | 姓名缺失 | `name` | `IS NULL OR = ''` |
|
||||
| H02-D03 | 性别枚举越界 | `gender` | `NOT IN (1, 2)` 或 `NOT IN ('男', '女')` |
|
||||
| H02-D03 | 出生日期为未来日期 | `birth_date` | `birth_date > CURRENT_DATE` |
|
||||
|
||||
**exam_report(体检报告)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H03-D03 | 报告状态枚举越界 | `report_status` | 不在预定义报告状态枚举集合内 |
|
||||
| H03-D05 | 关联员工不存在 | `employee_id` | 引用的员工档案不存在 |
|
||||
| H03-D04 | 报告状态为"已生成"但无结果明细 | `report_status` ↔ `exam_item_result` | 报告状态为已生成但无关联的检查结果明细 |
|
||||
|
||||
**exam_item_result(体检项目结果)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H04-D01 | 检查结果值为空 | `result_value` | `IS NULL OR = ''` |
|
||||
| H04-D03 | 结果值为负数(仅适用于不应为负的指标) | `result_value` | `result_value < 0` 且项目类型非偏移量类指标 |
|
||||
| H04-D05 | 关联体检项目不存在 | `item_code` | 引用的标准体检项目不存在 |
|
||||
| H04-D05 | 关联报告不存在 | `exam_report_id` | 引用的体检报告不存在 |
|
||||
| H04-D04 | 异常标记与结果值矛盾 | `is_abnormal`, `result_value`, `reference_range` | 标记为异常但结果值在参考范围内,或标记为正常但结果值明显超出参考范围 |
|
||||
|
||||
**exam_standard_item(体检基本项目)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H05-D01 | 项目编码缺失 | `item_code` | `IS NULL OR = ''` |
|
||||
| H05-D01 | 项目名称缺失 | `item_name` | `IS NULL OR = ''` |
|
||||
| H05-D06 | 项目编码重复 | `item_code` | 存在多条记录使用同一项目编码 |
|
||||
|
||||
**exam_hospital_item(医院体检项目)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H06-D05 | 关联标准项目不存在 | `linked_standard_item_id` | 引用的标准体检项目不存在 |
|
||||
| H06-D05 | 关联医院不存在 | `hospital_id` | 引用的医院不存在 |
|
||||
|
||||
**exam_report_template(报告模板)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H07-D01 | 模板名称缺失 | `template_name` | `IS NULL OR = ''` |
|
||||
| H07-D03 | 模板状态枚举越界 | `status` | `NOT IN (0, 1)`(0=无效, 1=有效) |
|
||||
|
||||
**exam_plan(体检计划)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H08-D04 | 计划结束日期早于开始日期 | `date_range` (start, end) | `end_date < start_date` |
|
||||
| H08-D05 | 关联医院不存在 | `hospital_id` | 引用的医院不存在 |
|
||||
|
||||
**exam_quota(体检名额)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| H09-D03 | 名额总数为负数 | `total_quota` | `< 0` |
|
||||
| H09-D03 | 已用名额大于总数 | `used_quota` | `used_quota > total_quota` |
|
||||
| H09-D05 | 关联计划不存在 | `plan_id` | 引用的体检计划不存在 |
|
||||
|
||||
---
|
||||
|
||||
### 5.5 营养管理
|
||||
|
||||
#### 涉及数据表
|
||||
|
||||
营养管理是系统中表数量最多的模块。以下按业务子域列出核心校验表。
|
||||
|
||||
| 业务子域 | 核心表 | 关键校验字段 |
|
||||
|----------|--------|-------------|
|
||||
| 用户档案 | `nut_user`, `nut_user_profile` | phone, bmi, height, weight, birthday, health_goal, dietary_restrictions |
|
||||
| 食品管理 | `nut_food`, `nut_food_composition`, `nut_food_nutri`, `nut_food_spec` | price, nutrition_info, value_per_100g, weight |
|
||||
| 食谱管理 | `nut_recipe`, `nut_recipe_food` | total_calories, nutrition_summary, food_id, portion |
|
||||
| 订餐管理 | `nut_order`, `nut_order_item` | total_amount, status, order_type, quantity, price, subtotal |
|
||||
| 原材料 | `nut_mater_base`, `nut_raw_inbound` | price, unit, quantity, weight, supplier_id |
|
||||
| 库存 | `nut_sup_inventory`, `nut_sup_inventory_flow` | quantity, qty, current_qty_after |
|
||||
| 生产 | `nut_prod_combo_task`, `nut_prod_qc_sample`, `nut_prod_serve_record` | task_no, plan_date, status, qc_status |
|
||||
| 算法 | `nut_algo_personal`, `nut_algo_mass` | user_id, 营养结果字段 |
|
||||
| 农场 | `nut_farm_plot`, `nut_farm_crop_batch`, `nut_farm_harvest`, `nut_farm_livestock_batch` | area, plant_date, expected_harvest, quantity, count |
|
||||
| 设备 | `nut_meter_reading` | 读数合理性 |
|
||||
|
||||
#### 检测规则
|
||||
|
||||
**nut_user / nut_user_profile(用户档案)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N01-D01 | 手机号为空 | `phone` | `IS NULL OR = ''` |
|
||||
| N01-D03 | BMI 值越界 | `bmi` | `< 10 OR > 80` |
|
||||
| N01-D03 | 身高越界 | `height` | `< 50 OR > 250` |
|
||||
| N01-D03 | 体重越界 | `weight` | `< 20 OR > 300` |
|
||||
| N01-D04 | 计算年龄为负数 | `birthday` | 生日晚于当前日期 |
|
||||
| N01-D06 | 同一 user_id 存在多条档案记录 | `user_id` | 同一用户存在多条档案记录 |
|
||||
|
||||
**nut_food / nut_food_composition / nut_food_nutri / nut_food_spec(食品管理)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N02-D03 | 价格为负数 | `price` | `< 0` |
|
||||
| N02-D03 | 每 100g 营养值为负数 | `value_per_100g` | `< 0` |
|
||||
| N02-D01 | 营养信息JSON为空 | `nutrition_info` | `IS NULL OR = '' OR = '{}'` |
|
||||
| N02-D02 | 营养信息JSON解析失败 | `nutrition_info` | JSON 格式不合法,无法解析 |
|
||||
| N02-D03 | 份量重量为负数或零 | `weight` | `<= 0` |
|
||||
|
||||
**nut_recipe / nut_recipe_food(食谱管理)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N03-D01 | 总热量为空 | `total_calories` | `IS NULL` |
|
||||
| N03-D02 | 营养汇总JSON格式非法 | `nutrition_summary` | JSON 格式不合法,无法解析 |
|
||||
| N03-D05 | 食谱引用的食材ID不存在 | `food_id` | 引用的食品不存在 |
|
||||
|
||||
**nut_order / nut_order_item(订餐管理)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N04-D03 | 订单金额为负数 | `total_amount` | `< 0` |
|
||||
| N04-D03 | 单次订餐份数超出上限 | `quantity` | `quantity > 系统设定的最大份数` |
|
||||
| N04-D03 | 单价为负数 | `price` | `< 0` |
|
||||
| N04-D04 | 订单金额与明细小计之和不一致 | `total_amount` ↔ `SUM(subtotal)` | 订单金额与明细小计之和不相等 |
|
||||
|
||||
**nut_mater_base / nut_raw_inbound / nut_sup_inventory / nut_sup_inventory_flow(原材料与库存)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N05-D03 | 入库数量为负数或零 | `quantity` | `<= 0` |
|
||||
| N05-D03 | 入库重量为负数 | `weight` | `< 0` |
|
||||
| N05-D03 | 库存数量为负数 | `quantity` | `< 0` |
|
||||
| N05-D04 | 库存流水余额与当前库存不一致 | `current_qty_after` ↔ `quantity` | 库存流水余额与当前库存数量不相等 |
|
||||
| N05-D05 | 原材料ID在原料库中不存在 | `mater_id` | 引用的原材料不存在 |
|
||||
| N05-D05 | 供应商ID不存在 | `supplier_id` | 引用的供应商不存在 |
|
||||
|
||||
**nut_prod_combo_task / nut_prod_qc_sample / nut_prod_serve_record(健康生产)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N06-D02 | 生产批次号含非法字符 | `task_no` | 不匹配批次号正则 |
|
||||
| N06-D04 | 生产任务完成但无供餐记录 | `status` ↔ `nut_prod_serve_record` | 生产任务已完成但无关联供餐记录 |
|
||||
| N06-D01 | 质检样品状态为"留样中"超过阈值天数 | `qc_status`, `sample_date` | 留样中状态持续超过阈值天数 |
|
||||
| N06-D03 | 计划日期为未来年份 | `plan_date` | 年份超出合理范围 |
|
||||
|
||||
**nut_algo_personal / nut_algo_mass(算法与AI)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N07-D06 | 同一用户同日存在多条分析记录 | `user_id` + 日期 | 同一用户同日存在多条分析记录 |
|
||||
| N07-D03 | 营养素计算结果超出合理范围 | 营养结果字段 | 各营养素值 < 0 或超过人体每日上限的 N 倍 |
|
||||
|
||||
**nut_farm_plot / nut_farm_crop_batch / nut_farm_harvest / nut_farm_livestock_batch(农场)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| N08-D03 | 地块面积为负数 | `area` | `< 0` |
|
||||
| N08-D04 | 预计采收日期早于种植日期 | `plant_date`, `expected_harvest` | `expected_harvest < plant_date` |
|
||||
| N08-D03 | 采收数量为负数 | `quantity` | `< 0` |
|
||||
| N08-D03 | 牲畜数量为负数 | `count` | `< 0` |
|
||||
|
||||
---
|
||||
|
||||
### 5.6 健康监测
|
||||
|
||||
#### 涉及数据表
|
||||
|
||||
| 表名 | 说明 | 核心校验字段 |
|
||||
|------|------|-------------|
|
||||
| `mon_device` | 可穿戴设备主表 | device_code, bind_status, bind_user_id, online_status, last_data_time |
|
||||
| `mon_device_config` | 设备监测配置 | threshold_min, threshold_max, upload_frequency |
|
||||
| `mon_bind_record` | 设备绑定/解绑记录 | bind_date, unbind_date |
|
||||
| `mon_daily_stats_heart_rate` | 心率日统计 | hr_max, hr_min, hr_avg, silence_hr_avg |
|
||||
| `mon_daily_stats_spo2` | 血氧日统计 | spo2_max, spo2_min, spo2_avg |
|
||||
| `mon_daily_stats_temperature` | 体温日统计 | temp_max, temp_min, temp_avg |
|
||||
| `mon_daily_stats_blood_pressure` | 血压日统计 | systolic_max, systolic_min, diastolic_max, diastolic_min |
|
||||
| `mon_daily_stats_sleep` | 睡眠日统计 | total_min, deep_min, score |
|
||||
| `mon_data_heart_rate` | 心率原始数据 | data_value |
|
||||
| `mon_data_spo2` | 血氧原始数据 | data_value |
|
||||
| `mon_data_temperature` | 体温原始数据 | data_value |
|
||||
| `mon_data_blood_pressure` | 血压原始数据 | systolic_value, diastolic_value |
|
||||
| `mon_data_gps` | GPS 原始数据 | longitude, latitude |
|
||||
| `mon_data_ecg` | 心电原始数据 | avg_heart_rate, data_points_url |
|
||||
| `mon_survey_answer_record` | 问卷回答记录 | user_id, survey_id, answer_time |
|
||||
| 环境监测各表 | 室内/室外/花粉/水质 | 温度、PM2.5、pH、read_time、meter_code |
|
||||
|
||||
#### 检测规则
|
||||
|
||||
**mon_device(设备主表)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M01-D01 | 设备编码缺失 | `device_code` | `IS NULL OR = ''` |
|
||||
| M01-D03 | 绑定状态枚举越界 | `bind_status` | 不在预定义枚举集合内 |
|
||||
| M01-D03 | 在线状态枚举越界 | `online_status` | 不在预定义枚举集合内 |
|
||||
| M01-D04 | 设备在线但最后上报时间为未来 | `online_status`, `last_data_time` | 设备在线但最后数据上报时间为未来时间 |
|
||||
|
||||
**mon_device_config(设备配置)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M02-D03 | 阈值下限大于阈值上限 | `threshold_min`, `threshold_max` | `threshold_min > threshold_max` |
|
||||
| M02-D03 | 上报频率为负数或零 | `upload_frequency` | `<= 0` |
|
||||
|
||||
**mon_bind_record(绑定记录)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M03-D04 | 解绑日期早于绑定日期 | `bind_date`, `unbind_date` | 解绑日期早于绑定日期 |
|
||||
| M03-D02 | 绑定日期格式非法 | `bind_date` | 无法解析为有效日期 |
|
||||
|
||||
**mon_data_heart_rate / mon_data_spo2 / mon_data_temperature / mon_data_blood_pressure / mon_data_ecg(穿戴原始数据)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M04-D03 | 心率值越界 | `data_value` | `< 20 OR > 300` (bpm) |
|
||||
| M04-D03 | 血氧值越界 | `data_value` | `< 50 OR > 100` (%) |
|
||||
| M04-D03 | 体温值越界 | `data_value` | `< 30 OR > 45` (℃) |
|
||||
| M04-D03 | 收缩压越界 | `systolic_value` | `< 50 OR > 300` (mmHg) |
|
||||
| M04-D03 | 舒张压越界 | `diastolic_value` | `< 30 OR > 200` (mmHg) |
|
||||
| M04-D04 | 收缩压低于舒张压 | `systolic_value`, `diastolic_value` | `systolic_value < diastolic_value` |
|
||||
| M04-D06 | 同一设备同一时间点重复数据 | `device_id` + `data_time` | 同一设备同一时间点存在多条数据 |
|
||||
| M04-D02 | 心电数据文件URL不可达 | `data_points_url` | URL格式非法或指向不存在资源 |
|
||||
|
||||
**mon_data_gps(GPS 数据)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M05-D03 | GPS 坐标超出国内范围 | `longitude`, `latitude` | `longitude < 73 OR longitude > 136 OR latitude < 4 OR latitude > 54` |
|
||||
|
||||
**mon_daily_stats_heart_rate / mon_daily_stats_spo2 / mon_daily_stats_temperature / mon_daily_stats_blood_pressure / mon_daily_stats_sleep(日统计聚合数据)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M06-D04 | 最大心率低于最小心率 | `hr_max`, `hr_min` | `hr_max < hr_min` |
|
||||
| M06-D04 | 最大收缩压低于最小收缩压 | `systolic_max`, `systolic_min` | `systolic_max < systolic_min` |
|
||||
| M06-D04 | 最大舒张压低于最小舒张压 | `diastolic_max`, `diastolic_min` | `diastolic_max < diastolic_min` |
|
||||
| M06-D04 | 静息心率高于平均心率 | `silence_hr_avg`, `hr_avg` | `silence_hr_avg > hr_avg` |
|
||||
| M06-D03 | 睡眠总时长越界 | `total_min` | `< 0 OR > 1440` |
|
||||
| M06-D04 | 深睡时长大于总时长 | `deep_min`, `total_min` | `deep_min > total_min` |
|
||||
|
||||
**mon_survey_answer_record / mon_survey_activity(调查问卷)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M07-D04 | 回答时间早于活动发布时间 | `answer_time` ↔ `mon_survey_activity.publish_time` | `answer_time < publish_time` |
|
||||
| M07-D06 | 同一用户同一问卷多条回答 | `user_id`, `survey_id` | 同一用户对同一问卷存在多条回答 |
|
||||
|
||||
**mon_env_data_indoor / mon_env_data_outdoor / mon_env_data_pollen / mon_env_data_water(环境监测)**
|
||||
|
||||
| 编码 | 规则描述 | 涉及字段 | 判定逻辑 |
|
||||
|------|----------|----------|----------|
|
||||
| M08-D03 | PM2.5 值为负数 | PM2.5字段 | `< 0` |
|
||||
| M08-D03 | pH 值越界 | `ph` | `< 0 OR > 14` |
|
||||
| M08-D03 | 环境温度超出设备量程 | 温度字段 | 超出传感器标定量程范围 |
|
||||
| M08-D05 | 环境数据关联仪表不存在 | `meter_code` | 引用的环境监测仪表不存在 |
|
||||
|
||||
---
|
||||
|
||||
## 六、附录
|
||||
|
||||
### 6.1 脏数据类型编码速查
|
||||
|
||||
| 编码 | 名称 | 一句话描述 |
|
||||
|------|------|--------------|
|
||||
| D01 | 数据缺失 | 该有的值没有 |
|
||||
| D02 | 格式违规 | 数据值的形态不对 |
|
||||
| D03 | 取值越界 | 值的量级不对 |
|
||||
| D04 | 逻辑冲突 | 多个值互相矛盾 |
|
||||
| D05 | 关联断裂 | 外键指向了不存在的记录 |
|
||||
| D06 | 数据重复 | 本应唯一的记录出现了多条 |
|
||||
|
||||
### 6.2 规则编号说明
|
||||
|
||||
规则编号格式:`{模块前缀}{序号}-{脏数据类型编码}`
|
||||
|
||||
| 模块 | 前缀 |
|
||||
|------|------|
|
||||
| 健康咨询 | C (Consult) |
|
||||
| 应急就医 | E (Emergency) |
|
||||
| 健康体检 | H (Health Checkup) |
|
||||
| 营养管理 | N (Nutrition) |
|
||||
| 健康监测 | M (Monitor) |
|
||||
| 系统管理 | S (System) |
|
||||
|
||||
示例:`C01-D03` = 健康咨询模块第 1 组规则,脏数据类型为 D03(取值越界)。
|
||||
|
||||
### 6.3 各模块规则数量统计
|
||||
|
||||
| 模块 | D01 | D02 | D03 | D04 | D05 | D06 | 合计 |
|
||||
|------|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|
||||
| 系统管理 | 12 | 2 | 14 | 1 | 5 | 7 | **41** |
|
||||
| 健康咨询 | 3 | 0 | 12 | 5 | 8 | 0 | **28** |
|
||||
| 应急就医 | 5 | 2 | 10 | 4 | 3 | 0 | **24** |
|
||||
| 健康体检 | 6 | 2 | 9 | 5 | 9 | 2 | **33** |
|
||||
| 营养管理 | 4 | 3 | 14 | 5 | 4 | 2 | **32** |
|
||||
| 健康监测 | 1 | 2 | 14 | 9 | 1 | 3 | **30** |
|
||||
| **合计** | **31** | **11** | **73** | **29** | **30** | **14** | **188** |
|
||||
Reference in New Issue
Block a user