# 风险因子设置 — 技术方案 > 依据:同目录 `风险因子设置功能需求.md`。本模块为**全局单套**风险因子权重配置:**查询 + 保存**(非分页台账 CRUD);五项权重须为正数且合计为 **1**。 --- ## 1. 技术架构 | 项 | 说明 | | --- | --- | | **后端** | RuoYi **v3.9.2**(**springboot2** 分支):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid | | **数据库** | MySQL **5.7.39**,InnoDB,`utf8mb4` | | **前端** | 若依 Vue2;权重小数录入;页面实时展示五项合计 | | **代码包** | `com.ruoyi.web.modules.diseasedetection`(建议,与疫情上报、实验室检测同域) | **分层**:`Controller`(`@PreAuthorize`、`AjaxResult`)→ `Service`(权重正数、合计为 1 校验)→ `Mapper`/XML → `domain`。 **业务特征(摘要)** | 场景 | 行为 | | --- | --- | | 查询 | 返回当前生效的一套五项权重;无记录时可返回默认值或空对象(与产品约定) | | 保存 | Body 一次性提交五项;服务端校验后 **UPDATE** 唯一配置行(无记录则 **INSERT**) | | 因子项 | **固定五项**,不落因子字典表;字段名与 **§2.4** 一一对应 | --- ## 2. 数据库设计 ### 2.1 表 `biz_risk_factor_weight`(风险因子权重配置) 全局**单行**配置表(`id = 1`);不按区划、不按版本分多套。 | 字段 | 类型 | 非空 | 说明 | | --- | --- | --- | --- | | `id` | `bigint(20)` | Y | 主键;固定 **`1`**(单例) | | `weight_breeding_density` | `decimal(8,4)` | Y | 养殖密度权重,> 0 | | `weight_traffic_mobility` | `decimal(8,4)` | Y | 交通流动性权重,> 0 | | `weight_quarantine_intensity` | `decimal(8,4)` | Y | 检疫强度权重,> 0 | | `weight_meteorological_suitability` | `decimal(8,4)` | Y | 气象适宜度权重,> 0 | | `weight_past_disease_level` | `decimal(8,4)` | Y | 既往发病水平权重,> 0 | | `create_by` / `create_time` / `update_by` / `update_time` | 若依惯例 | — | 审计 | **约束(业务层实现)** - 五项之和 = **1**(建议容差 `|Σ − 1| ≤ 0.0001`,与 `decimal(8,4)` 一致)。 - 各项 **> 0**(正数)。 - 不提供 `del_flag`;配置始终有效。 ### 2.2 DDL(MySQL 5.7) ```sql CREATE TABLE `biz_risk_factor_weight` ( `id` bigint(20) NOT NULL COMMENT '主键固定1', `weight_breeding_density` decimal(8,4) NOT NULL COMMENT '养殖密度权重', `weight_traffic_mobility` decimal(8,4) NOT NULL COMMENT '交通流动性权重', `weight_quarantine_intensity` decimal(8,4) NOT NULL COMMENT '检疫强度权重', `weight_meteorological_suitability` decimal(8,4) NOT NULL COMMENT '气象适宜度权重', `weight_past_disease_level` decimal(8,4) NOT NULL COMMENT '既往发病水平权重', `create_by` varchar(64) DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_by` varchar(64) DEFAULT '' COMMENT '更新者', `update_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='风险因子权重配置'; -- 初始化(可选):五项各 0.2 INSERT INTO `biz_risk_factor_weight` ( `id`, `weight_breeding_density`, `weight_traffic_mobility`, `weight_quarantine_intensity`, `weight_meteorological_suitability`, `weight_past_disease_level`, `create_by`, `create_time` ) VALUES ( 1, 0.2000, 0.2000, 0.2000, 0.2000, 0.2000, 'admin', NOW() ) ON DUPLICATE KEY UPDATE `id` = `id`; ``` ### 2.3 因子编码(固定,与功能需求 §2.1 对应) | 编码 | 因子名称 | 库字段 | API 驼峰 | | --- | --- | --- | --- | | `breeding_density` | 养殖密度 | `weight_breeding_density` | `breedingDensityWeight` | | `traffic_mobility` | 交通流动性 | `weight_traffic_mobility` | `trafficMobilityWeight` | | `quarantine_intensity` | 检疫强度 | `weight_quarantine_intensity` | `quarantineIntensityWeight` | | `meteorological_suitability` | 气象适宜度 | `weight_meteorological_suitability` | `meteorologicalSuitabilityWeight` | | `past_disease_level` | 既往发病水平 | `weight_past_disease_level` | `pastDiseaseLevelWeight` | **响应可冗余**:`weightSum`(五项之和,便于前端核对)、`updateTime` 等。 --- ## 3. 接口设计 **统一响应**:`AjaxResult`(`code` / `msg` / `data`)。 **权限标识**:`diseaseDetection:riskFactorWeight:query|edit` **Base Path**:`/diseaseDetection/riskFactorWeight` | # | 说明 | Method | URI | 权限 | 要点 | | --- | --- | --- | --- | --- | --- | | 3.1 | 获取当前权重 | GET | `/diseaseDetection/riskFactorWeight` | `...:query` | 返回 **§3.1.1**;无记录时 `data` 为 `null` 或默认五项 | | 3.2 | 保存权重 | PUT | `/diseaseDetection/riskFactorWeight` | `...:edit` | Body **§3.2.1**;校验通过后 upsert `id=1` | > 不提供分页 `list`、按 `id` 删除;菜单权限可用 `query` 进入页面,`edit` 控制保存。 #### 3.1.1 查询响应 `data`(示例) ```json { "breedingDensityWeight": 0.2, "trafficMobilityWeight": 0.2, "quarantineIntensityWeight": 0.2, "meteorologicalSuitabilityWeight": 0.2, "pastDiseaseLevelWeight": 0.2, "weightSum": 1.0, "updateBy": "admin", "updateTime": "2026-05-19 10:00:00" } ``` #### 3.2.1 保存 Body(JSON,驼峰) | 字段 | 必填 | 说明 | | --- | --- | --- | | `breedingDensityWeight` | Y | > 0 | | `trafficMobilityWeight` | Y | > 0 | | `quarantineIntensityWeight` | Y | > 0 | | `meteorologicalSuitabilityWeight` | Y | > 0 | | `pastDiseaseLevelWeight` | Y | > 0 | 五项之和须 **= 1**(容差见 **§2.1**);非法则返回业务错误,**不**部分更新。 ### 3.3 服务端校验(摘要) | 项 | 规则 | | --- | --- | | 正数 | 每项 `> 0`,且为合法 `decimal` | | 合计 | `sum(五项) = 1`(`|Σ − 1| ≤ 0.0001`) | | 原子性 | 一次请求更新全部五个字段 | | 单例 | 仅维护 `id = 1` 一行 | 校验类建议:`RiskFactorWeightValidation`(`validateForSave`)。 --- ## 4. 菜单与权限(示例) | 类型 | 名称 | 权限标识 | | --- | --- | --- | | 菜单 | 风险因子权重 | `diseaseDetection:riskFactorWeight:query` | | 按钮 | 保存 | `diseaseDetection:riskFactorWeight:edit` | 组件路径建议:`diseaseDetection/riskFactorWeight/index`(单页表单 + 保存按钮)。 **菜单 SQL 示例**(挂「疾病检测与上报」目录 `2110` 下,ID 按需调整): ```sql INSERT INTO sys_menu VALUES ('2113', '风险因子权重', '2110', '3', 'riskFactorWeight', 'diseaseDetection/riskFactorWeight/index', '', '', 1, 0, 'C', '0', '0', 'diseaseDetection:riskFactorWeight:query', 'slider', 'admin', sysdate(), '', NULL, '风险因子权重'); INSERT INTO sys_menu VALUES ('21131', '风险因子保存', '2113', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'diseaseDetection:riskFactorWeight:edit', '#', 'admin', sysdate(), '', NULL, ''); ``` --- ## 5. 交付清单 - [ ] `sql/biz_risk_factor_weight.sql`、初始化数据、菜单权限 SQL - [ ] `BizRiskFactorWeight` Domain / Mapper / Service / Controller - [ ] `RiskFactorWeightValidation`(正数、合计为 1) - [ ] 前端:单页五项录入、实时合计、保存 - [ ] 单元/接口测试:和不为 1、某项 ≤ 0、首次保存 insert、再次保存 update --- ## 6. 修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初稿:单表单行配置;GET + PUT;五项固定字段 |