feat:数据质量筛选规则需求整理
This commit is contained in:
@@ -0,0 +1,809 @@
|
||||
# 异常数据分析
|
||||
|
||||
> **文档目的**:根据业务表结构,预先梳理各模块可能产生脏数据的数据库表及对应的脏数据类型,供后续脏数据检测开发使用。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
- [一、脏数据类型汇总](#一脏数据类型汇总)
|
||||
- [二、健康评估](#二健康评估)
|
||||
- [2.1 涉及数据库表](#21-涉及数据库表)
|
||||
- [2.2 系统脏数据检测规则](#22-系统脏数据检测规则)
|
||||
- [2.3 检测频率建议](#23-检测频率建议)
|
||||
- [三、健康咨询](#三健康咨询)
|
||||
- [3.1 涉及数据库表](#31-涉及数据库表)
|
||||
- [3.2 系统脏数据检测规则](#32-系统脏数据检测规则)
|
||||
- [3.3 现有后端实现评估](#33-现有后端实现评估)
|
||||
- [3.4 检测频率建议](#34-检测频率建议)
|
||||
- [四、应急就医](#四应急就医)
|
||||
- [4.1 涉及数据库表](#41-涉及数据库表)
|
||||
- [4.2 系统脏数据检测规则](#42-系统脏数据检测规则)
|
||||
- [4.3 检测频率建议](#43-检测频率建议)
|
||||
- [五、营养管理](#五营养管理)
|
||||
- [5.1 涉及数据库表](#51-涉及数据库表)
|
||||
- [5.2 系统脏数据检测规则](#52-系统脏数据检测规则)
|
||||
- [5.3 现有后端实现评估](#53-现有后端实现评估)
|
||||
- [5.4 检测频率建议](#54-检测频率建议)
|
||||
- [六、健康监测](#六健康监测)
|
||||
- [6.1 涉及数据库表](#61-涉及数据库表)
|
||||
- [6.2 系统脏数据检测规则](#62-系统脏数据检测规则)
|
||||
- [6.3 检测频率建议](#63-检测频率建议)
|
||||
|
||||
---
|
||||
|
||||
## 一、脏数据类型汇总
|
||||
|
||||
| 脏数据类型 | 健康评估 | 健康咨询 | 应急就医 | 营养管理 | 健康监测 |
|
||||
|------------|:--:|:--:|:--:|:--:|:--:|
|
||||
| 数据缺失 | ✅ | ✅ | — | ✅ | ✅ |
|
||||
| 格式错误 | ✅ | ✅ | — | ✅ | ✅ |
|
||||
| 逻辑矛盾 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| 重复数据 | ✅ | — | — | ✅ | ✅ |
|
||||
| 范围越界 | ✅ | ✅ | — | ✅ | ✅ |
|
||||
| 关联缺失 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| 状态异常 | ✅ | ✅ | ✅ | — | — |
|
||||
| 非法数据 | — | — | ✅ | — | — |
|
||||
| 异常坐标 | — | — | ✅ | — | — |
|
||||
|
||||
---
|
||||
|
||||
## 二、健康评估
|
||||
|
||||
> **后端服务**:`platform-assessment`(端口 24803)| **原型参考**:评估模块原型使用摹刀独立设计
|
||||
>
|
||||
> **开发状态**:⚠️ 后端已有 `AssDataAbnormalController` 占位(返回硬编码 mock 数据)。
|
||||
|
||||
健康评估模块对员工进行多维度健康评估,包括风险评估、心理评估、规律起居评估、人群分类等。
|
||||
|
||||
### 2.1 涉及数据库表
|
||||
|
||||
评估模块共 21 张业务表,按子域分类如下。
|
||||
|
||||
#### 风险评估(7+2 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `ass_risk_evaluation` | 风险评估主表(问卷+自动双模式) | 高 — `eval_source`(评估来源:1=问卷/2=自动)、`status`(任务状态:1=成功/2=处理中/3=失败)、`is_exception`(是否异常:0=否/1=是)、`user_id`(用户ID) |
|
||||
| `ass_risk_result` | 风险评估结果(疾病等级、BMI、生活习惯标记) | 高 — `bmi`(BMI值)、`sbp`(收缩压)/`dbp`(舒张压)、`fasting_bg`(空腹血糖)、`diabetes_level`(糖尿病等级)、`bmi_mark`(BMI标记格式) |
|
||||
| `ass_risk_evaluation_statistics` | 风险评估统计(按用户/年份汇总) | 中 — `statics_num`(统计评估次数)、`exception_num`(异常评估次数) |
|
||||
| `ass_risk_factor` | 风险因素明细 | 中 — `current_value`(当前检测值)、`reference_range`(参考范围)、`is_abnormal`(是否异常) |
|
||||
| `ass_risk_questionnaire_info` | 问卷基础信息(病史、生活方式) | 高 — `height`(身高cm)/`weight`(体重kg)/`waist_line`(腰围cm)、`smoking_status`(吸烟状态:1-3) |
|
||||
| `ass_risk_diet_sports_prescription` | 饮食运动处方 | 中 — `f_elements`(食物元素格式)、`aerobic_*`(有氧运动)、`strength_*`(力量训练)、`flexibility_*`(柔韧训练) |
|
||||
| `ass_risk_hms_log` | 第三方HMS接口调用日志 | 低 — XML 格式完整性 |
|
||||
| `ass_risk_request_cache` | MD5请求去重缓存 | 低 — 缓存过期/碰撞 |
|
||||
| `ass_risk_food_element` | 食物营养元素字典 | 低 — 字典数据完整性 |
|
||||
|
||||
#### 心理评估(3 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `ass_psychology` | 心理评估主表(综合/压力/焦虑/抑郁) | 高 — `type`(评估类型:1=综合/2=压力/3=焦虑/4=抑郁)、`grade`(评估得分)、`phy_grade_level`(健康等级)、`is_exception`(是否异常)、`status`(任务状态) |
|
||||
| `ass_psychology_statistics` | 心理评估统计 | 中 — 统计值与实际记录数一致性 |
|
||||
| `ass_influence_factor` | 心理影响因素评估 | 中 — 因子数据完整性 |
|
||||
|
||||
#### 规律起居(2 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `ass_daily_routine_online` | 在线穿戴数据评估(睡眠/运动/心率/血氧/压力) | 高 — `sleep_hour`(睡眠时长分钟)、`sport_minute`(运动时长分钟)、`resting_heart_rate`(静息心率bpm)、`oxygen_saturation`(血氧饱和度%)、`week_start_date`(周开始日期)/`week_end_date`(周结束日期) |
|
||||
| `ass_daily_routine_paper` | 问卷规律起居(体力活动/睡眠/上网) | 中 — `sport_value`(运动值)、`sleep_value`(睡眠值)、`time_of_net_value`(上网时长)、`questions_id`(关联问卷ID) |
|
||||
|
||||
#### 人群分类(4 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `ass_group_user` | 人群分类主表(A/B/C/D/E五类) | 高 — `user_group`(人群分类枚举:A/B/C/D/E)、`audit_status`(审核状态:0-2)、`is_archived`(是否归档)、`latest_assessment_date`(最近评估日期) |
|
||||
| `ass_group_user_detail` | 人群分类明细(疾病/体检项) | 中 — `detail_type`(明细类型:A/B/C/D)、`item_code`(项目编码)、`risk_level_flag`(风险等级标记) |
|
||||
| `ass_group_user_change_his` | 分类变更历史 | 低 — 变更记录完整性 |
|
||||
| `ass_group_user_audit_his` | 分类审核历史 | 低 — 审核记录完整性 |
|
||||
|
||||
#### 共享/基础(3 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `ass_questions` | 问卷答案(JSON) | 中 — `questions_json`(问卷JSON)、`status`(状态:卡处理中) |
|
||||
| `ass_algorithm_model` | 算法模型文档 | 低 |
|
||||
| `ass_trigger_config` | 评估触发器配置 | 低 |
|
||||
|
||||
### 2.2 系统脏数据检测规则
|
||||
|
||||
> 参照营养模块 `nut_ano_dirty` 模式。mock 数据中定义了四种异常类型:缺失值、超范围值、重复数据、格式错误。
|
||||
|
||||
#### 风险评估
|
||||
|
||||
**评估主表(`ass_risk_evaluation`)**
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及字段 | 说明 |
|
||||
|----------|----------|----------|------|
|
||||
| 数据缺失 | `user_id` 为 NULL | `user_id`(用户ID) | 评估记录无归属人 |
|
||||
| 范围越界 | `eval_source` 不在 1-2 范围内 | `eval_source`(评估来源) | 评估来源异常(1=问卷/2=自动) |
|
||||
| 状态异常 | `status` = 2(处理中)或 3(失败)超过 24 小时 | `status`(任务状态) | 评估任务卡住未完成 |
|
||||
| 逻辑矛盾 | `is_exception` = 1 但 `ass_risk_result` 中所有疾病等级均为正常 | `is_exception`(是否异常) ↔ `ass_risk_result.*_level`(疾病等级) | 异常标记与结果数据不一致 |
|
||||
|
||||
**评估结果(`ass_risk_result`)**
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及字段 | 说明 |
|
||||
|----------|----------|----------|------|
|
||||
| 范围越界 | BMI 值 < 10 或 > 80 | `bmi`(BMI值) | 超出人体可能范围 |
|
||||
| 范围越界 | 收缩压 < 50 或 > 300 mmHg | `sbp`(收缩压) | 血压值异常 |
|
||||
| 范围越界 | 舒张压 < 30 或 > 200 mmHg | `dbp`(舒张压) | 血压值异常 |
|
||||
| 逻辑矛盾 | `sbp` < `dbp` | `sbp`(收缩压)、`dbp`(舒张压) | 收缩压低于舒张压 |
|
||||
| 范围越界 | `fasting_bg`(空腹血糖)< 0 或 > 50 mmol/L | `fasting_bg`(空腹血糖) | 血糖值异常 |
|
||||
| 范围越界 | `health_age` / `potential_health_age` 计算为负数或 > 150 | `health_age`(健康年龄)、`potential_health_age`(潜在健康年龄) | 健康年龄异常 |
|
||||
| 格式错误 | `bmi_mark` / `smoke_mark` / `sleep_mark` 等不符合 `state,score,fullmark` 格式 | `*_mark` 字段(生活习惯标记) | 生活习惯标记格式异常 |
|
||||
| 范围越界 | 疾病等级(`diabetes_level`、`hypertension_level` 等)不在预期枚举范围内 | `*_level` 字段(疾病等级) | 等级编码越界 |
|
||||
| 逻辑矛盾 | `cholesterol`、`triglycerin`、`hdlc`、`ldlc` 均为 0 或 NULL 但疾病等级非空 | 血脂四项 + `*_level`(疾病等级) | 血脂数据缺失但给出了疾病评级 |
|
||||
|
||||
**问卷信息(`ass_risk_questionnaire_info`)**
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及字段 | 说明 |
|
||||
|----------|----------|----------|------|
|
||||
| 范围越界 | 身高 < 50cm 或 > 250cm | `height`(身高cm) | 录入异常 |
|
||||
| 范围越界 | 体重 < 20kg 或 > 300kg | `weight`(体重kg) | 录入异常 |
|
||||
| 范围越界 | 腰围 < 30cm 或 > 200cm | `waist_line`(腰围cm) | 录入异常 |
|
||||
| 范围越界 | `smoking_status` 不在 1-3 | `smoking_status`(吸烟状态) | 吸烟状态枚举越界 |
|
||||
| 范围越界 | 个人病史字段(`personal_diabetes` 等)不为 0 或 1 | `personal_*` 字段(个人病史) | 病史枚举越界 |
|
||||
| 数据缺失 | `height`、`weight`、`waist_line` 均为 NULL | `height`(身高)、`weight`(体重)、`waist_line`(腰围) | 基础体测数据完全缺失 |
|
||||
| 格式错误 | 问卷 JSON 原始数据格式异常 | `questions_json`(问卷JSON,通过 `ass_questions`) | JSON 解析失败 |
|
||||
|
||||
**评估统计(`ass_risk_evaluation_statistics`)**
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及字段 | 说明 |
|
||||
|----------|----------|----------|------|
|
||||
| 逻辑矛盾 | `statics_num` 与 `ass_risk_evaluation` 中实际评估次数不一致 | `statics_num`(统计评估次数) | 统计数据过期 |
|
||||
| 逻辑矛盾 | `is_bmi_abnormal` 等疾病异常标记与 `last_evaluation_id` 对应结果数据不一致 | `is_*_abnormal` 字段(疾病异常标记) | 统计标记与源数据脱节 |
|
||||
| 逻辑矛盾 | `exception_num` 与实际 `is_exception=1` 的记录数不一致 | `exception_num`(异常计数) | 异常计数错误 |
|
||||
|
||||
#### 心理评估
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 范围越界 | `type` 不在 1-4(综合/压力/焦虑/抑郁) | `ass_psychology` | `type`(评估类型) |
|
||||
| 范围越界 | `grade` 超出该量表合理分值范围 | `ass_psychology` | `grade`(评估得分) |
|
||||
| 数据缺失 | `grade` 或 `phy_grade_level` 为 NULL | `ass_psychology` | `grade`(评估得分)、`phy_grade_level`(健康等级) |
|
||||
| 格式错误 | `phy_grade_level` 编码不在数据字典范围内 | `ass_psychology` | `phy_grade_level`(健康等级编码) |
|
||||
| 状态异常 | `status` = 2(分析中)超过 24 小时 | `ass_psychology` | `status`(任务状态) |
|
||||
| 逻辑矛盾 | `is_exception` = 1 但 `grade` 在正常范围内 | `ass_psychology` | `is_exception`(是否异常) ↔ `grade`(评估得分) |
|
||||
| 关联缺失 | `questions_id` 在 `ass_questions` 中不存在 | `ass_psychology` | `questions_id`(关联问卷ID) |
|
||||
| 逻辑矛盾 | `ass_psychology_statistics` 统计值与实际评估记录数不一致 | `ass_psychology_statistics` | — |
|
||||
|
||||
#### 规律起居
|
||||
|
||||
**在线穿戴评估(`ass_daily_routine_online`)**
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及字段 | 说明 |
|
||||
|----------|----------|----------|------|
|
||||
| 范围越界 | `sleep_hour` < 0 或 > 1440 分钟 | `sleep_hour`(睡眠时长分钟) | 睡眠时长不合理 |
|
||||
| 范围越界 | `sport_minute` < 0 或 > 1440 分钟 | `sport_minute`(运动时长分钟) | 运动时长不合理 |
|
||||
| 范围越界 | `resting_heart_rate` < 30 或 > 220 bpm | `resting_heart_rate`(静息心率bpm) | 静息心率异常 |
|
||||
| 范围越界 | `oxygen_saturation` < 60% 或 > 100% | `oxygen_saturation`(血氧饱和度%) | 血氧值异常 |
|
||||
| 范围越界 | `pressure_value` 超出传感器量程 | `pressure_value`(压力值) | 压力值异常 |
|
||||
| 逻辑矛盾 | `week_end_date` < `week_start_date` | `week_end_date`(周结束日期)、`week_start_date`(周开始日期) | 周起止日期倒置 |
|
||||
| 逻辑矛盾 | `sleep_hour` + `sport_minute` > 1440 | `sleep_hour`(睡眠时长)、`sport_minute`(运动时长) | 睡眠+运动超过24小时 |
|
||||
| 状态异常 | `status` = 2(分析中)超过 24 小时 | `status`(任务状态) | 任务卡住 |
|
||||
| 数据缺失 | `is_exception` 为 NULL | `is_exception`(是否异常) | 异常标记缺失 |
|
||||
|
||||
**问卷评估(`ass_daily_routine_paper`)**
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及字段 | 说明 |
|
||||
|----------|----------|----------|------|
|
||||
| 范围越界 | `sport_value` / `sleep_value` / `time_of_net_value` 为负值 | `sport_value`(运动值)、`sleep_value`(睡眠值)、`time_of_net_value`(上网时长) | 负数无意义 |
|
||||
| 范围越界 | `time_of_net_value` > 24 小时 | `time_of_net_value`(上网时长) | 上网时长不合理 |
|
||||
| 范围越界 | `sport_level` / `sleep_type` / `time_of_net_level` 不在枚举范围 | `sport_level`(运动等级)、`sleep_type`(睡眠类型)、`time_of_net_level`(上网等级) | 等级编码越界 |
|
||||
| 关联缺失 | `questions_id` 在 `ass_questions` 中不存在 | `questions_id`(关联问卷ID) | 孤立问卷关联 |
|
||||
| 数据缺失 | `is_exception` 为 NULL | `is_exception`(是否异常) | 异常标记缺失 |
|
||||
|
||||
#### 人群分类
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 范围越界 | `user_group` 不在 A/B/C/D/E 范围内 | `ass_group_user` | `user_group`(人群分类) |
|
||||
| 范围越界 | `group_change_type` 不在 1-3 | `ass_group_user` | `group_change_type`(变更类型) |
|
||||
| 范围越界 | `audit_status` 不在 0-2 | `ass_group_user` | `audit_status`(审核状态) |
|
||||
| 逻辑矛盾 | `is_archived` = 1 且 `archived_time` 为 NULL | `ass_group_user` | `is_archived`(是否归档)、`archived_time`(归档时间) |
|
||||
| 范围越界 | `date_year` 为未来年份或早于 2020 | `ass_group_user` | `date_year`(归属年份) |
|
||||
| 范围越界 | `latest_assessment_date` 为未来日期 | `ass_group_user` | `latest_assessment_date`(最近评估日期) |
|
||||
| 关联缺失 | `group_user_id` 在 `ass_group_user` 中不存在 | `ass_group_user_detail` | `group_user_id`(人群分类ID) |
|
||||
| 范围越界 | `detail_type` 不在 A/B/C/D | `ass_group_user_detail` | `detail_type`(明细类型) |
|
||||
| 范围越界 | `data_type` 不在 1-2 | `ass_group_user_detail` | `data_type`(数据类型) |
|
||||
| 重复数据 | 同一用户同一年度存在多条活跃分类记录 | `ass_group_user` | `user_id`(用户ID) + `date_year`(归属年份) |
|
||||
|
||||
#### 问卷与处方
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 格式错误 | `questions_json` 格式非法(JSON 解析失败) | `ass_questions` | `questions_json`(问卷JSON) |
|
||||
| 状态异常 | `status` = 2(分析中)超过 24 小时 | `ass_questions` | `status`(任务状态) |
|
||||
| 格式错误 | `f_elements` 不符合 `meal_foodCode_amount;...` 格式 | `ass_risk_diet_sports_prescription` | `f_elements`(食物元素格式) |
|
||||
| 范围越界 | `energy_level` 为负值或 > 10000 kcal | `ass_risk_diet_sports_prescription` | `energy_level`(能量等级) |
|
||||
| 数据缺失 | 评估正常但处方中所有运动字段为 NULL | `ass_risk_diet_sports_prescription` | `aerobic_*`(有氧运动)、`strength_*`(力量训练)、`flexibility_*`(柔韧训练) |
|
||||
|
||||
### 2.3 检测频率建议
|
||||
|
||||
| 检测类型 | 建议频率 | 说明 |
|
||||
|----------|----------|------|
|
||||
| 评估任务卡住检测 | 每小时 | `status=2` 超过 24 小时的记录 |
|
||||
| 数值范围越界检测 | 每日凌晨(评估任务完成后) | 全量扫描 BMI/血压/心率等 |
|
||||
| 统计一致性校验 | 每日凌晨 | `statics_num` vs 实际记录数 |
|
||||
| 格式校验(JSON/mark) | 数据入库时实时 | 问卷JSON、`f_elements`、`*_mark` |
|
||||
|
||||
---
|
||||
|
||||
## 三、健康咨询
|
||||
|
||||
> **后端服务**:`platform-consult`(端口 24806)| **原型参考**:无独立原型页面
|
||||
>
|
||||
> **开发状态**:✅ 已实现 `con_exception_dirty` 表 + 3 种异常类型定时检测,管理端分页查询/忽略/导出功能完整。
|
||||
|
||||
健康咨询模块管理员工在线图文/视频咨询全流程,涵盖咨询会话、专家管理、病历档案、IM 消息、评价结算等。
|
||||
|
||||
### 3.1 涉及数据库表
|
||||
|
||||
#### 咨询核心(4 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `con_consult` | 咨询会话主表(图文/视频统一) | 高 — `consult_no`(咨询单号)、`content_status`(预约/咨询状态:1-8)、`session_status`(会话状态:1=进行中/2=已结束)、`start_time`(开始时间)/`end_time`(结束时间)、`duration_minutes`(咨询时长秒)、`score`(用户评分1-5)、`cost`(咨询费用) |
|
||||
| `con_evaluate` | 咨询评价表 | 高 — `score`(评分1-5)、`consult_id`(关联咨询ID)、`expert_id`(被评价专家ID) |
|
||||
| `con_medical_record` | 病历档案表 | 中 — `medical_describe`(病情描述)、`duration_type`(持续时间:1-4)、`images`(检查资料图片URL) |
|
||||
| `con_family_member` | 家庭成员/咨询人表 | 中 — `member_name`(成员姓名)、`birthday`(出生日期)、`height`(身高cm)、`weight`(体重kg)、`relation`(家庭关系) |
|
||||
|
||||
#### 专家与排班(2 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `con_expert` | 专家信息表 | 高 — `expert_no`(专家编号)、`expert_type`(专家类型:1=收费/2=免费/3=其他)、`overall_merit`(综合评分)、`response_rate`(24h回复率)、`hospital_id`(所属医院ID)、`dept_id`(所属科室ID)、`reg_date`(入职日期)/`off_date`(离职日期) |
|
||||
| `con_expert_schedule_rule` | 专家排班规则表(按周设置) | 中 — `week_day`(周几:1-7)、`period`(时段:1-4)、`start_time`(出诊开始时间)/`end_time`(出诊结束时间)、`capacity`(接诊人数上限) |
|
||||
|
||||
#### IM 消息(2 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `con_im_message` | IM消息记录表 | 中 — `msg_key`(腾讯IM消息唯一标识)、`msg_type`(消息类型:1=单聊/2=群聊/3=应急群聊/4=音视频)、`msg_content`(消息内容)、`send_time`(发送时间)、`consult_id`(关联咨询ID) |
|
||||
| `con_im_chat` | IM聊天会话表(通讯录单聊) | 中 — `session_id`(会话ID)、`pair_id`(会话对唯一标识)、`from_user_id`(发起者)、`to_user_id`(接受者) |
|
||||
|
||||
#### 结算(4 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `con_settle_main` | 结算主表 | 中 — `settle_status`(结算状态:0=待结算/1=结算中/2=已结算/3=异常)、`com_fee_per_month`(每月通讯费)、`error_msg`(异常信息) |
|
||||
| `con_settle_result` | 结算结果 | 中 — 金额一致性 |
|
||||
| `con_settle_result_item` | 结算结果明细 | 中 — 明细与汇总一致性 |
|
||||
| `con_settle_cost_config` | 费用配置 | 低 — 配置值合理性 |
|
||||
|
||||
#### 基础数据(4 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `con_hospital` | 医院关联配置 | 中 — `ref_id`(关联外部医院ID) |
|
||||
| `con_hospital_dept` | 医院-科室关联表 | 低 — `hospital_id`(医院ID)、`dept_id`(科室ID) |
|
||||
| `con_department` | 科室表 | 中 — `dept_name`(科室名称)、`parent_id`(上级科室ID) |
|
||||
| `con_disease` | 疾病信息表 | 低 — `disease_name`(疾病名称)、`dept_id`(所属科室ID) |
|
||||
|
||||
#### 其他(4 张表)
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `con_notice` | 咨询须知表 | 低 |
|
||||
| `con_phrase` | 常用语表 | 低 |
|
||||
| `con_settle_period_config` | 结算周期配置 | 低 |
|
||||
|
||||
### 3.2 系统脏数据检测规则
|
||||
|
||||
> 后端已实现 `con_exception_dirty` 表,目前定义了 3 种异常类型:咨询时长异常(`exception_type=1`)、长时间未回复(`exception_type=2`)、评价分数极低(`exception_type=3`)。
|
||||
>
|
||||
> ⚠️ **已知问题**:`ConConsultTimeoutJob` 每小时自动关闭超时 7 天的会话,因此"咨询时长异常"检测的阈值必须设置在 7 天以内,否则异常记录永远无法生成。
|
||||
>
|
||||
> ⚠️ **已知缺陷**:`ConExceptionDirtyMapper.xml` 第 29 行 `work_no` 被硬编码为 `NULL`,前端展示员工工号列为空。
|
||||
>
|
||||
> ⚠️ **已知缺陷**:`ConExceptionDirtyMapper.xml` 中 `h."name" AS hospital_name` 引用了 `con_hospital` 表中可能不存在的 `name` 列(`con_hospital` 实体仅有 `ref_id` 无 `name`),需确认运行时是否会报错或从外部服务取数。
|
||||
|
||||
#### 咨询会话(已有)
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 状态异常 | 咨询时长异常:会话进行中但 `duration_minutes` 超过合理阈值(如 > 60 分钟) | `con_consult` | `duration_minutes`(咨询时长)、`content_status`(预约/咨询状态) | `exception_type=1`,需在超时 Job(7天)前触发 |
|
||||
| 状态异常 | 长时间未回复:专家超过 N 小时未回复用户消息 | `con_consult` | `last_reply_time`(最后回复时间)、`content_status`(预约/咨询状态) | `exception_type=2` |
|
||||
| 范围越界 | 评价分数极低:`score` < 2 分 | `con_evaluate` / `con_consult` | `score`(评分) | `exception_type=3` |
|
||||
|
||||
#### 咨询会话(建议新增)
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 逻辑矛盾 | `start_time` > `end_time` | `con_consult` | `start_time`(开始时间)、`end_time`(结束时间) | 咨询结束时间早于开始时间 |
|
||||
| 逻辑矛盾 | `session_status` = 进行中(1) 但 `end_time` 不为空 | `con_consult` | `session_status`(会话状态)、`end_time`(结束时间) | 状态与时间矛盾 |
|
||||
| 逻辑矛盾 | `content_status` = 已完成(3) 但 `end_time` 为空 | `con_consult` | `content_status`(预约/咨询状态)、`end_time`(结束时间) | 已完成但无结束时间 |
|
||||
| 逻辑矛盾 | `content_status` = 已拒绝(8) 但 `reject_reason` 为空 | `con_consult` | `content_status`(预约/咨询状态)、`reject_reason`(拒绝原因) | 拒绝但无理由 |
|
||||
| 范围越界 | `duration_minutes` < 0 | `con_consult` | `duration_minutes`(咨询时长) | 咨询时长为负数 |
|
||||
| 范围越界 | `consult_type` 不在 1-2 | `con_consult` | `consult_type`(咨询类型:1=图文/2=视频) | 咨询类型枚举越界 |
|
||||
| 范围越界 | `content_status` 不在 1-8 | `con_consult` | `content_status`(预约/咨询状态) | 内容状态枚举越界 |
|
||||
| 范围越界 | `cost` < 0 | `con_consult` | `cost`(咨询费用) | 咨询费用为负数 |
|
||||
| 关联缺失 | `expert_id` 在 `con_expert` 中不存在 | `con_consult` | `expert_id`(专家ID) | 关联专家已删除 |
|
||||
| 关联缺失 | `member_id` 不为空但在 `con_family_member` 中不存在 | `con_consult` | `member_id`(咨询人ID) | 关联咨询人已删除 |
|
||||
| 数据缺失 | `consult_no` 为空 | `con_consult` | `consult_no`(咨询单号) | 咨询单号缺失 |
|
||||
|
||||
#### 专家信息
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 范围越界 | `overall_merit` < 0 或 > 5 | `con_expert` | `overall_merit`(综合评分) | 综合评分越界 |
|
||||
| 范围越界 | `response_rate` < 0 或 > 100 | `con_expert` | `response_rate`(24h回复率%) | 回复率越界 |
|
||||
| 范围越界 | `expert_type` 不在 1-3 | `con_expert` | `expert_type`(专家类型) | 专家类型枚举越界 |
|
||||
| 数据缺失 | `expert_no` 为空 | `con_expert` | `expert_no`(专家编号) | 专家编号缺失 |
|
||||
| 逻辑矛盾 | `off_date` < `reg_date`(均已填写时) | `con_expert` | `off_date`(离职日期)、`reg_date`(入职日期) | 离职日期早于入职日期 |
|
||||
| 关联缺失 | `hospital_id` 在 `con_hospital` 中不存在 | `con_expert` | `hospital_id`(所属医院ID) | 关联医院不存在 |
|
||||
| 关联缺失 | `dept_id` 在 `con_department` 中不存在 | `con_expert` | `dept_id`(所属科室ID) | 关联科室不存在 |
|
||||
|
||||
#### 咨询评价
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 范围越界 | `score` < 0 或 > 5 | `con_evaluate` | `score`(评分) | 评分越界 |
|
||||
| 关联缺失 | `consult_id` 在 `con_consult` 中不存在 | `con_evaluate` | `consult_id`(关联咨询ID) | 评价关联的咨询不存在 |
|
||||
| 关联缺失 | `expert_id` 在 `con_expert` 中不存在 | `con_evaluate` | `expert_id`(被评价专家ID) | 评价关联的专家不存在 |
|
||||
|
||||
#### 家庭成员
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 范围越界 | `height` < 50 或 > 250 (cm) | `con_family_member` | `height`(身高cm) | 身高越界 |
|
||||
| 范围越界 | `weight` < 20 或 > 300 (kg) | `con_family_member` | `weight`(体重kg) | 体重越界 |
|
||||
| 范围越界 | `sex` 不在 1-2 | `con_family_member` | `sex`(性别:1=男/2=女) | 性别枚举越界 |
|
||||
| 范围越界 | `birthday` 为未来日期 | `con_family_member` | `birthday`(出生日期) | 生日为未来日期 |
|
||||
|
||||
#### 病历档案
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 数据缺失 | `medical_describe` 为空 | `con_medical_record` | `medical_describe`(病情描述) | 病情描述缺失 |
|
||||
| 范围越界 | `duration_type` 不在 1-4 | `con_medical_record` | `duration_type`(持续时间:1=几天内/2=1-2周/3=1-3月/4=3月以上) | 持续时间枚举越界 |
|
||||
|
||||
#### IM 消息
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 数据缺失 | `msg_content` 为空且非撤回消息 | `con_im_message` | `msg_content`(消息内容) | 消息内容缺失 |
|
||||
| 范围越界 | `msg_type` 不在 1-4 | `con_im_message` | `msg_type`(消息类型) | 消息类型枚举越界 |
|
||||
| 关联缺失 | `consult_id` 不为空但在 `con_consult` 中不存在 | `con_im_message` | `consult_id`(关联咨询ID) | 消息关联的咨询不存在 |
|
||||
|
||||
#### 排班规则
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 范围越界 | `week_day` 不在 1-7 | `con_expert_schedule_rule` | `week_day`(星期:1=周一~7=周日) | 星期枚举越界 |
|
||||
| 范围越界 | `period` 不在 1-4 | `con_expert_schedule_rule` | `period`(时段:1-4) | 时段枚举越界 |
|
||||
| 范围越界 | `capacity` < 0 | `con_expert_schedule_rule` | `capacity`(接诊人数上限) | 接诊人数为负 |
|
||||
| 逻辑矛盾 | `end_time` < `start_time` | `con_expert_schedule_rule` | `start_time`(出诊开始时间)、`end_time`(出诊结束时间) | 排班结束时间早于开始时间 |
|
||||
|
||||
### 3.3 现有后端实现评估
|
||||
|
||||
#### 已实现
|
||||
|
||||
| 组件 | 状态 | 说明 |
|
||||
|------|:--:|------|
|
||||
| `con_exception_dirty` 表 | ✅ 已上线 | 5个字段:consult_id、consult_no、exception_type、exception_value、alarm_time |
|
||||
| `ConExceptionDirtyController` | ✅ 已上线 | `/page` 分页查询 + `/ignore` 批量忽略 + `/export` 导出 |
|
||||
| `ConExceptionDirtyService` | ✅ 已上线 | 分页 JOIN 咨询/专家/医院 + Feign 批量查用户名 |
|
||||
| `ExceptionTypeEnum` | ✅ 已上线 | 3 种异常类型:时长异常/长时间未回复/低分评价 |
|
||||
| `ConConsultTimeoutJob` | ✅ 已上线 | 每小时扫描,7 天超时自动关闭会话 |
|
||||
|
||||
#### 待完善
|
||||
|
||||
| 项目 | 优先级 | 说明 |
|
||||
|------|:--:|------|
|
||||
| 异常数据自动检测定时任务 | 高 | 需实现定时扫描生成 `con_exception_dirty` 记录 |
|
||||
| `work_no` 字段补充 | 高 | 当前 Mapper XML 硬编码为 NULL,需 JOIN `con_user_snapshot` 获取 |
|
||||
| 咨询时长异常阈值与超时 Job 的协调 | 高 | 时长异常应在超时 Job 触发前检测(如 > 60 分钟即告警,而非等 7 天) |
|
||||
| 专家/家庭成员/病历/排班等数据校验 | 中 | 当前仅覆盖咨询会话维度的 3 种异常 |
|
||||
| IM 消息数据完整性校验 | 低 | 消息内容、关联关系 |
|
||||
|
||||
### 3.4 检测频率建议
|
||||
|
||||
| 检测类型 | 建议频率 | 说明 |
|
||||
|----------|----------|------|
|
||||
| 咨询时长异常检测 | 每 30 分钟 | 需在超时 Job(7天)前触发,建议 > 60 分钟即告警 |
|
||||
| 长时间未回复检测 | 每小时 | 检查 `last_reply_time` 超过阈值 |
|
||||
| 低分评价检测 | 评价生成时实时 | 评价提交后即时判断 |
|
||||
| 枚举/范围/逻辑矛盾校验 | 每日凌晨 | 全量扫描各表枚举字段和数值范围 |
|
||||
|
||||
---
|
||||
|
||||
## 四、应急就医
|
||||
|
||||
> **后端服务**:`platform-emergency`(端口 24808)| **原型参考**:`web-admin/emergency-dispatch/admin/exception-dirty.html`
|
||||
>
|
||||
> **开发状态**:⚠️ 后端已有 `EmDirtyDataController` 占位(返回空数据),`EmExceptionDictConstant` 定义常量;尚未实现具体检测和存储。
|
||||
|
||||
应急就医管理员工应急工单、云坐席通话、AED 设备部署与管理、救护车调度等。脏数据类型与其他模块差异较大,主要关注 **AED 设备**数据质量和**通话记录**完整性。
|
||||
|
||||
### 4.1 涉及数据库表
|
||||
|
||||
#### 核心应急表
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `em_emergency_center` | 应急中心 | 中 — `longitude`(经度)/`latitude`(纬度)、`center_phone`(中心电话)、`status`(状态) |
|
||||
| `em_user_profile` | 应急人员档案 | 中 — `cert_number`(证书编号)、`license_number`(执照编号)、`station_status`(驻场状态) |
|
||||
| `em_call_record` | 通话记录(七陌云客服) | 高 — `incoming_phone`(来电号码)、`match_status`(匹配状态:1=唯一匹配/2=多重匹配)、`employee_id`(匹配员工ID)、`duration`(通话时长) |
|
||||
| `em_emergency_order` | 应急工单 | 高 — `order_no`(工单编号)、`status`(工单状态)、`location_desc`(位置描述)、`location_lat`(纬度)/`location_lng`(经度)、`closed_at`(关闭时间) |
|
||||
| `em_work_order_dispatch` | 工单调度日志 | 中 — 调度链路完整性 |
|
||||
|
||||
#### AED 设备管理
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `em_aed_device` | AED 设备主表 | 高 — `battery_level`(电池电量百分比)、`battery_status`(电池状态枚举) |
|
||||
| `em_aed_deploy_point` | AED 部署点位 | 高 — `longitude`(经度)、`latitude`(纬度) |
|
||||
| `em_aed_maintenance` | AED 维护记录 | 中 — 维护日期、到期提醒 |
|
||||
| `em_aed_latest` | AED 最新状态 | 高 — `battery_power`(厂商原始电池数据String)、实时状态聚合 |
|
||||
| `em_aed_warn_info` | AED 告警信息 | 中 — 告警记录 |
|
||||
| `em_aed_usage` | AED 使用记录 | 中 — 使用时间、使用人 |
|
||||
|
||||
#### 其他应急表
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `em_ambulance` | 救护车 | 中 — `plate_no`(车牌号)、`driver`(驾驶员)、`status`(状态) |
|
||||
| `em_schedule_record` | 值班排班记录 | 中 — 排班时间冲突 |
|
||||
| `em_emergency_contact` | 紧急联系人 | 中 — 联系方式有效性 |
|
||||
| `em_emergency_center_call_record` | 应急中心通话记录 | 中 — `call_id`(通话ID)、`employee_id`(员工ID)、`begin_time`(开始时间)、`end_time`(结束时间)、`record_file`(录音文件) |
|
||||
| `em_emergency_center_call_join` | 应急中心通话参与人 | 中 — 参与人关联完整性、`employee_id`(员工ID) |
|
||||
| `em_hospital` | 应急合作医院 | 低 |
|
||||
| `em_first_aid_kit` | 急救箱 | 中 — 过期检查 |
|
||||
| `em_drill_record` | 演练记录 | 低 |
|
||||
|
||||
### 4.2 系统脏数据检测规则
|
||||
|
||||
> 应急模块使用独特的异常类型分类:非法数据 / 异常坐标 / 状态异常。
|
||||
>
|
||||
> **注意**:后端 `EmExceptionDictConstant` 当前定义了 `MISSING_FIELD` / `INVALID_FORMAT` / `ORPHAN_RECORD`,与原型中的 `非法数据` / `异常坐标` / `状态异常` 分类不一致,需后续对齐。
|
||||
|
||||
#### 通话记录
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 非法数据 | 电话号码格式不合法(非国内手机号/非座机号) | `em_call_record` | `incoming_phone`(来电号码) | 云客服传入的号码非法 |
|
||||
| 状态异常 | `match_status` 为"多重匹配"(=2),存在多个员工对应同一号码 | `em_call_record` | `match_status`(匹配状态)、`employee_id`(匹配员工ID) | 一个号码匹配到多名员工,需人工确认 |
|
||||
| 关联缺失 | 通话记录关联的 `order_id` 在 `em_emergency_order` 中不存在 | `em_call_record` | `order_id`(关联工单ID) | 孤立的工单关联 |
|
||||
| 逻辑矛盾 | 通话结束时间早于开始时间 | `em_call_record` | `begin_time`(开始时间)、`end_time`(结束时间) | 时间戳异常 |
|
||||
| 逻辑矛盾 | 通话状态为"已接听"但时长为 0 | `em_call_record` | `answer_status`(接听状态) + `duration`(通话时长) | 状态与数据矛盾 |
|
||||
|
||||
#### AED 设备管理
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 | 说明 |
|
||||
|----------|----------|--------|----------|------|
|
||||
| 非法数据 | 电池电量百分比超出 0-100% 范围(如 = 260%) | `em_aed_device` | `battery_level`(电池电量百分比) | 硬件上传了不可能的电量值 |
|
||||
| 非法数据 | 设备上报的原始电池电压/电量(String 类型,厂商原始值) | `em_aed_latest` | `battery_power`(厂商原始电池数据) | 厂商原始电池数据,非 0-100% 百分比 |
|
||||
| 非法数据 | 电池状态值不在预定义枚举范围内 | `em_aed_device` | `battery_status`(电池状态) | 状态码异常,如"未知" |
|
||||
| 异常坐标 | GPS 坐标不在国内范围(经度 73-135°E,纬度 18-54°N) | `em_aed_deploy_point` | `longitude`(经度)、`latitude`(纬度) | 如坐标指向海外(悉尼) |
|
||||
| 异常坐标 | GPS 坐标为 (0,0) 或 NULL(未获取到定位) | `em_aed_deploy_point` | `longitude`(经度)、`latitude`(纬度) | AED 部署点位无有效坐标 |
|
||||
| 关联缺失 | AED 部署点位关联的应急中心不存在 | `em_aed_deploy_point` ↔ `em_emergency_center` | 中心关联字段 | |
|
||||
| 逻辑矛盾 | AED 最近一次维护日期晚于当前日期 | `em_aed_maintenance` | 维护日期 | 未来日期,数据录入错误 |
|
||||
| 数据缺失 | AED 设备缺少维护记录 | `em_aed_device` ↔ `em_aed_maintenance` | | 设备部署后从未维护 |
|
||||
|
||||
> **注意**:AED 设备离线检测(基于心跳时间差)当前暂不可用,因为 `em_aed_latest` 表缺少 `update_time` 字段。需后续新增该字段。
|
||||
|
||||
### 4.3 检测频率建议
|
||||
|
||||
| 检测类型 | 建议频率 | 说明 |
|
||||
|----------|----------|------|
|
||||
| 系统脏数据 — AED 电池/坐标 | 每日凌晨 | AED 设备数据量小 |
|
||||
| 系统脏数据 — 通话记录非法数据 | 每日凌晨 | 通话记录增量扫描 |
|
||||
| AED 设备离线检测 | 每小时 | `em_aed_latest` 心跳超时判断 |
|
||||
|
||||
---
|
||||
|
||||
## 五、营养管理
|
||||
|
||||
> **后端服务**:`platform-nutrition`(端口 24810)| **原型参考**:`web-admin/nutrition/ano-dirty.html`
|
||||
>
|
||||
> **开发状态**:✅ 已实现脏数据存储表 `nut_ano_dirty`,服务已上线。
|
||||
|
||||
营养管理是系统最大的模块(约 130 张表),涵盖菜品/食谱管理、订餐/取餐、农场种植养殖、原材料采购库存、中央厨房生产、营养算法与 AI 推荐等全链路。
|
||||
|
||||
### 5.1 涉及数据库表
|
||||
|
||||
#### 用户与档案
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_user` | 营养用户(用餐者) | 高 — `phone`(手机号)、`bmi`(BMI值)、`health_tags`(健康标签) |
|
||||
| `nut_user_profile` | 用户健康档案 | 高 — `height`(身高)、`weight`(体重)、`target_weight`(目标体重)、`allergies`(过敏原)、`dietary_restrictions`(饮食限制) |
|
||||
| `nut_user_account` | 用户账户/充值 | 中 — 账户余额字段 |
|
||||
| `nut_user_face` | 面部识别数据 | 中 — 面部嵌入向量有效性 |
|
||||
| `nut_member` | 会员记录 | 中 — 会员有效期 |
|
||||
|
||||
#### 食品与食谱
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_food` | 菜品主表 | 高 — `price`(价格)、`nutrition_info`(营养信息)、`status`(状态) |
|
||||
| `nut_food_class` | 菜品分类 | 中 — `parent_id`(上级分类ID) 自引用完整性 |
|
||||
| `nut_food_composition` | 食物成分 | 高 — `value_per_100g`(每100g营养值) |
|
||||
| `nut_food_nutri` | 食物营养数据 | 高 — 详细营养分解 |
|
||||
| `nut_food_spec` | 食物规格/份量 | 中 — `weight`(份量重量) |
|
||||
| `nut_food_check` | 食品检测记录 | 中 — `result`(检测结果)、`passed`(是否通过) |
|
||||
| `nut_recipe` | 食谱 | 中 — `total_calories`(总热量)、`nutrition_summary`(营养汇总JSON) |
|
||||
| `nut_recipe_food` | 食谱-菜品关联 | 中 — `portion`(份数) |
|
||||
| `nut_cookbook` | 菜谱 | 低 — `steps`(步骤) |
|
||||
|
||||
#### 膳食与订餐
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_order` | 订单主表 | 高 — `total_amount`(订单总金额)、`status`(订单状态)、`order_type`(订单类型) |
|
||||
| `nut_order_item` | 订单明细 | 高 — `quantity`(数量)、`price`(单价)、`subtotal`(小计) |
|
||||
| `nut_canteen` | 餐厅/食堂 | 中 — `capacity`(容量)、`status`(状态) |
|
||||
| `nut_canteen_pickup_record` | 取餐记录 | 中 — `portion`(份量)、`calories`(热量) |
|
||||
| `nut_pickup_order` | 取餐订单 | 中 — `nutrition_info`(营养汇总) |
|
||||
| `nut_consume_record` | 消费记录 | 中 — 金额一致性 |
|
||||
| `nut_pay_error` | 支付错误日志 | 低 — 支付异常记录 |
|
||||
|
||||
#### 原材料与供应
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_mater_base` | 原材料主表 | 高 — `price`(价格)、`unit`(单位) |
|
||||
| `nut_raw_inbound` | 原材料入库 | 高 — `quantity`(数量)、`weight`(重量) |
|
||||
| `nut_sup_inventory` | 供应库存 | 高 — `quantity`(库存数量) |
|
||||
| `nut_sup_inventory_flow` | 库存流水 | 中 — `qty`(操作量)、`current_qty_after`(操作后在库量) |
|
||||
| `nut_sup_hygiene_test` | 卫生检测 | 中 — 检测结果 |
|
||||
| `nut_sup_warehouse` | 仓库 | 低 — `location`(位置)、`manager`(管理员) |
|
||||
|
||||
> **注**:`nut_sup_inventory_flow` 的 SQL DDL 文件缺失(`db/nutrition/` 目录下未找到对应建表脚本),需补充。
|
||||
|
||||
#### 生产与中央厨房
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_prod_combo_task` | 组合生产任务 | 中 — `plan_date`(计划日期)、`status`(任务状态) |
|
||||
| `nut_prod_qc_sample` | 质检样品 | 高 — `status`(状态:0=留样中/1=已处置/2=已检验) |
|
||||
| `nut_prod_qc_violation` | 质检违规 | 中 — 违规记录完整性 |
|
||||
| `nut_prod_serve_record` | 供餐记录 | 中 — 实际供餐与实际订单一致性 |
|
||||
| `nut_prod_stat_cost` | 生产成本统计 | 中 — 金额合理性 |
|
||||
|
||||
#### 农场
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_farm_plot` | 地块 | 中 — `area`(面积)、`soil_type`(土壤类型) |
|
||||
| `nut_farm_crop_batch` | 作物批次 | 中 — `plant_date`(种植日期)、`expected_harvest`(预计采收日期) |
|
||||
| `nut_farm_harvest` | 采收记录 | 中 — `quantity`(采收数量) |
|
||||
| `nut_farm_livestock_batch` | 牲畜批次 | 中 — `count`(数量) |
|
||||
| `nut_farm_supplier_rating` | 供应商评级 | 低 — 评分范围 |
|
||||
|
||||
#### 算法与 AI
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_algo_personal` | 个性化算法结果 | 高 — 营养计算结果 |
|
||||
| `nut_algo_mass` | 批量算法结果 | 高 — 批量计算结果 |
|
||||
| `nut_algo_standard` | 算法标准 | 中 — 标准值合理性 |
|
||||
| `nut_model_llm` | LLM 模型配置 | 中 — 配置有效性 |
|
||||
| `nut_model_small_version` | 模型版本 | 低 — 版本管理 |
|
||||
|
||||
#### 设备与终端
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `nut_terminal` | 终端设备 | 中 — 设备状态 |
|
||||
| `nut_terminal_fault` | 终端故障记录 | 低 |
|
||||
| `nut_meter_device` | 计量设备(秤) | 中 — 计量精度 |
|
||||
| `nut_meter_reading` | 计量读数 | 高 — 读数合理性 |
|
||||
|
||||
### 5.2 系统脏数据检测规则
|
||||
|
||||
> 后端已实现 `nut_ano_dirty` 表,以下按原型业务模块分类列出需要检测的规则。
|
||||
|
||||
#### 用户档案
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 逻辑矛盾 | 年龄为负数 | `nut_user_profile` | `birthday`(生日) → 计算年龄 |
|
||||
| 范围越界 | BMI 值超出合理范围 | `nut_user` / `nut_user_profile` | `bmi`(BMI值) |
|
||||
| 数据缺失 | 手机号为空 | `nut_user` | `phone`(手机号) |
|
||||
| 重复数据 | 同一 `user_id` 存在多条档案记录 | `nut_user_profile` | `user_id`(用户ID) |
|
||||
| 逻辑矛盾 | 健康目标与饮食限制冲突(如目标为增重但设置了减脂限制) | `nut_user_profile` | `health_goal`(健康目标) ↔ `dietary_restrictions`(饮食限制) |
|
||||
|
||||
#### 食谱管理
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 数据缺失 | 热量值字段为空 | `nut_recipe` / `nut_food_nutri` | `total_calories`(总热量) |
|
||||
| 关联缺失 | 食谱引用的食材ID在食材库中不存在 | `nut_recipe_food` | `food_id`(食材ID) → `nut_food.id` |
|
||||
| 格式错误 | 食谱营养汇总JSON格式非法 | `nut_recipe` | `nutrition_summary`(营养汇总JSON) |
|
||||
|
||||
#### 订餐管理
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 格式错误 | 订餐日期格式非法 | `nut_order` | 订单日期字段 |
|
||||
| 范围越界 | 单次订餐份数超出系统上限 | `nut_order_item` | `quantity`(数量) |
|
||||
| 逻辑矛盾 | 订单金额与明细小计之和不一致 | `nut_order.total_amount` vs `SUM(nut_order_item.subtotal)` | |
|
||||
|
||||
#### 营养分析
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 重复数据 | 同一用户同日存在多条重复营养分析记录 | `nut_algo_personal` | `user_id`(用户ID) + 日期 |
|
||||
| 范围越界 | 营养素计算结果超出合理范围 | `nut_algo_personal` / `nut_algo_mass` | 营养结果字段 |
|
||||
|
||||
#### 食材库存
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 范围越界 | 库存数量为负值 | `nut_sup_inventory` | `quantity`(库存数量) |
|
||||
| 逻辑矛盾 | 库存流水余额与当前库存不一致 | `nut_sup_inventory_flow` ↔ `nut_sup_inventory` | `current_qty_after`(操作后在库量) vs `quantity`(库存数量) |
|
||||
| 关联缺失 | 库存记录的原材料在 `nut_mater_base` 中不存在 | `nut_sup_inventory` | `mater_id`(原材料ID) |
|
||||
|
||||
#### 健康生产
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 格式错误 | 生产批次号含非法字符 | `nut_prod_combo_task` | `task_no`(任务编号) |
|
||||
| 逻辑矛盾 | 生产任务完成但无供餐记录 | `nut_prod_combo_task` ↔ `nut_prod_serve_record` | |
|
||||
| 数据缺失 | 质检样品无检测结果 | `nut_prod_qc_sample` | `status`(状态:0=留样中/1=已处置/2=已检验) |
|
||||
|
||||
#### 卫生供应
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 数据缺失 | 供应商资质证书编号为空 | `nut_farm_supplier_external` | 证书字段 |
|
||||
| 格式错误 | 卫生检测报告编号格式非法 | `nut_sup_hygiene_test` | 检测编号字段 |
|
||||
| 关联缺失 | 供应记录关联的供应商已删除 | `nut_raw_inbound` | `supplier_id`(供应商ID) |
|
||||
|
||||
### 5.3 现有后端实现评估
|
||||
|
||||
#### 已实现
|
||||
|
||||
| 组件 | 状态 | 说明 |
|
||||
|------|:--:|------|
|
||||
| `nut_ano_dirty` 表 | ✅ 已上线 | 5个索引,支持分页/筛选/导出 |
|
||||
| `NutAnoDirtyService` | ✅ 已上线 | 完整 CRUD + 异步导出 |
|
||||
| `NutAnoDirtyController` | ✅ 已上线 | 与原型一致的查询接口 |
|
||||
|
||||
#### 待完善
|
||||
|
||||
| 项目 | 优先级 | 说明 |
|
||||
|------|:--:|------|
|
||||
| 系统脏数据自动检测定时任务 | 高 | 需实现每日全量扫描 Job |
|
||||
| 订餐管理、食材库存、健康生产、卫生供应的脏数据规则 | 高 | 原型有定义但后端可能未覆盖全 |
|
||||
| 农场子域的脏数据检测 | 中 | 原型未明确涉及,但表结构已存在 |
|
||||
| 设备/终端数据脏数据检测 | 低 | 秤读数、终端故障等 |
|
||||
|
||||
### 5.4 检测频率建议
|
||||
|
||||
| 检测类型 | 建议频率 | 说明 |
|
||||
|----------|----------|------|
|
||||
| 系统脏数据全面扫描 | 每日凌晨 2:00 | 全量扫描所有7个业务模块 |
|
||||
| 库存数量负值检查 | 每日凌晨 + 每次出入库后 | 实时性要求较高 |
|
||||
| 订单金额一致性 | 每日凌晨 | 财务敏感性数据 |
|
||||
|
||||
---
|
||||
|
||||
## 六、健康监测
|
||||
|
||||
> **后端服务**:`platform-monitor`(端口 24805)| **原型参考**:`web-admin/health-monitor/exception-dirty.html`
|
||||
>
|
||||
> **开发状态**:❌ 未实现独立的脏数据检测表,已有 `mon_alert_record`(穿戴告警)和 `mon_env_warn_info`(环境告警)。
|
||||
|
||||
健康监测是系统第二大模块,涵盖可穿戴设备数据采集、环境监测、健康调查问卷等。
|
||||
|
||||
### 6.1 涉及数据库表
|
||||
|
||||
#### 设备与告警
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `mon_device` | 可穿戴设备主表 | 高 — `device_code`(设备编码)、`bind_status`(绑定状态)、`bind_user_id`(绑定用户ID)、`online_status`(在线状态)、`last_data_time`(最后数据上报时间) |
|
||||
| `mon_device_config` | 设备监测配置 | 高 — `threshold_min`(阈值下限)、`threshold_max`(阈值上限)、`upload_frequency`(上报频率) |
|
||||
| `mon_bind_record` | 设备绑定/解绑记录 | 中 — `bind_date`(绑定日期)、`unbind_date`(解绑日期) |
|
||||
| `mon_alert_record` | 告警记录 | 中 — `alert_value`(告警值)、`threshold_range`(阈值范围)、GPS 坐标 |
|
||||
| `mon_notification` | 通知消息 | 低 — `send_time`(发送时间)、`notice_status`(通知状态) |
|
||||
|
||||
#### 每日聚合统计(9张表)
|
||||
|
||||
| 表名 | 关键字段 | 脏数据风险 |
|
||||
|------|----------|:--:|
|
||||
| `mon_daily_stats_summary` | `wear_flag`(佩戴标记)、`last_upload_time`(最后上报时间) | 中 |
|
||||
| `mon_daily_stats_heart_rate` | `hr_max`(最大心率)/`hr_min`(最小心率)/`hr_avg`(平均心率)/`hr_latest`(最新心率)、`silence_hr_*`(静息心率) | 高 |
|
||||
| `mon_daily_stats_spo2` | `spo2_max`(最大血氧)/`spo2_min`(最小血氧)/`spo2_avg`(平均血氧)/`spo2_latest`(最新血氧) | 高 |
|
||||
| `mon_daily_stats_stress` | `stress_max`(最大压力)/`stress_min`(最小压力)/`stress_avg`(平均压力)/`stress_latest`(最新压力) | 中 |
|
||||
| `mon_daily_stats_temperature` | `temp_max`(最高体温)/`temp_min`(最低体温)/`temp_avg`(平均体温)/`temp_latest`(最新体温)、`skin_temp_*`(皮肤温度) | 高 |
|
||||
| `mon_daily_stats_blood_pressure` | `systolic_max`(最高收缩压)/`systolic_min`(最低收缩压)、`diastolic_max`(最高舒张压)/`diastolic_min`(最低舒张压) | 高 |
|
||||
| `mon_daily_stats_sleep` | `total_min`(总睡眠时长分钟)、`deep_min`(深睡时长)、`score`(睡眠评分) | 中 |
|
||||
| `mon_daily_stats_exercise` | `steps`(步数)、`exercise_calorie`(运动消耗卡路里)、`steps_distance`(步行距离)、`exercise_distance`(运动距离) | 中 |
|
||||
| `mon_daily_stats_ecg` | `ecg_count`(心电测量次数)、`latest_value`(最新值) | 低 |
|
||||
|
||||
#### 原始监测数据(12张表)
|
||||
|
||||
| 表名 | 关键字段 | 脏数据风险 |
|
||||
|------|----------|:--:|
|
||||
| `mon_data_heart_rate` | `data_value`(心率值bpm)、`silence_value`(静息心率值) | 高 |
|
||||
| `mon_data_spo2` | `data_value`(血氧值%) | 高 |
|
||||
| `mon_data_stress` | `data_value`(压力值)、`start_time`(测量开始时间)、`end_time`(测量结束时间) | 中 |
|
||||
| `mon_data_temperature` | `data_value`(体温值℃)、`skin_value`(皮肤温度) | 高 |
|
||||
| `mon_data_sleep` | `fall_asleep_time`(入睡时间)、`wake_up_time`(醒来时间)、`sleep_score`(睡眠评分) | 中 |
|
||||
| `mon_data_sleep_stage` | `stage_type`(睡眠阶段类型)、`start_time`(开始时间)、`end_time`(结束时间)、`duration`(持续时间) | 中 |
|
||||
| `mon_data_ecg` | `avg_heart_rate`(平均心率)、`arrhy_type`(心律失常类型)、`data_points_url`(数据点文件URL) | 中 |
|
||||
| `mon_data_exercise` | `calorie`(消耗卡路里)、`distance`(运动距离)、`duration`(运动时长) | 中 |
|
||||
| `mon_data_exercise_trace` | `longitude`(经度)、`latitude`(纬度)、`altitude`(海拔) | 中 |
|
||||
| `mon_data_steps` | `step_count`(步数)、`calorie`(消耗卡路里)、`distance`(距离) | 中 |
|
||||
| `mon_data_blood_pressure` | `systolic_value`(收缩压)、`diastolic_value`(舒张压) | 高 |
|
||||
| `mon_data_gps` | `longitude`(经度)、`latitude`(纬度)、`address`(地址) | 中 |
|
||||
|
||||
#### 环境监测(16张表)
|
||||
|
||||
| 类别 | 数据表 | 日数据表 | 月数据表 | 使用记录表 |
|
||||
|------|--------|----------|----------|-----------|
|
||||
| 室内 | `mon_env_data_indoor` | `mon_env_day_data_indoor` | `mon_env_month_data_indoor` | `mon_env_use_record_indoor` |
|
||||
| 室外 | `mon_env_data_outdoor` | `mon_env_day_data_outdoor` | `mon_env_month_data_outdoor` | `mon_env_use_record_outdoor` |
|
||||
| 花粉 | `mon_env_data_pollen` | `mon_env_day_data_pollen` | `mon_env_month_data_pollen` | `mon_env_use_record_pollen` |
|
||||
| 水质 | `mon_env_data_water` | `mon_env_day_data_water` | `mon_env_month_data_water` | `mon_env_use_record_water` |
|
||||
|
||||
附加表:`mon_env_category_indoor/outdoor/pollen/water`(指标类别定义)、`mon_env_meter_info`(环境仪表元数据)、`mon_env_warn_info`(环境告警记录)、`mon_env_warn_sync_record`(告警同步记录)
|
||||
|
||||
#### 调查问卷
|
||||
|
||||
| 表名 | 说明 | 脏数据风险 |
|
||||
|------|------|:--:|
|
||||
| `mon_survey` | 调查主表 | 低 |
|
||||
| `mon_survey_activity` | 调查活动 | 低 |
|
||||
| `mon_survey_answer_record` | 回答记录 | 中 |
|
||||
| `mon_survey_answer_detail` | 回答详情 | 中 |
|
||||
|
||||
### 6.2 系统脏数据检测规则
|
||||
|
||||
> 按原型业务模块分类:健康排查、穿戴监测、体重监测、环境监测
|
||||
|
||||
#### 健康排查(问卷)
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 数据缺失 | 积分字段异常(`mon_survey_answer_record` 无 score 字段,积分在别处计算) | `mon_survey_answer_record` + 积分相关表 | — |
|
||||
| 逻辑矛盾 | 问卷回答时间早于活动发布时间 | `mon_survey_answer_record` ↔ `mon_survey_activity` | 时间字段 |
|
||||
| 重复数据 | 同一用户同一问卷出现多条回答记录 | `mon_survey_answer_record` | `user_id`(用户ID) + `survey_id`(问卷ID) |
|
||||
|
||||
#### 穿戴监测
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 格式错误 | 设备绑定日期格式非法 | `mon_bind_record` | `bind_date`(绑定日期) |
|
||||
| 重复数据 | 同一设备同一时间段出现重复数据记录 | `mon_data_heart_rate` / `mon_data_spo2` / ... | `device_id`(设备ID) + `data_time`(数据时间) |
|
||||
| 范围越界 | 心率值超出人体可能范围(如 <20 或 >300 bpm) | `mon_data_heart_rate` | `data_value`(心率值bpm) |
|
||||
| 范围越界 | 血氧值超出合理范围(如 <50% 或 >100%) | `mon_data_spo2` | `data_value`(血氧值%) |
|
||||
| 范围越界 | 体温值超出人体可能范围(如 <30℃ 或 >45℃) | `mon_data_temperature` | `data_value`(体温值℃) |
|
||||
| 逻辑矛盾 | 静息心率高于活动心率 | `mon_daily_stats_heart_rate` | `silence_hr_avg`(静息心率均值) > `hr_avg`(心率均值) |
|
||||
| 逻辑矛盾 | 设备在线但超过 N 天无数据上报 | `mon_device` | `online_status`(在线状态) + `last_data_time`(最后上报时间) |
|
||||
| 范围越界 | GPS 坐标超出国内范围 | `mon_data_gps` | `longitude`(经度)、`latitude`(纬度) |
|
||||
| 格式错误 | 穿戴设备原始数据 `data_points_url` 指向的 URL 不可访问 | `mon_data_ecg` | `data_points_url`(数据点文件URL) |
|
||||
|
||||
#### 体重监测
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 逻辑矛盾 | 日统计中的最大心率 < 最小心率 | `mon_daily_stats_heart_rate` | `hr_max`(最大心率) < `hr_min`(最小心率) |
|
||||
| 逻辑矛盾 | 日统计中的收缩压 < 舒张压 | `mon_daily_stats_blood_pressure` | `systolic_*`(收缩压) < `diastolic_*`(舒张压) |
|
||||
| 逻辑矛盾 | 睡眠时长 > 24小时 | `mon_daily_stats_sleep` | `total_min`(总睡眠时长) > 1440 |
|
||||
|
||||
#### 环境监测
|
||||
|
||||
| 异常类型 | 检测规则 | 涉及表 | 涉及字段 |
|
||||
|----------|----------|--------|----------|
|
||||
| 逻辑矛盾 | 室内温度高于室外温度超过10℃(且空调未在制热) | `mon_env_data_indoor` + `mon_env_data_outdoor` | 温度字段 |
|
||||
| 范围越界 | 环境温度超出设备量程 | 各环境数据表 | 温度字段 |
|
||||
| 范围越界 | PM2.5 值为负数 | `mon_env_data_indoor` / `mon_env_data_outdoor` | PM2.5 字段 |
|
||||
| 范围越界 | ph 值超出 0-14 范围 | `mon_env_data_water` | `ph`(酸碱度) |
|
||||
| 数据缺失 | 环境监测设备超过 N 天未上报数据 | 各环境数据表 | `read_time`(读取时间) |
|
||||
| 关联缺失 | 环境数据关联的仪表在 `mon_env_meter_info` 中不存在 | 各环境数据表 | `meter_code`(仪表编码) |
|
||||
|
||||
### 6.3 检测频率建议
|
||||
|
||||
| 检测类型 | 建议频率 | 说明 |
|
||||
|----------|----------|------|
|
||||
| 系统脏数据全面扫描 | 每日凌晨 3:00 | 穿戴/环境数据量大,错峰执行 |
|
||||
| 原始数据范围越界检查 | 数据入库时实时 | 在数据接收层做第一道校验 |
|
||||
| 聚合统计一致性检查 | 每日凌晨(聚合任务完成后) | 校验日统计 = 原始数据汇总 |
|
||||
| 设备在线但无数据告警 | 每小时 | `mon_device.online_status` + `last_data_time` |
|
||||
| GPS 坐标越界检查 | 每日凌晨 | 全量扫描 `mon_data_gps` |
|
||||
Reference in New Issue
Block a user