|
|
3 روز پیش | |
|---|---|---|
| .. | ||
| fixtures | 3 روز پیش | |
| screenshots | 3 روز پیش | |
| README.md | 3 روز پیش | |
| generate_fixtures.py | 3 روز پیش | |
验证本轮改造在真实案件、真实数据源上的表现:
| 项 | 值 |
|---|---|
| 后端 | ai-server,http://127.0.0.1:8980/js/a |
| 前端 | http://localhost:3100 |
| 案件 | 新建 AI清洗验收-20261022(案件 id 10) |
| 登录 | 开发环境默认 admin |
| 迁移 | 已执行 sql/ai_clean_row_stats.sql(否则 ai_clean_batch.loaded_rows 等列不存在,智能清洗 500) |
自动化环境限制:ZCode 内置浏览器不支持系统文件选择框。样本通过页面同源的
POST /dm/preFileUpload(携带页面登录 token)注入;随后 智能清洗、导入文件列表、 数据页、失败明细弹窗全部在界面里操作/核对。在普通浏览器里可直接用「选择文件」。
样本在 fixtures,可用 generate_fixtures.py 重新生成。
| 文件 | 内容 | 目的 |
|---|---|---|
01_self_built_types.xlsx |
标题行 + 空行 + 9 列表头 + 7 行数据(含各类脏值、空行隔断) | 自建表类型推断、日期/金额/数字/证件转换、row_no 缺口 |
02_reordered_headers.xlsx |
与 01 同表头但倒序 | 模板复用必须同序(单测覆盖,UI 未跑) |
03_messy_title_blank.xlsx |
单格标题 + 空行 + 表头 + 4 行数据(其中一行坏金额/日期) | 表头定位、标题/空行不阻塞、坏值置空 |
04_csv_types.csv |
与 01 同数据,UTF-8 CSV | CSV 探测/入库;可选列脏值只置空 |
05_required_bad.xlsx |
同 9 列表头,20 行;第 1 行身份证 12345 非法 |
必填列坏值整行拒绝 + 失败明细 |
06_csv_clean.csv |
同 9 列表头,7 行全合法 | CSV 正常入库 |
01 的 9 列与脏值覆盖:
张三/李四/...12345+86 139-0000-1111、1236222 0202 ...、科学计数法 6.22202E+152026/1/6、2026年1月7日、2026-02-30、Excel 序列号 45000、紧凑 2026010810:30、25:00、epoch 17040672001,234.50、-100.00、(200.50)、约100元、¥2,300.5、100元1.5、abc01 → 智能清洗(无候选 → 出口 B 自建表)。loadedRows=7, rejectedRows=0, warned=2, selfBuiltCount=1;AI 表「经营者信息」7 行。ai_clean_field):
ID_CARD_NUMBER、c2 手机号 PHONE、c3 银行卡号 ACCT_CARD_NO(物理 TEXT)DATE、c5 交易时间 DATE_TIME(TIMESTAMP)MONEY(DECIMAL(18,2))、c7 数量 NUMBER(DECIMAL(38,6))、c8 备注 TEXT2026-01-07;金额 (200.50) → -200.50;数量 1.5。13800002222、卡号正常入库。45000 → 2023-03-15;1704067200 → 2024-01-01 08:00:00;¥2,300.5 → 2,300.50。20260108 → 2026-01-08;100元 → 100.00。row_no 保留原文件物理行号。c1(身份证号)临时改为 required=1。05(20 行,第 1 行身份证 12345)→ 智能清洗(指纹命中同一 AI 模板,出口 B 复用)。loadedRows=19, rejectedRows=1, unprocessedRows=0;job rowTotal=20, rowLoaded=19, rowRejected=1。失败明细接口:
{"row_no":2,"blocking_col_index":1,"blocking_col_name":"c1",
"reason":"REQUIRED_TYPE_INVALID",
"errors_json":"[{\"colIndex\":1,\"column\":\"c1\",\"reason\":\"REQUIRED_TYPE_INVALID\",\"value\":\"12345\",\"blocking\":true}]"}
界面:导入文件列表 → 展开文件 → 工作表行「导入失败 1」→ 弹窗显示:
c1(列 1)、原因「必填列类型不合法」、原值预览 12345后置:required 已重置为 0,避免影响后续样本。
headerScore=1.0),但抽样校验因身份证列
2/7=28.6% 非法(非必填)判 待人工。loadedRows=7, rejectedRows=0, warned=2,复用同一 AI 模板。rowWarned/detail.load.optional,不阻塞行。06 → 智能清洗(指纹命中 AI 模板)。loadedRows=7, rejectedRows=0, selfBuiltCount=0。SheetProbe 用 POI 拒之门外。03 → 智能清洗(无候选 → 自建表「人员交易」)。loadedRows=4, rejectedRows=0;坏金额/日期两列置空,行保留。最终导入文件列表(import-list-5-files.png):
| 文件 | 导入成功 | 导入失败 |
|---|---|---|
| 06_csv_clean.csv | 7 | 0 |
| 03_messy_title_blank.xlsx | 4 | 0 |
| 04_csv_types.csv | 7 | 0 |
| 05_required_bad.xlsx | 19 | 1 |
| 01_self_built_types.xlsx | 7 | 0 |
数据页(ai-table-40-rows.png):
mvn -pl ai-server -Dtest='com.zsjz.ai.module.aiclean.**.*Test,com.zsjz.ai.module.dm.**.*Test' test:
192 个用例通过(5 个 live 跳过)。覆盖:
AiValueCoercer 日期/时间/金额/数字/电话/身份证/卡号格式矩阵HeaderScorer 同义词/列序/单位/形状/必填覆盖与出口 A 闸门sameOrderedHeaders 复用安全AiRuleVerifier 用 cleanRow 的全部错误计算列错误率,
可选身份证列 28.6% 非法导致整表转人工。修复:cleanRow 只回填阻塞错误,
cleanRowDetailed 仍保留全部错误供 warned/明细统计(提交 c4b167b)。aiJobId/cleanMode,点「导入失败」只能走旧
clean_error_log。修复:单 sheet 文件把 sheet 的 AI 任务信息带到文件行(提交 c4b167b)。ai_clean_batch.loaded_rows 等新列未建时智能清洗 500;必须执行
sql/ai_clean_row_stats.sql。HeaderScorerTest / AiTemplateMatcherTest 覆盖;恢复 LLM 后建议再跑一次真实模型样本。02_reordered_headers.xlsx:需要 LLM 重新绑定,本次 UI 未跑;sameOrderedHeaders
单测已钉住「列序变化不复用旧 colIndex」。02 之外的乱序/合并样本
待 Phase B 后续。header_md5 全局唯一键尚未改案件作用域,本轮未做双案件并发验收。sql/ai_clean_row_stats.sql。mvn -pl ai-server spring-boot:run;启动前端 pnpm dev。fixtures/ 下样本(普通浏览器可直接选择文件)。POST /js/a/aiClean/smartClean。必填拒绝用例:先让 01 生成 AI 模板,再执行
update ai_clean_field set required=1
where ai_template_id = :tpl and column_name = 'c1';
上传 05_required_bad.xlsx 并智能清洗;验收后把 required 重置为 0。