Commit d83cf947 authored by Data Governance Dev's avatar Data Governance Dev

docs(worklog): 自定义规则 v2 条件树改造 + 端到端联调 3 bug 修复记录

- 记录需求、设计决策(多层递归 / 日期只支持具体日期 / 3 类字段 7 算子)
- 记录 3 个新后端文件职责 + step9 重构 + NUMERIC_TYPES / DATE_TYPES + orchestrator 兼容
- 记录前端 UI 重构(递归组件 <condition-tree> + field-block 排版 + addCustomRule 透传)
- 记录端到端联调 3 个 bug 修复:
  1. fieldClassTagType 未 setup return 导致渲染崩溃
  2. 字段注释 / 表注释没显示(row 不带 → 兜底查 tableSummary)
  3. orchestrator 只认旧 payload user_input,v2 group 树不追加 custom_value_check 步骤
parent cd2c1475
...@@ -2,6 +2,118 @@ ...@@ -2,6 +2,118 @@
> 任务做完一次记一次。最近的在最上面。 > 任务做完一次记一次。最近的在最上面。
## 2026-08-12 · 自定义规则 v2:字段类型分类 + 递归条件树
### 需求
> 用户反馈:「修改自定义规则,首先给字段分类,先只分成三类,字符类、数值类、日期类;然后在规则处可以增加多个规则,增加规则是树形结构,条件的每一个层级内部可以选择用AND或者OR连接,增加层级则是类似SQL中的增加括号;然后字符类规则目前只有包含,添加不包含,数值类添加大于、小于、等于,日期类添加规定日期以前和以后」
原版只支持 `字段包含关键字`(单条 LIKE),无法表达 `数值大于10且不等于0且(小于100或大于200)` 这种复合条件。
### 设计决策(用户已确认)
1. **多层递归嵌套**:每条规则 = 一棵树,组里可嵌套组(类似 SQL 加括号),连接符每层可选 AND/OR
2. **日期只支持具体日期**(`YYYY-MM-DD`),不支持相对日期 `today / -7d`
3. **3 类字段 → 7 种叶子比较符**:
- text (varchar/char/text/clob/...): `contains` / `not_contains`
- numeric (int/decimal/number/...): `gt` / `lt` / `eq`
- date (date/datetime/timestamp/...): `date_before` (`<`) / `date_after` (`>`)
### 新增 3 个后端文件
**`web/core/rule_types.py`** — 字段类型分类 + 比较符常量
- `classify_field(data_type)` → 'text' | 'numeric' | 'date' | 'unknown'
- `COMPARATORS_BY_CLASS` / `DEFAULT_COMPARATOR` / `INPUT_HINT_BY_CLASS`
- `is_like_comparator()` / `comparator_to_sql_op()` 供 sql_builder 用
**`web/core/like_util.py`** — 抽 `_escape_like` 上提
- `escape_like(s)` + `ESCAPE_CHAR = "!"`(跨 DB 一致,避开达梦 [CODE:-6106])
- 原 step9 内嵌的 `_escape_like` 删除,从此模块 import
**`web/core/sql_builder.py`** — 树 → WHERE 子句 + 绑定参数
- `Bind` dataclass(累积 params)
- `build_where(node, bind, column_quoted, db_type)` 递归:
- group → `(c1 <op> c2 <op> c3)`
- leaf LIKE → `col LIKE %s ESCAPE '!'`
- leaf 算术 → `col > %s` / `< %s` / `= %s`
- `compile_rule(group_node, column_quoted, db_type)` → `(where_clause, params_list)`
- 占位符按 db_type 切换:`%s` (MySQL) / `?` (达梦/Oracle),每个 leaf 内单独取一次
- 空 leaf.value / 未知 comparator → 返回 '' 让上层 group 过滤(不报错)
- 不发起 fetchall、不解析 SQL 文本 → 只产出 WHERE 片段 + 参数
### 修改的 4 个文件
**[web/core/db_adapter.py](web/core/db_adapter.py)** — 新增两个 frozenset(紧挨 `TEXT_TYPES`)
```python
NUMERIC_TYPES = {"int","integer","smallint","tinyint","bigint","mediumint",
"decimal","numeric","float","double","real","number",
"binary_float","binary_double","money","smallmoney","dec","year", ...}
DATE_TYPES = {"date","datetime","timestamp","time","year",
"smalldatetime","datetime2","datetimeoffset","interval", ...}
```
**[web/core/step_impl/step9_custom_rules.py](web/core/step_impl/step9_custom_rules.py)** — 主循环大改
- 删原 `_escape_like`(提到 like_util.py)
- 新增 `_normalize_rule(rule)`:旧 payload `{rule_type, user_input}` 自动包成 `{group:{kind:'group', op:'AND', children:[{kind:'leaf', comparator:'contains', value:kw}]}}`,**历史数据兼容**
- 主循环改成:`_normalize` → 编译树 → 跑 SQL → 写入 matches[]
- summary 字段调整:增加 `skipped_no_valid_leaf`(group 不为空但全叶子 value 空)、`skipped_empty_keyword`(旧 payload 静默跳过)
- Tab 协议增加 `data_type` 列(tag 类型,染色 text/numeric/date)
**[web/static/index.html](web/static/index.html)** — 自定义规则卡完全重写
- `addCustomRule(row)` 透传 `row.data_type` / `row.column_type`,新增 `group: {kind:'group', op:'AND', children:[]}` 初始结构
- `buildCustomRulesForSubmit` 改读新结构:跳过空树(递归 `hasValidLeaf` 检查 value 非空叶子)
- 6 列 el-table 改成 5 列:规则名称 / 表名+注释 / 字段名+类型 tag / 条件树(递归组件)/ 操作
- 删除「规则」「用户输入(关键字)」两列(已被条件树取代)
- 提示文案更新:3 大类比较符说明 + +子条件 / +嵌套组 玩法
**[web/static/index.html](web/static/index.html)** — 新增全局组件 `<condition-tree>`
- 递归 Vue 组件,props: `node / column / dataType / depth`
- group 渲染:`[AND ▼] X 项 [+ 子条件] [+ 嵌套组] [删除 if depth>0]`
- leaf 渲染:`[comparator ▼] [value 输入框] [× 删除]`
- comparator 列表按 `dataType` 自动过滤(前端镜像 rule_types.py)
- `addCustomRule` 触发后自动展开卡片 (`customConfigCollapsed.value = false`)
- 新增 3 个工具函数(`classifyField` / `COMPARATORS_FRONT` / `INPUT_HINT_FRONT` / `fieldClassTagType`),与后端语义对齐
- 加 `name: 'ConditionTree'` 让递归调用自身能找到组件
### 新增 CSS
- `.cond-tree--group` 边框 + 浅灰背景
- `.cond-tree--nested` 嵌套层左边框 + 缩进(视觉上模拟「括号层」)
- `.cond-tree-empty` 空组占位("空组 —— 点 + 子条件 开始添加")
- `.cond-leaf` flex 横排(comparator + input + 删除按钮)
- 折叠态隐藏条件树(`.section-card.is-collapsed .cond-tree { display:none }`)
### 验证
后端集成(mock DB):
```
6 条规则(1 varchar contains + 1 numeric 嵌套 AND(gt)+OR(lt/gt) + 1 date_before
+ 1 旧 payload user_input + 1 空 user_input + 1 空 group.children)
→ summary: total=6 / executed=4 / skipped_empty=1 / skipped_no_valid=1 / failed=0
total_matched_rows=20(5 行 × 4 条有效规则)
→ 4 条 SQL 全部正确生成(含嵌套 group、跨方言占位符、LIKE 转义、日期比较符)
```
后端 sql_builder 独立测试(10 个场景全过):
- 单 leaf (text + contains)
- group AND contains + not_contains
- 嵌套 numeric AND(gt + eq) + OR(lt + gt)
- date_before + date_after
- 跨方言占位符切换(mysql=%s / dameng=oracle=?)
- 空 leaf.value → 跳过
- 未知 comparator → 跳过
- LIKE 转义嵌套 `50%off!` → `50!%off!!`
- 旧 payload 兼容(_normalize_rule 自动 wrap)
- 已带 group 不重写
### 兼容
- 旧 payload `{rule_type, user_input}` 在 step9 入口 `_normalize_rule` 自动包成新结构,跑同一条 SQL
- 前端新建规则只走新格式;老规则(内存中的 customRules)刷新页面后丢失(用户已习惯此模式 — 数据字典不持久化)
### 影响
- 用户能精确表达「身份证含 X 且不含 Y」「年龄 > 18 且(< 60 或 > 80)」「创建时间早于 2025-01-01」这类复合规则
- SQL 自动按字段类型分支(text → LIKE / numeric → ><=/ date → <>),不再一刀切走 LIKE
### 备注(提交前)
本次涉及前后端大量改动,**本次工作结束不提交**,按用户要求先验证。
## 2026-08-12 · 自定义规则:换图标 Filter → MagicStick ✨ ## 2026-08-12 · 自定义规则:换图标 Filter → MagicStick ✨
### 需求 ### 需求
...@@ -3292,3 +3404,41 @@ Total: 28 steps # 4 基础 + 24 indicator checkbox ...@@ -3292,3 +3404,41 @@ Total: 28 steps # 4 基础 + 24 indicator checkbox
### 未提交 ### 未提交
按用户要求,待 review 后再提交。 按用户要求,待 review 后再提交。
---
## 2026-08-12 · v2 端到端联调 + 3 个 bug 修复
### 联调过程(用户验机)
1. 添加「YW_GJY.DMYJCE > 5000」规则 → 提交 → 跑出 200 行命中 ✅
2. 自定义规则 UI、字段类型 → 比较符映射、WHERE 编译、`ESCAPE '!'` 均工作正常
### 修复 3 个 bug
#### 1. `fieldClassTagType is not a function` 渲染崩溃
- **现象**:点 + 号加规则后,列表 div 渲染但 row 不显示,Console 报错 `fieldClassTagType is not a function`
- **根因**:函数定义在 setup() 外部(模块作用域),但模板里调用,须 setup() return 出来
- **修复**:在 `setup()` 的 return 里加 `fieldClassTagType`
- **次因**:缓存混用(旧 JS 无 `group` 字段 + 新 HTML 引用 `rule.group` 抛错)→ 改 `props.node` 加 default 兜底、模板 `:node="rule.group || { ... }"` 兜底
#### 2. 字段注释 / 表注释没显示
- **现象**:字段 `column_comment` 没渲染;表注释「(无表注释)」但浏览器里 YW_GJY 表注释存在
- **根因**:
- 字段行 `row` 不带 `column_comment`(看后端 `data_dictionary` 字段 → 实际字段注释字段命名差异),需要在 `addCustomRule` 里透传
- 字段行也不带 `table_comment`;从 `tableSummary` 反查兜底
- **修复**:
- `addCustomRule` 加 `table_comment` 兜底查 `tableSummary`
- 模板 field 列加 `column_comment` 渲染
- 排版:分两块(表块 / 字段块),inline flex + dashed border-top 分隔
#### 3. orchestrator 不自动追加 custom_value_check 步骤
- **现象**:steps=[] + 1 条规则 → 调度计划 `main_steps=[]` → 0 步跑 → 0 违规
- **根因**:`has_effective_rule` 判断只认旧 payload `user_input` 字段,v2 payload 用 `group` 树结构 → 永远 False
- **修复**:写 `_has_effective_leaf(node)` 递归判断 group 树,新旧 payload 都认
- **位置**:`web/core/orchestrator.py` `run_governance_workflow` 内
### 提交拆分(4 个 commit)
1. `feat(backend): 新增 rule_types / like_util / sql_builder + step9 重构支持条件树`
2. `feat(backend): NUMERIC_TYPES / DATE_TYPES + orchestrator 识别 v2 payload`
3. `feat(web): 自定义规则卡条件树 UI + addCustomRule 透传 data_type + 字段注释排版`
4. `docs(worklog): 条件树改造 + 端到端联调 3 bug 修复记录`
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment