Explorar el Código

feat(aiclean): ai_clean_rule 增加 field_name_cn 列头中文名

- 建表语句与实体新增 field_name_cn;已有库用 sql/ai_clean_rule_field_name_cn.sql 幂等补列(升级代码前必须先执行,否则规则登记会报列不存在)
- 规则写入处(loadViaAiTemplate)从对应的 AiCleanField.fieldNameCn 取值,空则存 null
- 真库往返测试补充 field_name_cn 断言;顺带把测试里过期的 field_name_en(trans_date -> c0,该列自 2026-10-18 起为 varchar(5) 的物理列名)修正
cc hace 2 días
padre
commit
7d5f6b7f52

+ 7 - 0
ai-server/src/main/java/com/zsjz/ai/module/aiclean/entity/AiCleanRule.java

@@ -50,6 +50,13 @@ public class AiCleanRule implements Serializable {
     @TableField("field_name_en")
     private String fieldNameEn;
 
+    /**
+     * 列头中文名,与 {@code ai_clean_field.field_name_cn} 同源;
+     * 表头为空或没有中文名时为空
+     */
+    @TableField("field_name_cn")
+    private String fieldNameCn;
+
     /**
      * 扁平提示 JSON 数组
      */

+ 2 - 0
ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanService.java

@@ -569,6 +569,8 @@ public class AiCleanService {
                 AiCleanRule r = new AiCleanRule();
                 r.setColIndex(f.getColIndex());
                 r.setFieldNameEn(f.getFieldNameEn());
+                // 列头中文名与字段登记(ai_clean_field.field_name_cn)保持一致;没有中文名就存 null
+                r.setFieldNameCn(StrUtil.isBlank(f.getFieldNameCn()) ? null : f.getFieldNameCn());
                 r.setHints(AiCleanStore.hintsJson(bind == null ? List.of() : bind.getHints()));
                 r.setVer(1);
                 ruleRows.add(r);

+ 6 - 2
ai-server/src/test/java/com/zsjz/ai/module/aiclean/AiCleanPgRoundTripTest.java

@@ -75,7 +75,8 @@ class AiCleanPgRoundTripTest {
             AiCleanField f = new AiCleanField();
             f.setColumnName("c0");
             f.setFieldNameCn("交易日期");
-            f.setFieldNameEn("trans_date");
+            // 2026-10-18 起 field_name_en 就是物理列名 c0/c1(列宽 varchar(5)),不再是语义英文名
+            f.setFieldNameEn("c0");
             f.setFieldType("DATE");
             f.setRequired(1);
             f.setFieldLen(0);
@@ -84,7 +85,8 @@ class AiCleanPgRoundTripTest {
 
             AiCleanRule r = new AiCleanRule();
             r.setColIndex(0);
-            r.setFieldNameEn("trans_date");
+            r.setFieldNameEn("c0");
+            r.setFieldNameCn("交易日期");
             r.setHints("[\"EXTRACT_NAMED:MOBILE_CN\"]");
 
             Long id = store.register(tpl, List.of(f), List.of(r));
@@ -102,6 +104,8 @@ class AiCleanPgRoundTripTest {
                     .eq(AiCleanRule::getAiTemplateId, id));
             assertEquals(1, rules.size());
             assertEquals("[\"EXTRACT_NAMED:MOBILE_CN\"]", rules.getFirst().getHints());
+            // 列头中文名要能原样落库、读回(2026-10-28 新增列)
+            assertEquals("交易日期", rules.getFirst().getFieldNameCn());
         } finally {
             cleanUp();
         }

+ 1 - 0
sql/ai_clean.sql

@@ -82,6 +82,7 @@ create table if not exists ai_clean_rule
     ai_template_id bigint,                                -- 出口 B 挂模板;出口 A 的快照可空(挂 job)
     col_index      integer    not null,
     field_name_en  varchar(200),
+    field_name_cn  varchar(200),                          -- 列头中文名;表头为空/没有中文名时为 null
     hints          text,                                   -- 枚举 hint 的 JSON 数组,如 ["TRIM","UNIT_SCALE:WAN"]
     ref_template_id integer,                              -- 出口 A:命中的既有 table_info.id
     ver            integer   default 1,

+ 12 - 0
sql/ai_clean_rule_field_name_cn.sql

@@ -0,0 +1,12 @@
+-- ============================================================================
+-- ai_clean_rule:新增 field_name_cn(列头中文名)  (2026-10-28)
+--
+-- 背景:规则表原先只有 field_name_en(AI 动态表的物理列 c0/c1…),
+-- 排查与展示时看不到对应的中文列名。新增 field_name_cn,与
+-- ai_clean_field.field_name_cn 同源;表头为空或没有中文名时存 null。
+--
+-- 本脚本用于**已存在的** AI 元数据表;新环境直接按 ai_clean.sql 建表即可。
+-- 幂等,可重复执行。
+-- ============================================================================
+
+alter table ai_clean_rule add column if not exists field_name_cn varchar(200);