# AssessReport 迁移方案(从 GetData.asmx.cs → yudao-server) ## 1. 旧接口梳理(assessReport.html 实际调用) | 原方法 | 主要入参 | 返回 | 涉及表 / 处理 | | --- | --- | --- | --- | | `GetCondition(algorithm)` | `algorithm` | JSON(含 `model_score`、模式条件) | `model_condition` | | `GetInfoV(p, version)` | 模型 ID、版本 | `Model_Info` JSON、点表 `pointInfo`、`trainTime` 等 | `model_view` / `model_version` | | `GetReport(ID)` | 报告 ID | `report` JSON、`Model_Name` | 视图 `Assess_Report_View` | | `GetModelDiagnosis_reverse_new(json, assess, alg, modelInfo)` | 评估请求体(点、幅度、限值、时间窗)、`alg`、`modelInfo` | 正/反向 `fdr/far/recon`、清洗耗时 | 调用外部 EXA/Python 服务 | | `LF_GetAlgById(id)` | 模型 ID | 算法简称 | `MODEL_VIEW` | | `insertReport(...)` | `report` JSON、模型/版本、得分、覆盖率、验证人、时间等 | bool | `Assess_Report_CFG` | | `GetEXACleanDataMessagech(id, time, version)` | 模型 ID、时间范围、版本 | 清洗汇总(dead/limits/condition/envelopes) | 外部 Python `/api/test/clean_data` | | `GetClrMsgDeadDtlch(item, time)` | 点号列表、时间段 | 死区清洗成功/占比 | EXA 清洗 | | `GetConditionClrRateCH(condition, st, et)` | 模式条件、时间窗 | 各条件有效样本比 | EXA 历史数据 | | `GetEnvelopesClrRateCH(condition, st, et)` | 包络条件、时间窗 | 各条件有效样本比 | EXA 历史数据 | ## 2. 新 REST 设计(建议) Base Path:`/alert/assess-report` - `GET /init`:入参 `modelId`、`version`、可选 `reportId/timeRange`。返回模型信息、点表、模式信息、默认参与预警点、底线分数。 - `GET /report/{id}`:读取历史报告。 - `POST /evaluate`:入参 `AssessEvaluateRequest`(点表、幅度、时间窗、模式),返回正/反向 `fdr/far/recon`、覆盖率、耗时。 - `POST /`:保存评估报告(包含得分、覆盖率、是否投入、报告 JSON)。 - `GET /clean/summary`:获取清洗汇总(对应 `GetEXACleanDataMessagech`)。 - `GET /clean/dead`:按点号返回死区清洗占比/结果。 - `GET /clean/condition-rate`、`/clean/envelope-rate`:模式/包络有效样本占比。 - `GET /condition`:按算法返回评估底线、模式条件。 ## 3. Controller / Service / Mapper 代码骨架(yudao 风格) ```java // controller/admin/model/AssessReportController.java @RestController @RequestMapping("/alert/assess-report") @RequiredArgsConstructor public class AssessReportController { private final AssessReportService assessReportService; @GetMapping("/init") public CommonResult init(AssessInitReqVO reqVO) { return success(assessReportService.init(reqVO)); } @GetMapping("/report/{id}") public CommonResult detail(@PathVariable Long id) { return success(assessReportService.getReport(id)); } @PostMapping("/evaluate") public CommonResult evaluate(@RequestBody AssessEvaluateReqVO reqVO) { return success(assessReportService.evaluate(reqVO)); } @PostMapping public CommonResult save(@RequestBody AssessReportCreateReqVO reqVO) { return success(assessReportService.saveReport(reqVO)); } @GetMapping("/clean/summary") public CommonResult cleanSummary(AssessCleanQueryReqVO reqVO) { return success(assessReportService.cleanSummary(reqVO)); } } ``` ```java // service接口 public interface AssessReportService { AssessInitRespVO init(AssessInitReqVO reqVO); AssessReportDetailVO getReport(Long id); AssessEvaluateRespVO evaluate(AssessEvaluateReqVO reqVO); Boolean saveReport(AssessReportCreateReqVO reqVO); AssessCleanSummaryVO cleanSummary(AssessCleanQueryReqVO reqVO); } // service实现关键片段 @Service @RequiredArgsConstructor public class AssessReportServiceImpl implements AssessReportService { private final AssessReportMapper assessReportMapper; private final ModelMapper modelMapper; private final RemoteExaClient remoteExaClient; // 封装 EXA/Python HTTP 调用 @Override public AssessInitRespVO init(AssessInitReqVO reqVO) { // 1) 模型信息&版本解析;2) pointInfo 过滤 lock=false; 3) 构造默认 assess 列表 // 4) 读取底线 model_score } @Override public AssessEvaluateRespVO evaluate(AssessEvaluateReqVO reqVO) { // 组织 payload 适配原 json(Test_Data、dead/limit/uplow、number_fault_variable 等) // 调用 remoteExaClient.assess(...); 映射回 fdr/far/recon } @Override public Boolean saveReport(AssessReportCreateReqVO reqVO) { AssessReportDO report = AssessReportConvert.INSTANCE.convert(reqVO); return assessReportMapper.insert(report) > 0; } } ``` ```java // 数据对象 & Mapper @TableName("alert_assess_report") @Data public class AssessReportDO extends BaseDO { @TableId private Long id; private Long modelId; private String version; private String reportJson; private BigDecimal score; private BigDecimal coverRange; private String validFlag; // '是'/'否' private String identifier; private String verifier; private LocalDateTime assessTime; private String conditionName; } @Mapper public interface AssessReportMapper extends BaseMapperX { } ``` ## 4. MySQL 表结构建议 ```sql CREATE TABLE alert_assess_report ( id BIGINT PRIMARY KEY AUTO_INCREMENT, model_id BIGINT NOT NULL, version VARCHAR(64) NOT NULL, report_json JSON NOT NULL, score DECIMAL(8,2) NOT NULL, cover_range DECIMAL(8,4) DEFAULT 0, valid_flag CHAR(1) DEFAULT '0', -- 1:是,0:否 identifier VARCHAR(64) NOT NULL, verifier VARCHAR(64), assess_time DATETIME NOT NULL, condition_name VARCHAR(128), creator VARCHAR(64), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, updater VARCHAR(64), update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); CREATE TABLE alert_model_condition ( id BIGINT PRIMARY KEY AUTO_INCREMENT, algorithm VARCHAR(32) NOT NULL, condition_text TEXT, model_score DECIMAL(8,2), UNIQUE KEY uk_alg (algorithm) ); ``` 视图/版本:`model_view`、`model_version` 迁移到 MySQL 后保留字段 `model_info` (JSON)、`cur_version` 等即可支撑 init 查询。 ## 5. T-SQL → MySQL 改写要点 - `SELECT TOP 1 ... ORDER BY` → `SELECT ... ORDER BY ... LIMIT 1` - `NVARCHAR` → `VARCHAR`,`DATETIME` 兼容;`bit` → `tinyint(1)`;`float` → `double` - 日期加减:`DATEADD(hour, -24, GETDATE())` → `DATE_SUB(NOW(), INTERVAL 24 HOUR)` - 字符拼接:`'a' + b` → `CONCAT('a', b)` - 布尔:`true/false` 改为 `1/0` ## 6. 清洗/评估逻辑迁移提示 - EXA/Python 调用封装在 `RemoteExaClient`,使用 `WebClient`/`RestTemplate`,增加超时、异常转译(返回 `CommonResult`)。 - 模式/包络有效样本占比 `GetConditionClrRateCH`、`GetEnvelopesClrRateCH` 可重写为:查询历史表(时间戳+值),在 Java 端计算满足条件的计数后返回数组。 - 报告得分计算(前端已有,同步可在服务端实现确保导出一致性)。 ## 7. 统一返回与异常 - 统一 `CommonResult`,非法参数返回 `PARAMS_ERROR`,外部服务异常包装为 `INTERNAL_SERVER_ERROR`。 - 导出/下载接口可返回临时文件 token 或直流写出。