diff --git a/docs/superpowers/specs/2026-04-28-add-data-flicker-batch-design.md b/docs/superpowers/specs/2026-04-28-add-data-flicker-batch-design.md new file mode 100644 index 0000000..9680075 --- /dev/null +++ b/docs/superpowers/specs/2026-04-28-add-data-flicker-batch-design.md @@ -0,0 +1,603 @@ +# 电能质量 13 张表批量补数设计说明 + +## 1. 背景 + +`tools/add-data` 当前只有模块骨架和历史 SQL 文件 [DATA_FLICKER.sql](D:/Work/SourceCode/CN_Tool/tools/add-data/DATA_FLICKER.sql),尚未提供真实业务接口。 + +本次需求是在 `add-data` 模块中补齐一套“按时间区间批量生成电能质量数据并写入数据库”的能力,满足以下业务目标: + +- 支持按时间区间补数,例如一天、一月。 +- 支持时间戳步长选择:`1`、`3`、`5`、`10` 分钟。 +- 支持单监测点和多监测点,前端可选择监测点 ID,默认单监测点。 +- 支持批量写入,优先保证大区间补数时的效率。 +- 同一主键数据已存在时跳过,不覆盖、不删除。 +- 同步提供前端页面交互方案与参数展示规则。 + +## 2. 范围确认 + +根据当前 [DATA_FLICKER.sql](D:/Work/SourceCode/CN_Tool/tools/add-data/DATA_FLICKER.sql) 内容,本次补数范围按 13 张表处理,而不是 14 张表: + +1. `data_flicker` +2. `data_fluc` +3. `data_harmphasic_i` +4. `data_harmphasic_v` +5. `data_harmpower_p` +6. `data_harmpower_q` +7. `data_harmpower_s` +8. `data_harmrate_i` +9. `data_harmrate_v` +10. `data_i` +11. `data_inharm_i` +12. `data_plt` +13. `data_v` + +## 3. 已确认需求 + +本次设计基于以下已确认结论: + +- 写入方式是“按时间戳步长生成整段数据”,不是定时常驻写库。 +- 重复补数时采用“跳过已存在数据”策略。 +- 前端方案需要和后端接口一起设计。 +- 展示字段需要覆盖: + - `电能质量参数名称` + - `相别` + - `是否合格` + - `最大值` + - `最小值` + - `平均值` + - `95%概率大值` + - `数据展示(保留小数)` +- 数值展示默认保留 `2` 位小数。 +- 相别参照用户提供图片中的“相别”列。 + +## 4. 关键约束 + +### 4.1 主键约束 + +13 张表均以 `LINEID + TIMEID + PHASIC_TYPE` 作为主键,重复写入时必须避免主键冲突导致整批失败。 + +### 4.2 相别字段长度约束 + +`PHASIC_TYPE` 字段长度为 `varchar(2)`。因此前端展示中的相别值和数据库实际落库值不能简单等同: + +- 页面展示可使用 `T`、`ABC`、`AB/BC/CA` +- 落库时必须拆分为真实可存储的 `PHASIC_TYPE` + +### 4.3 数据量约束 + +当时间区间为“一月”、步长为“1 分钟”、监测点为“多选”时,补数规模会非常大,不能采用单条插入或一次性全量加载入内存的方式。 + +### 4.4 现有仓库约束 + +- 当前仓库是后端工程,没有现成前端代码,本次只输出前端交互方案和接口契约。 +- 默认不执行 `mvn` 编译、打包、测试。 +- 修改范围应尽量收敛在 `tools/add-data` 模块内。 + +## 5. 方案选择 + +本次比较三种实现路径: + +### 方案 A:同步接口直接写库 + +特点: + +- 控制器接收参数后直接在请求线程中完成全部写库。 +- 实现最简单。 + +问题: + +- 大区间、多监测点时容易超时。 +- 任务执行中断后难以定位进度。 +- 前端体验差,无法明确看到当前执行状态。 + +结论: + +不采用。 + +### 方案 B:异步任务 + JDBC 批量写入 + +特点: + +- 请求只负责创建任务,后台异步执行。 +- 任务状态可轮询。 +- 批量写入时可按表、按批次提交。 + +优势: + +- 更适合月级、多监测点补数。 +- 可以精细控制批次大小。 +- 当前数据源连接串已开启 `rewriteBatchedStatements=true`,适合批处理。 + +结论: + +采用该方案。 + +### 方案 C:只生成 SQL 文件,人工执行 + +特点: + +- 后端只生成 SQL 脚本,不直接写库。 + +问题: + +- 需要人工执行,流程割裂。 +- 不符合“前端选择后直接补数”的目标。 + +结论: + +不采用。 + +## 6. 总体设计 + +### 6.1 设计目标 + +在 `tools/add-data` 中新增一套“批量补数任务”能力,支持: + +- 前端提交补数参数 +- 后端预估本次写入规模 +- 后端异步生成数据并按表批量写入 +- 前端轮询任务状态 +- 前端获取参数展示规则 + +### 6.2 模块边界 + +本次能力只落在 `tools/add-data`,不向 `system`、`user`、`detection` 扩散业务逻辑。 + +如需监测点列表,首版不假设存在基础监测点表,也不新增点位管理能力,直接由前端传入选中的 `lineIds`。 + +### 6.3 接口拆分 + +建议把“任务管理”和“参数模板展示”分成两类接口: + +- 补数任务接口:负责预估、创建、状态查询 +- 模板展示接口:负责返回图片对应的参数展示规则 + +## 7. 数据模型与相别规则 + +### 7.1 展示相别与落库相别分离 + +前端展示相别来自用户图片中的“相别”列,但落库时需要展开成真正的 `PHASIC_TYPE` 值。 + +建议在模板中同时维护: + +- `phaseDisplay`:前端展示值 +- `phaseCodes`:落库使用的真实相别集合 + +### 7.2 相别展开规则 + +建议默认规则如下: + +- `T` -> `["T"]` +- `ABC` -> `["A", "B", "C"]` +- `AB/BC/CA` -> `["AB", "BC", "CA"]` + +这套规则同时用于: + +- 决定每个参数需要展开多少条写库数据 +- 决定前端参数表如何显示相别列 + +### 7.3 参数模板职责 + +参数模板不直接等于数据库表结构,而是承担以下职责: + +- 描述前端展示行 +- 绑定该参数对应的数据表 +- 描述展示相别和落库相别 +- 约定是否展示“是否合格” +- 约定最大值、最小值、平均值、95%概率大值的展示逻辑 +- 约定保留小数位数,默认 `2` + +## 8. 后端接口设计 + +### 8.1 预估接口 + +接口: + +- `POST /addData/task/preview` + +作用: + +- 根据 `lineIds`、时间区间、时间戳步长,返回本次补数的预估规模 + +入参: + +- `lineIds`:监测点 ID 列表 +- `startTime`:开始时间 +- `endTime`:结束时间 +- `intervalMinutes`:`1`、`3`、`5`、`10` + +返回内容: + +- 时间点数量 +- 监测点数量 +- 每张表预估写入条数 +- 总预估条数 + +### 8.2 创建任务接口 + +接口: + +- `POST /addData/task/create` + +作用: + +- 创建一个批量补数任务,并立即进入后台执行 + +入参: + +- `lineIds` +- `startTime` +- `endTime` +- `intervalMinutes` + +返回内容: + +- `taskId` +- 初始状态 + +说明: + +- 前端默认提交单个 `lineId` +- 多监测点时前端直接提交多个 `lineIds` +- 不单独拆分“单点接口”和“多点接口” + +### 8.3 任务状态接口 + +接口: + +- `GET /addData/task/status/{taskId}` + +作用: + +- 供前端轮询当前任务执行状态 + +返回内容: + +- 任务状态:`WAITING`、`RUNNING`、`SUCCESS`、`FAILED` +- 当前执行表名 +- 当前批次信息 +- 已写入条数 +- 已跳过条数 +- 失败条数 +- 失败原因 +- 开始时间、结束时间 + +### 8.4 参数模板接口 + +接口: + +- `GET /addData/template/list` + +作用: + +- 返回前端页面参数规则表所需的静态配置 + +返回内容: + +- 电能质量参数名称 +- 相别展示值 +- 是否展示“是否合格” +- 最大值规则 +- 最小值规则 +- 平均值规则 +- 95%概率大值规则 +- 保留小数位数 + +## 9. 后端分层设计 + +### 9.1 Controller 层 + +建议新增两个控制器: + +- `AddDataTaskController` + - 补数任务相关接口 +- `AddDataTemplateController` + - 参数模板查询接口 + +### 9.2 Service 层 + +建议拆分为: + +- `AddDataTaskService` + - 创建任务 + - 状态查询 + - 预估规模 +- `AddDataTemplateService` + - 返回前端参数模板 + +### 9.3 Component 层 + +建议新增以下组件: + +- `AddDataTaskExecutor` + - 负责异步执行任务 +- `AddDataBatchWriter` + - 负责按表批量写入 +- `AddDataValueGenerator` + - 负责根据模板生成每条记录的值 +- `AddDataTaskStatusHolder` + - 首版用内存保存任务状态 +- `AddDataTemplateRegistry` + - 持有参数模板与相别映射 + +### 9.4 数据访问层 + +本次不建议为 13 张表分别创建超长 MyBatis XML 批量插入语句。 + +原因如下: + +- 宽表字段极多,XML 可维护性差。 +- 13 张表结构差异大,重复代码很多。 +- 本次更偏工具型批处理写数,不适合以业务实体方式逐表建模。 + +建议采用: + +- `JdbcTemplate` +- `PreparedStatement` +- `batchUpdate` + +在写入 SQL 上统一使用: + +- `INSERT IGNORE` + +以满足“跳过已存在数据”的业务要求。 + +## 10. 批量写入策略 + +### 10.1 总体原则 + +批量写入必须满足以下原则: + +- 不先查存在再插入 +- 不整段数据一次性全部放入内存 +- 按表、按批次逐步提交 +- 主键冲突自动跳过 + +### 10.2 跳过已存在数据 + +采用 `INSERT IGNORE` 而不是以下策略: + +- 不采用“先查后写”,避免额外查询放大数据库压力 +- 不采用“覆盖更新”,与已确认需求不符 +- 不采用“先删后写”,避免误删 + +### 10.3 流式生成 + +建议按如下顺序流式生成: + +1. 先遍历时间点 +2. 再遍历监测点 +3. 再按模板展开相别 +4. 最后路由到对应表的批缓存 + +达到批次阈值后立即落库并清空当前缓存。 + +### 10.4 分批阈值 + +建议根据表宽度分层设置批次大小: + +- 窄表:`500 ~ 1000` 行/批 +- 宽表:`100 ~ 200` 行/批 + +其中以下表建议视为宽表: + +- `data_harmphasic_i` +- `data_harmphasic_v` +- `data_harmpower_p` +- `data_harmpower_q` +- `data_harmpower_s` +- `data_harmrate_i` +- `data_harmrate_v` +- `data_i` +- `data_inharm_i` +- `data_v` + +### 10.5 任务统计 + +任务执行过程中需累计以下统计值: + +- `insertedCount` +- `skippedCount` +- `failedCount` + +其中: + +- `insertedCount` 表示本次真正插入成功的行数 +- `skippedCount` 表示因主键重复被忽略的行数 +- `failedCount` 表示非主键冲突导致的失败数量 + +## 11. 数据生成策略 + +### 11.1 首版原则 + +首版不引入复杂公式配置,不让前端传计算表达式。数据生成规则由后端内置。 + +### 11.2 生成方式 + +建议采用“基准值 + 受控扰动 + 派生字段回填”的方式生成数据: + +- 主值字段按基准值和随机扰动生成 +- 最大值字段不小于平均值 +- 最小值字段不大于平均值 +- `95%概率大值` 对应 `CP95` 字段 +- 宽表中的谐波分量和派生列按统一规则回填 + +### 11.3 质量标识 + +`QUALITYFLAG` 首版建议统一使用固定有效值,例如 `1`。 + +前端“是否合格”不直接读取数据库 `QUALITYFLAG` 的原始含义,而是走模板展示规则,避免把数据生成逻辑和展示文案硬耦合。 + +## 12. 前端页面交互方案 + +### 12.1 页面结构 + +建议页面分为两个区域: + +1. 补数任务区 +2. 参数规则展示区 + +### 12.2 补数任务区 + +表单项建议如下: + +- 监测点选择模式:`单点` / `多点` +- 监测点 ID 选择框 +- 开始时间 +- 结束时间 +- 时间戳步长:`1`、`3`、`5`、`10` 分钟 +- 预计写入量按钮 +- 开始补数按钮 + +交互说明: + +- 默认单监测点 +- 多监测点时切换为多选 +- 前端先调用预估接口,展示预计写入规模 +- 用户确认后再调用创建任务接口 + +### 12.3 任务状态展示 + +前端创建任务后轮询状态接口,建议展示: + +- 当前状态 +- 当前表名 +- 已写入数量 +- 已跳过数量 +- 失败数量 +- 失败原因 +- 开始时间 +- 结束时间 + +### 12.4 参数规则展示区 + +参数规则表按用户提供图片组织,至少展示以下列: + +- `电能质量参数名称` +- `相别` +- `显示` +- `最大值` +- `最小值` +- `平均值` +- `95%概率大值` +- `是否合格` +- `数据展示(保留小数)` + +其中: + +- 相别列使用 `phaseDisplay` +- 所有数值默认保留 `2` 位小数 +- 该表展示的是模板规则,不是实时数据库统计结果 + +## 13. 文件结构建议 + +建议在 `tools/add-data` 下按现有仓库风格扩展: + +```text +tools/add-data/src/main/java/com/njcn/gather/tool/adddata/ +├── controller +│ ├── AddDataTaskController.java +│ └── AddDataTemplateController.java +├── service +│ ├── AddDataTaskService.java +│ ├── AddDataTemplateService.java +│ └── impl +│ ├── AddDataTaskServiceImpl.java +│ └── AddDataTemplateServiceImpl.java +├── component +│ ├── AddDataTaskExecutor.java +│ ├── AddDataBatchWriter.java +│ ├── AddDataValueGenerator.java +│ ├── AddDataTaskStatusHolder.java +│ └── AddDataTemplateRegistry.java +└── pojo + ├── param + └── vo +``` + +如参数模板需落成资源文件,建议放在: + +- `tools/add-data/src/main/resources/template/add-data-parameter-template.json` + +## 14. 非目标 + +本次不包含以下内容: + +- 不新增监测点基础信息管理能力 +- 不新增监测点字典表 +- 不新增数据库迁移框架 +- 不在 `system` 或 `user` 模块中扩展通用任务中心 +- 不实现真实前端页面代码 +- 不做覆盖更新或先删后写逻辑 + +## 15. 风险与取舍 + +### 15.1 内存态任务状态的风险 + +首版如果使用内存保存任务状态: + +- 服务重启后任务状态会丢失 +- 适合当前工具型场景 +- 不适合后续演进为长期审计能力 + +当前取舍: + +- 首版接受该限制 +- 如果后续需要审计与追踪,再补任务表 + +### 15.2 模板与真实表字段映射的风险 + +用户图片中的参数项比“13 张表名”更偏业务视角,实际落库需要一层参数模板到表结构的映射。 + +当前取舍: + +- 首版把模板规则集中维护在 `AddDataTemplateRegistry` +- 不在前端直接拼接数据库字段名 + +### 15.3 大批量写入的数据库压力 + +多监测点、长区间、1 分钟步长时数据库压力会很大。 + +当前取舍: + +- 采用预估接口提前提示规模 +- 控制批次大小 +- 使用异步执行与 `INSERT IGNORE` + +## 16. 验证方式 + +本次设计和后续实现默认不执行 `mvn`,验证方式以静态检查和链路闭合检查为主。 + +### 16.1 设计验证 + +确认以下设计点闭合: + +- 13 张表范围明确 +- 相别展示与落库规则明确 +- 重复数据处理策略明确 +- 前后端接口契约明确 +- 批量写入策略明确 + +### 16.2 实现后验证 + +后续实现时重点检查: + +- 入参校验是否覆盖时间区间、步长、监测点 ID 列表 +- 预估条数计算是否正确 +- SQL 是否统一使用 `INSERT IGNORE` +- 批次是否按宽表和窄表区分 +- 重复补数时是否正确累加 `skippedCount` +- 参数模板返回是否与图片字段一致 + +## 17. 结论 + +本次采用“异步任务 + JDBC 批量写入 + 参数模板展示接口”的实现方案,在 `tools/add-data` 模块内完成电能质量 13 张表的批量补数能力。 + +该方案兼顾以下目标: + +- 支持单监测点和多监测点 +- 支持日级、月级区间 +- 支持 1/3/5/10 分钟时间戳步长 +- 支持重复补数时跳过已存在数据 +- 支持前端按图片规则展示参数和相别 +- 在当前仓库约束下把改动范围控制在最小必要集合