- 13 Aug, 2026 14 commits
-
-
Data Governance Dev authored
状态机重构: - 删 tableSummary / dataDict 全量 ref + 4 个前端过滤 computed - 新增 tableList/fieldList + page/hasMore/total/loading 共 10 个 ref - 新增 fetchTablesPage/fetchFieldsPage(防 stale 响应 + nextTick 后重挂 scroll) - 新增 onTablesScroll/onFieldsScroll:EP 2.14.3 + height 时 scroll 不冒泡到 el-table 根, 改在 .el-scrollbar__wrap 上挂原生 addEventListener('scroll', { passive: true }) - 新增 rebindDictScroll:每次 fetch + nextTick 后重挂兜底(el-table 重建 wrap 时失效) - 筛选 commit 时从后端重读第 1 页(applyTableSearch/applyFieldSearch) - watch(form.tables) 触发 fetchFieldsPage(1, true)(勾选表变化自动更新字段表) 跨页勾选同步: - onTableSelectionChange 改为 set 合并(visible 名 + 新选中 → add;visible - 未选中 → delete; 不在 visible 的保留)—— 旧实现会丢跨页勾选 - 新增 restoreTableSelection:数据刷新后把 el-table 可见勾选与 form.tables 对齐 (reserve-selection 在 :data 整体替换时失效,必须手动同步) 按钮重写: - 全选 / 反选:调 /api/dict/all-table-names 拿全量匹配名字 → 设 form.tables → fetchTablesPage(1, true) 把所有匹配表拉回首屏 - 清空:form.tables = [] + clearSelection() CSS:web/static/style.css - .dict-tables-table thead .el-checkbox, .dict-fields-table thead .el-checkbox { visibility: hidden; pointer-events: none; } (display:none 会算错表头高度) addCustomRule:去除 tableSummary 兜底(后端 /api/dict/fields 每行附 table_comment) 踩坑: - EP 2.14.3 + height → <el-scrollbar> 包裹 body → @scroll 不触发,必须原生监听 - selection-change 只返 visible 选中行,直接赋值丢跨页勾选 → set 合并 - reserve-selection 在 :data 整体替换时失效 → 自写 restoreTableSelection -
Data Governance Dev authored
DataDictCache 之前只在 connect/test 写入;这次新增 3 个 GET 端点让前端按需切片: - GET /api/dict/tables?db_type=&host=&port=&user=&database=&page=&page_size=&q= → 分页返回 table_summary,每项附加 field_count(前端不再算) - GET /api/dict/fields?...&tables=t1,t2&page=&page_size=&q= → 分页返回 data_dictionary(按 tables 参数过滤),每项附加 table_comment - GET /api/dict/all-table-names?...&q= → 仅返名字列表,供前端「全选 / 反选」按钮使用(不分页) 实现要点: - 全部走 DataDictCache.get_instance().get(cfg),命中即 list[a:b] 切片(微秒级) - cache miss 时现场抽一次(缺 password 抛 warning 让前端提示重连) - 多连接并存按 5 元组 (db_type, host, port, database, user) 区分 key - 排序:tables 按 table_name 字典序;fields 按 (table_name, ordinal_position) 与旧前端 filteredFields 排序保持一致 踩坑: - port=3306 默认参数必须放最末位(Python SyntaxError) - list_dict_fields 重复定义 host 别名导致 FastAPI 参数解析歧义 → 简化为单一 host 参数 - list_columns SQL 不带 table_comment,/api/dict/fields 响应里要手动从 table_summary 关联
-
Data Governance Dev authored
用户反馈:自定义规则命中明细表里「规则」列只显示 'tree',没有信息量。 ## 改动 - step9_custom_rules.py: 新增 _serialize_rule_human(group) 递归把条件树 序列化为可读 SQL 形态字符串 - 叶子: col LIKE '%X%' / col NOT LIKE '%Y%' / col > 10 / col < '2026-01-01' - 顶层组: children 用 AND/OR 串接;单 child 不加括号 - 嵌套组: (children) 加括号让优先级清晰 - 每条 entry 增加 rule_text 字段(common dict);删除无意义的 rule_type 赋值 - ColumnSpec: prop 'rule_type' → 'rule_text';render tag → code(等宽字体) ;min_width 120 → 240 - step8_report._md_custom_value_check / docx 版同步: - 去掉「关键字」列(v1 字段,v2 已不存在) - 「规则」列改用 rule_text ## 端到端验证 mock DB 跑一条含嵌套组的规则: 输入: AND(contains(X), OR(contains(Y), not_contains(Z))) rule_text: 'col LIKE \'%X%\' AND (col LIKE \'%Y%\' OR col NOT LIKE \'%Z%\')' 真实 SQL: '... WHERE (`id_card` LIKE %s ESCAPE \'!\' AND (`id_card` LIKE %s ESCAPE \'!\' OR `id_card` NOT LIKE %s ESCAPE \'!\')) LIMIT 100' 显示与真实 SQL 语义一致;区别仅是显示用 'col' 占位列名(方便看),真实 SQL 用 quote_ident。 ## 踩坑 第一版递归在父循环对子组额外包括号 '(" + walk() + ")',而 walk(is_top=False) 内部对嵌套组已经返回带括号形式 → 嵌套组变成 '((col < 5 OR col = 100))'。 修法:用 is_top 参数让递归本身决定是否加括号,调用方不再重复加。 教训:写递归字符串拼接时给一个 is_root / is_top 参数控制顶层 vs 嵌套行为。 -
Data Governance Dev authored
用户需求:针对特定字段的分析(国标字段规范、业务字段规范、用户自定义规则) 希望可切换「部分(前 1000 行)抽样 / 全量扫描」,且每个分析项独立配置(A 项选部分, B 项可独立选全量)。 ## 后端 - 新增 web/core/sql_utils.py: apply_sample_limit(sql, sample_limit, db_type) - sample_limit=None → 移除末尾 LIMIT N / AND ROWNUM <= N(全量扫描) - sample_limit=int → 保留原样(partial 模式) - 三方言均覆盖:MySQL / 达梦(标准 LIMIT)/ Oracle 11g(AND ROWNUM <= N) - models.ConnectRequest 新增 sample_limits: dict[str, int | None] - job_manager.submit 透传 sample_limits 给 orchestrator - orchestrator.run_governance_workflow 新增 sample_limits kwarg;按 step_id 取值 分发给各 _run_* 闭包 - step7_standards._run_round1/2/3_* 全部加 sample_limit 参数:渲染 SQL 后用 apply_sample_limit 二次处理(partial→加 LIMIT 1000,full→剥 LIMIT) - step9_custom_rules.run_step_custom_value_check 加 sample_limit 参数: SQL 构造按 None / oracle / else 三分支 ## 前端 - index.html sampleScope ref + SAMPLE_PARTIAL_LIMIT 常量 - 每个 IND-XXX leaf 行(checkbox 之后、字段名输入框之前)加 partial/full radio - key = step_id(每个 IND 独立),不再按 group 共享 - 标签去掉了「1000」后缀,仅显示「部分 / 全量」 - 自定义规则卡片保持 card-level 单个 radio(共享 custom_value_check step_id): step9 后端所有规则共用一个 LIMIT,要下沉需另改接口 - watch(analysisTree.groups) 加载后为每个 step_id 初始化 sampleScope='partial' - buildSampleLimitsForSubmit() 把 sampleScope 转成后端要的 {step_id: int|None} - startJob() payload 加 sample_limits 字段 - style.css 新增 .sample-scope--leaf(margin-left: 8px,紧贴字段名输入框) ## 端到端验证 - 用户在 IND-001/002/003 选全量、IND-004 选部分 → payload 正确: {std_ind_001: None, std_ind_002: None, std_ind_003: None, std_ind_004: 1000} - Pydantic ConnectRequest 解析通过;类型 [(str, 'NoneType'/'int'), ...] - 三方言 × partial/full × 多种 SQL 形态,行为符合预期 ## 踩坑 edit 工具改函数签名+docstring 时只换首行 → 留孤儿 """ → SyntaxError。 教训:edit 改函数签名 + docstring 时,把整个 docstring 完整贴一遍。 -
Data Governance Dev authored
新增 2026-08-13 条目,覆盖 6 块改动: 1) ORA-01036: illegal variable name/number - sql_builder 历史 Oracle 路径输出 qmark ?,但 python-oracledb 不支持 - Bind.next_idx 加 numbered :1/:2/... 占位符 2) ORA-00933: SQL command not properly ended - step9 无条件 LIMIT 200,Oracle 11g 不支持 - 截断子句分支:Oracle 走 WHERE ROWNUM <= N 3) 中间 bug:Oracle 分支漏 WHERE 关键字 - 静态验证三方言 SQL 时暴露,立即补 WHERE - 教训:跨方言分支必须同一组测试数据验证 4) evalPathExpr 不支持 dict 索引 - 设计 data.matches_rule_<idx> 扁平字段避开 this.x[key] 语法 - 教训:协议路径表达式先看支持语法再设计数据结构 5) flatResultRows 折叠表聚合踩坑 - 顶层 summary 是 section 共享的,按 tab key 前缀识别 custom_value_check_<idx> 6) UX:默认名「自定义规则N」 - nextDefaultRuleName() 扫已用名,找最小可用 N - 后端兜底回落 <table>.<column>(不再用 (未命名))
-
Data Governance Dev authored
两个用户反馈: 1) 自定义规则命中明细:原来 N 条规则塞进 1 个 tab,规则一多翻不到。 改为每条规则单独占 1 个 tab: - key = custom_value_check_<idx>(idx 从 1 开始,与前端卡片顺序一致) - title = <rule_name>(<table>.<column>) - summary alert:成功显示"本规则命中 N 行";失败显示"执行失败:**错误**"(红 alert) - table source = this.matches_rule_<idx>(扁平命名) 失败规则也出 tab(alert 显示错误),用户能直接看到为什么失败。 2) 新建自定义规则时输入框默认「自定义规则N」,N 从已用编号集合里找最小可用, 用户手动改名后 N 仍递增不会撞名。 数据 / 前端配套: - 后端 data 顶层加 matches_rule_<idx> / error_rule_<idx> / matched_rule_<idx> 三组扁平字段 - 为什么不走 dict 索引(this.by_rule['rule_X']):前端 evalPathExpr 是简单属性路径 (this.x.y.z),不识别 [key] 语法,扁平命名最干净 - 前端 flatResultRows 识别 custom_value_check_<idx> 前缀的 tab:命中数从 matched_rule_<idx> 取,检查数固定 1(每条规则 = 1 个字段) 静态验证(mock 两条规则,1 ok + 1 ORA-00933 失败)已通过: tabs: [ {key:custom_value_check_1, type:info, vars:{matched:this.matched_rule_1}}, {key:custom_value_check_2, type:error, vars:{error:this.error_rule_2}} ] WORKLOG 待用户在 Oracle 端实跑自定义规则验证后追加(不阻塞提交) -
Data Governance Dev authored
两个 Oracle 专属问题,连续两次跑自定义规则暴露: 1) ORA-01036: illegal variable name/number - 原因:sql_builder._placeholder 旧版 Oracle 路径输出 '?',但 python-oracledb 不支持 qmark 占位符(thin 模式不会自动转 :N,必须显式给 numbered) - 修复:Bind 加 next_idx;Oracle 路径按递增编号输出 :1, :2, ...,与 bind.params 顺序一一对应 2) ORA-00933: SQL command not properly ended - 原因:step9_custom_rules 无条件拼 'LIMIT 200',Oracle 11g 不支持 LIMIT (12c 引入 FETCH FIRST;11g 只能用 WHERE ROWNUM <= N) - 修复:截断子句按 db_type 分支,Oracle 走 WHERE ROWNUM <= 200 中间 bug:Oracle 分支漏写 WHERE 关键字(FROM "tbl" "col" LIKE :1 ...), 静态验证脚本(三个方言各跑一遍)暴露后补上 WHERE。 静态验证 SQL: MySQL : SELECT `COL` FROM `TBL` WHERE `COL` LIKE %s ESCAPE '!' LIMIT 200 达梦 : SELECT "COL" FROM "TBL" WHERE "COL" LIKE ? ESCAPE '!' LIMIT 200 Oracle : SELECT "COL" FROM "TBL" WHERE "COL" LIKE :1 ESCAPE '!' AND ROWNUM <= 200 WORKLOG 待用户在 Oracle 端跑自定义规则验证后追加(不阻塞提交) -
Data Governance Dev authored
把原本 3 行布局的「连接数据库」卡片重排为 2 行独立 form,结构更清晰 且整体更紧凑。 主要改动: 1. 拆成两个独立的 <el-form> - 第一个 form 只包「数据库类型」(3 个 radio-button) - 第二个 form 包「主机 IP / 端口 / 用户名 / 密码 / 数据库名 / 字符集」+ 测试连接按钮 + 结果 alert - 共享同一个 reactive form 对象,校验 / 重置不受影响 - 两个 form 之间用 margin-top: 12px 留白(不用 hr 不用 divider) 2. 切到 inline form 模式 - :inline="true" + label-width="auto" + label-position="right" - label 和控件同一行(不再是 label 上方 + 控件下方占两行) 3. span 重新分配(合计 24) - 主机 IP: 5(缩到刚好显示 192.168.20.196) - 端口: 3(数字 input) - 用户名: 2(用户名通常短) - 密码: 3(含眼睛图标) - 数据库名: 4(schema 名长度可变) - 字符集: 7(select + 下拉箭头占空间) 4. 端口字段改造 - 从 el-input-number 改 el-input(用户偏好) - v-model.number 保证后端拿到 int(Pydantic cfg.port: int 兼容) - @input 过滤非数字字符(避免 Pydantic "not a valid integer") 5. 解决 inline form 下 select/input 撑不满 col 的问题 - 给每个 el-form-item 加 display: inline-flex; align-items: center; width: 100% - 让 form-item 强制撑满 el-col 内部,input/select width:100% 才能真正展开 - 之前只加 width:100% 不够,因为 inline form 下 form-item 默认 inline-block 宽度 = max(label, content),select 会按内容自适应而不是 col 宽 6. gutter 从 20 → 12(列间距减半) 调整过程踩坑(避免再走): - inline form 下 el-form-item 默认 inline-block → 不会撑满 el-col - 单纯给 input 加 width:100% 不够 → form-item 本身也要撑满 - 终极方案是 form-item 用 inline-flex + width:100% 让内部 flex 自动展开 -
Data Governance Dev authored
之前已分别记录了 5 个 Oracle 相关条目(放开 Oracle / connect_timeout / DPY-3010 / 路径外置 / DPI-1047 PE 解析)。本条目汇总本轮新加的 4 个修复: 1. health SQL 不分方言 → ORA-00923(SELECT 1 不 FROM) 2. 前端 UI 隐藏 Oracle Client 输入框 3. 抽数据字典 ORA-00904 → 11g ALL_TABLES 实际可用列清单 4. 抽数据字典 0 行 → service_name vs schema 名混淆 含关键对照表: - MSVC 版本 vs MSVCR DLL(VC++ 2013 Redist 是关键) - MySQL/达梦/Oracle 的 schema 名语义差异
-
Data Governance Dev authored
Oracle Instant Client 路径不再让用户在 UI 填,改为: - 配置文件:web/configs/db_defaults.yaml 的 oracle_client_dir - 前端通过 GET /api/db-defaults 读取,注入 form.oracle_client_dir - 测试连接时 ...form 展开自动带上,后端 cfg.oracle_client_dir 拿到值 - UI 上完全看不到该输入框 修改路径的新流程:改 yaml → 重启 web 服务(sql_loader/db_defaults 不热加载) → 测连接。 state 字段 form.oracle_client_dir 保留(作为 form 数据载体); loadDbDefaults() 注入逻辑保留(只是 UI 不展示)。
-
Data Governance Dev authored
Oracle 11g (11.2.0.4) 数据库连接抽数据字典端到端跑通,解决 4 个独立问题: 1. connect_timeout → tcp_connect_timeout oracledb 1.4.2+ 移除了 connect_timeout kwarg(之前误以为兼容), 改成 tcp_connect_timeout;报错日志加 inspect 自动定位兼容 kwarg。 2. thick 模式加载 + DPI-1047 深度诊断 - _ensure_oracle_client() 解析 oci.dll 的 PE 导入表,自动列出 实际依赖的运行时 DLL(如 MSVCR120.dll → VC++ 2013 Redist) - DPY-3010(thin 不支持老 Oracle)日志加针对性安装指引 - 11.2.0.4 必须 thick 模式(thin 不支持 11.2) 3. 健康检查 SQL 分方言 新建 check_connection.oracle.sql 写 SELECT 1 FROM dual; Oracle 严格执行 SQL 标准,不像 MySQL/达梦 兼容裸 SELECT 1。 sql_loader 按 <name>.<dialect>.sql 优先 + .sql 回退 自动分流。 4. ALL_TABLES 11g 列兼容性 修 list_tables.oracle.sql: - data_length 用 t.BLOCKS * 8192 估算(11g 没 BYTES 列,12c+ 才有) - create_time / update_time 取 NULL(11g 没 CREATED/LAST_DDL_TIME,12c+ 才有) - 注释贴了 11.2.0.4 ALL_TABLES 完整可用列清单(用户 DESC 确认) 5. schema 名传递修正 data_dict.py 之前对所有数据库都传 cfg.database 给 list_tables/list_columns, 但 Oracle 体系里 ALL_TABLES.OWNER 是用户名(=cfg.user),不是 service_name。 加 cfg.db_type == 'oracle' 分支:schema_name = cfg.user 6. /api/db-defaults 加 oracle_client_dir 路径从 web/configs/db_defaults.yaml 预填,前端可隐藏输入框。 验证日志: [DB] Oracle Instant Client 已加载(thick 模式)lib_dir=... [DB] 连接已建立(耗时 ~100ms) [DB] 测试连接成功 [Cache] 写入数据字典: (表 N 张, 字段 M 个) 踩坑详见 docs/WORKLOG.md(2026-08-13 Oracle 端到端打通条目)。 -
Data Governance Dev authored
UI 从 7 组 / 30+ step 收敛到 3 组 / 15 step;隐藏 27 个 indicator。 合并 / 改名为独立 IND 号(移入 standards 组): - IND-401 / IND-402 → std_ind_401(姓名校验,2 子检查合一) - IND-006-b → std_ind_006(邮政编码) - IND-013-a / -b / -c → std_ind_017 / -018 / -019 (单位类别 GB/T 12402 / 经济类型 国统字〔2011〕86 号 / 行业代码 GB/T 4754) 隐藏 27 个 indicator(_HIDDEN_SUBS,暂离 UI,按需恢复): - IND-016-a / -101 / -201..-204 / -301 / -302 / -501 / -502 - IND-601..-603 / -901 / -902 - IND-006-a / -008-a..-011-a(其他业务字段整组下架) - IND-013-a..-c(已改名) - IND-012-a / -014-a / -014-b / -015-a(单位法人经办人整组下架) 整组下架(5 个 group): - 单位对公账户 字段规范 - 民政信息 - 证件信息 - 其他业务字段 - 单位 / 法人 / 经办人 字段规范 新增 / 重命名 group: - 业务字段规范(含 std_ind_401 姓名 + std_ind_007_a 公积金账号) 后端改动: - 抽 _run_standards_ind_renamed(source_id, target_step_id, target_title) 工厂 合并 IND-005/006/013 的改名逻辑 - _run_standards_combined factory 处理 std_ind_401 合并子检查 - _IND_COMBINED['ind_401'] 配置(IND-401/IND-402 字符集 + 长度合一) - _MERGED_SUBS / _HIDDEN_SUBS / mapped_step 同步更新 前端 / 配置: - analysis_tree.json: 7 组 → 3 组;description / default_expand 同步精简 - routes.py /api/match-config: _COMBINED_GROUPS 聚合 + IND-005/006/013 改名映射 docs(WORKLOG): 6 轮完整记录 + 踩坑(log 闭包 bug 修复、sub_prefix 对无后缀 ID 的适配等) UI 顺序:基础检查 → 国标字段规范(10 step)→ 业务字段规范(2 step)
-
Data Governance Dev authored
需求:把 IND-002(USCC 3 子)/ IND-003(手机号 2 子)/ IND-004(行政区划 2 子) 也和 IND-001 一样合并成单 step;IND-005(固定电话,1 子)UI 不再显示 -a 后缀。 改动: - step7_standards.py: 把 IND-001 专属的合并逻辑通用化为配置驱动 - _IND_COMBINED: {parent_id: {sub_ids, title, format}} 配置表(覆盖 ind_001/-002/-003/-004) - _wrap_combined_ind_001 → _wrap_combined_indicator(parent_id, ...) - run_step7_for_ind_001 → run_step7_combined(parent_id, ...) - 旧名保留为薄包装(backward compat) - orchestrator.py: - _MERGED_SUBS 扩展到 12 个子指标(4+3+2+2+1) - _run_standards_combined(parent_id) 工厂 + _COMBINED_STEP_META 注册表 - 循环注册 std_ind_001/-002/-003/-004 四个 step - _run_standards_ind_005 端到端改 4 处:section_key / step_id / tab.key / tab.title - analysis_tree.json: 标准组 7 行 → 5 行(去掉 -a/-b/-c 后缀) - routes.py: _COMBINED_GROUPS 4 组聚合 + IND-005 单独处理(YAML key 仍叫 IND-005-a) - WORKLOG 追加整段记录 + 踩坑说明(IND-005 改名必须 4 处一致) -
Data Governance Dev authored
需求:勾一个 IND-001 checkbox 跑全部 4 子检查; 结果合并展示,单条违规里显示「哪些子检查失败」。 改动: - step7_standards.py: 新增 _IND_001_SUB_IDS / _merge_violations_by_tuple / _wrap_combined_ind_001 / run_step7_for_ind_001,单 (table,col,value) 多子检查失败行合并,rule_type 列改为 'IND-001-a, IND-001-b', error 列改为 '[a] 长度 19 ≠ 18\n[b] 校验位错误' 拼接原文 - orchestrator.py: 注册 std_ind_001 step(order=100,llm=none), 跳过 IND-001-a/b/c/d 自动注册,避免 4 个独立 section 还在 - analysis_tree.json: 国标字段规范组删 4 行 IND-001-a/b/c/d,加 1 行 std_ind_001 - routes.py: /api/match-config 过滤未注册为 step 的子 indicator; 把 IND-001 a/b/c/d 的 applies_to_fields / comment_keywords 聚合到 std_ind_001 的输入框,避免合并后前端输入框丢失 - 修复 double-wrap bug:_run_standards_ind_001 不再二次包裹 run_step7_for_ind_001 原返回值(已含 {section_key, data}) - WORKLOG 追加 4 段:合并设计 / 关键词输入框回归 / 标题 '合并 a/b/c/d' 去除 / 结果不显示修复(double-wrap 根因 + 烟测)
-
- 12 Aug, 2026 13 commits
-
-
Data Governance Dev authored
- 改 1:自定义规则卡 icon 换 Operation(之前 MagicStick 渲染不出来) - 改 2:4 个卡片 header 点击折叠 + 按钮 .stop(卡 1 / 2 / 2.5 / 3) - 改 3:sql_builder 数值比较符强制 float 避免达梦字符串解析为 0.0 坑 - 改 4:step9 SummarySpec template 改双花括号与前端 renderSummary 匹配
-
Data Governance Dev authored
- 现象:「自定义规则命中明细」tab 顶部 alert 显示「执行 **{total}** 条规则...」花括号没替换 - 根因:step9 template 用单花括号 {total},前端 renderSummary 正则只匹配 {{ var }} 双花括号 - 修复:template 改 {{total}} 双花括号(与其他 step 风格一致:step4 / step5 / step6 / step7) - 修后:执行 **1** 条规则,有效 **1** 条,命中 **0** 行(...) -
Data Governance Dev authored
- 现象:自定义规则 GRJCJS > 5000 命中 38 行全是 0.0 - 根因:value 是字符串 '5000',达梦 SQL WHERE GRJCJS > ? 收到字符串 '5000' 后做字符串 vs DECIMAL 比较,部分达梦版本把 '5000' 解析为 0.0(字符串解析失败回退),变成 WHERE GRJCJS > 0.0 - 修复:编译 gt/lt/eq 时 bind.params.append(float(val)) 强制数值化;非法值返回空字符串 让上层跳过 - 日期:date_before / date_after 保持 str(val)(达梦 / Oracle DATE 比较认字符串 YYYY-MM-DD)
-
Data Governance Dev authored
- 自定义规则卡 icon:MagicStick SVG 渲染不出来 → 改用 Operation(扳手+齿轮,贴合自定义规则语义) - 4 个卡片 header 点击折叠:连接数据库 / 分析配置 / 自定义规则 / 数据字典浏览器 - CSS 加 .collapsible-header { cursor: pointer; user-select: none; } + hover 灰底 - 整个 .card-header 是点击区,@click 切换折叠 - 内部按钮加 @click.stop 防止冒泡(全选/清空/反选/折叠 按钮) - 分析进度 / 分析结果 卡片无折叠按钮,本轮不动 -
Data Governance Dev authored
- 记录需求、设计决策(多层递归 / 日期只支持具体日期 / 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 步骤
-
Data Governance Dev authored
把单条 el-table 行(含 1 个 el-input 关键字)重写为 div + CSS Grid 4 列布局。 - 字段类型 → 比较符映射(前端镜像 web/core/rule_types.py) - NUMERIC_TYPES_FRONT / DATE_TYPES_FRONT / TEXT_TYPES_FRONT 三集合 - classifyField(dataType) → text/numeric/date/unknown - COMPARATORS_FRONT / INPUT_HINT_FRONT 按字段类分发 - fieldClassTagType(dataType) → 数值 warning / 日期 info / 字符 success - 全新递归组件 <condition-tree> - app.component('condition-tree', { name: 'ConditionTree', ... }) - props: node(默认空 group) / column / dataType / depth - 渲染:group 节点显示 AND/OR radio + 项数 + 「+ 子条件 / + 嵌套组」按钮 - 渲染:leaf 节点显示 comparator select + value input + × 删除 - emits: change / remove - 列表 div 替代 el-table - 4 列 grid:规则名称 / 对象·字段·类型 / 条件树 / 操作 - .field-block 容器:表名 + 表注释 / 字段名 + 类型 + 字段注释 inline 排 - .field-block--field dashed border-top 视觉分隔两行 - addCustomRule 改造 - 透传 row.data_type / row.column_type(决定可用比较符) - 初始化 group = { kind: 'group', op: 'AND', children: [] } - table_comment 兜底查 tableSummary(字段行 row 不带) - 自动展开卡片(customConfigCollapsed = false) - buildCustomRulesForSubmit 改读新结构 - hasValidLeaf(node) 递归判断:跳过空树 - 输出包含 {rule_name, table_name, column_name, data_type, group_op, group} - 修复 2 个调试 bug - fieldClassTagType 是模块作用域函数,模板调用须 setup() return 出来 - <condition-tree> props.node 加 default 兜底,避免 rule.group undefined 渲染崩溃 -
Data Governance Dev authored
- web/core/db_adapter.py - 新增 NUMERIC_TYPES / DATE_TYPES frozenset(紧挨 TEXT_TYPES) - 覆盖 MySQL / 达梦 / Oracle 三方言的常见数值 + 日期类型 - web/core/orchestrator.py - 修 bug:"自动追加 custom_value_check 步骤" 判断只认旧 payload {user_input} - v2 payload 用 group 树结构 → 永远 False → main_steps=[] → 0 步跑 - 新增 _has_effective_leaf(node) 递归判断:新旧 payload 都认 - 修后:steps=[] + 1 条有效规则 → 自动追加 custom_value_check → 跑 200 行命中 -
Data Governance Dev authored
自定义规则 v2 后端核心:把单条 LIKE 升级为递归条件树。 - web/core/rule_types.py(新) - classify_field(data_type) → text/numeric/date/unknown - COMPARATORS_BY_CLASS / DEFAULT_COMPARATOR / INPUT_HINT_BY_CLASS - 文本 2 算子(contains / not_contains);数值 3 算子(gt / lt / eq);日期 2 算子(date_before / date_after) - web/core/like_util.py(新) - escape_like(s) + ESCAPE_CHAR = '!'(跨 DB 一致,避开达梦 [CODE:-6106]) - 从 step9 内嵌函数上提,从此模块 import - web/core/sql_builder.py(新) - build_where(node, bind, column_quoted, db_type) 递归编译 group 树 - _placeholder(db_type) MySQL %s / 达梦+Oracle ? - 顶层 compile_rule(group, column_quoted, db_type) → (clause, params) - web/core/step_impl/step9_custom_rules.py - 主循环重写:每条规则编译 group 树 → 跑 SQL → LIMIT 200 命中 - _normalize_rule 自动包旧 payload {rule_type, user_input} → 新 group 树,兼容旧调用 - 摘要字段补齐:total_rules / executed_rules / skipped_empty_keyword / skipped_no_valid_leaf / failed_rules / total_matched_rows / violations / fields_checked -
Data Governance Dev authored
【折叠】 [web/static/index.html:1619-1624](web/static/index.html#L1619-L1624) startJob() 成功回调里追加 customConfigCollapsed.value = true,跟另外 3 张配置卡 (连接 / 分析配置 / 数据字典浏览器)行为一致 —— 让视觉焦点落到 「分析进度」和「分析结果」上。 注释里的「3 张」改为「配置卡」(表述更准确)。 【icon】 [web/static/index.html:366](web/static/index.html#L366) 自定义规则 header icon 从 Filter(漏斗)换成 MagicStick
✨ (魔法棒): - 视觉权重更高,16px 下也比 Filter 显眼 - 语义贴合「自定义 = 用户施展的小魔法」 - 不与其他三张卡冲突:Connection / Setting / Document / MagicStick✨ - 已 grep 确认 Element Plus icons-vue v2.3.2 IIFE bundle 导出 MagicStick 【WORKLOG】 docs/WORKLOG.md 顶部追加两条记录说明上述两个改动。 -
Data Governance Dev authored
将「数据字典浏览器 → 字段表 + 号 → 累积自定义规则 → 后端跑 LIKE 检索」打通完整链路。 【新增】 - web/core/step_impl/step9_custom_rules.py:每条规则 SELECT col FROM tbl WHERE col LIKE '%kw%' ESCAPE '!' LIMIT 200;跨 DB 占位符 (mysql=%s / dmPython=oracledb=?)、统一 '!' 避免达梦 [CODE:-6106]; 每条 SQL 命中行 = 1 个 entry(不做 distinct,重复值并列展示) - orchestrator 注册 custom_value_check 步骤(hidden=True,前端不展示; 提交 non-empty custom_rules 时自动追加) - models.ConnectRequest.custom_rules 字段 【修改】 - job_manager:区分 None(跑全部)vs [](显式空选择),同步 orchestrator 语义 - orchestrator.run_governance_workflow:同上 + 接受 custom_rules 参数 - step8_report:自定义规则报告渲染改读 matches[](7 列:规则名称/表名/ 字段名/匹配值/规则/关键字/错误;删除「命中行」列) - index.html:分析配置卡 + 自定义规则卡 UI 联动 - docs/WORKLOG.md:上述变更的工作记录 【为什么需要整体提交】 orchestrator 的 steps 语义修正 + custom_rules 注入 + job_manager 同步 + step9 执行 + step8 渲染 + models 字段,每一块独立提交都会留下 broken intermediate commit。
-
Data Governance Dev authored
匹配规则外置: - 新增 web/configs/standards_match.yaml(44 个 indicator + 14 条 length 规则) - 新增 web/core/match_config.py:线程安全加载 + get_indicator_match / get_length_rules / merge_user_override - step6 / step7 走 YAML + 用户运行时 override 三级 fallback(用户输入追加而非替换) - ConnectRequest 新增 match_overrides: dict[str, dict[str, list[str]]] - 新增 GET /api/match-config:返回前端输入框默认值(逗号分隔格式) 前端检查项 2 个输入框: - 每行 leaf 后挂「字段名 / 字段注释」2 个 el-input - loadMatchConfig() 启动时拉 YAML 默认值灌进 form.match_overrides - buildMatchOverridesForSubmit() 提交时把字符串转 list(Pydantic 期望 list[str]) - 跨字段 indicator(IND-301/302/901/902)UI 隐藏输入框(_skip: true) 卡片折叠 + 动画: - 连接数据库 / 分析配置 / 数据字典浏览器 三张卡都加折叠按钮 + Vue transition - startJob() 成功后三张卡自动折叠,焦点落到「分析进度」 - el-card__body 折叠时 padding 上下 1px(默认 20px),padding 加 0.28s 过渡 - el-card__header 折叠时 padding 6px,margin-bottom 折叠时 8px - i 图标移到输入框右侧 - progress-block margin 改为 0 Bug fix: - testConnection 也走 buildMatchOverridesForSubmit()(否则 names/comments 是 string → 422) - inline <style> 全局 CSS 不能用 :deep(),全部改为直接选择器 WORKLOG 详细记录所有决策点。
-
Data Governance Dev authored
按 2026-08-12 用户反馈: - 「分析配置」卡片上移到「连接数据库」下方、「数据字典浏览器」上方 - 还原回旧版「字段名 + 字段注释关键字模糊匹配」自动选字段行为 - 删除右表格字段 checkbox 及全链路 column_filter 前端 (web/static/index.html): - 卡片顺序:连接数据库 → 分析配置 → 数据字典浏览器 → 进度 → 结果 - 删右表格 selection 列、工具栏(全选/清空/反选)、fieldsTableRef、form.columns - startJob() 不再带 columns,只看 tables.length 后端: - web/core/models.py: 删 ConnectRequest.columns - web/core/job_manager.py: 不再透传 columns - web/core/orchestrator.py: 移除 columns / column_filter 构造与参数 - 6 个 step 文件(step2/4/5/6/7)移除 column_filter 参数 - step7_standards.py: 恢复 _collect_hit_columns + has_name/has_cmt 守卫 文档: - docs/WORKLOG.md: 追加本次记录
-
Data Governance Dev authored
- loadSteps():去掉 form.steps 默认全选,只保留 hidden step 兜底过滤 required 步骤仍在 startJob() 里自动补勾 - expandedGroups:初始化为空 Set,原 watcher 不再消费 analysisTree.json 的 default_expand 自动展开 - logExpanded:ref(true) → ref(false),实时日志面板默认折叠 工具栏的「全选 / 清空 / 全部展开 / 全部折叠」按钮照常可用, 用户想一键操作仍然可以。 .gitignore:追加 Session.vim(Vim 会话临时文件)
-
- 11 Aug, 2026 3 commits
-
-
Data Governance Dev authored
后端 - models.py: ConnectRequest 加 columns: list[{table_name, column_name}] (空 = 走选中表全量字段;非空 = 仅跑用户勾选字段) - orchestrator.py: run_governance_workflow 接 columns,构造 column_filter: set[(table, column)] 传给每个 step - job_manager.py: _run_job 透传 columns - step2/4/5/6: 加 column_filter 参数 + 按 (table, column) 过滤 - step7 (核心): 删除 _collect_hit_columns 关键字推断 (applies_to_fields / comment_keywords 不再用于挑选目标字段), 改为 _select_target_columns 直接返回上游 column_filter 后的字段; run_step7_for_indicator 单值类分支去掉 has_name/has_cmt 守门 前端 - index.html: 右表格加 checkbox 列 + 全选/清空/反选 工具栏 - form.columns: Set<table||column>,勾上表时联动勾上表所有字段、 取消表时移除该表所有字段,用户手动调整不联动回表 - startJob(): Set → [{table_name, column_name}] 后提交 - 启动按钮增加 columns.size === 0 守门 + 新 alert - disconnectDataDict / testConnection 成功 后清空 form.columns 修复 - testConnection() 不再传 Set 类型的 columns(JSON.stringify 会变 {} 导致 Pydantic 422),改为显式传空 list - data_dict.py: 达梦环境下 ALL_TAB_COLUMNS / ALL_COL_COMMENTS 视图 可能返回 N 倍重复行(B_ZJZX 12 字段实测 78 行),Python 端按 (table_name, column_name) 兜底去重,命中时打 WARN 日志 -
Data Governance Dev authored
本批 3 个独立任务合并提交(互相有依赖:hidden 机制引入 → 暴露了一个 bug → 修复)。 【Step 5 缺失注释字段检查:去 LLM 推测,改纯规则】 - web/core/step_impl/step5_missing_comments.py(全文重写) · 删 LLMClient 导入 / llm 参数 / 整段批量推测逻辑 · TabProtocol 简化为 4 列:表名+注释 / 字段名 / 类型 / 可空 · 新增 _is_missing() 工具函数 · 输出 missing_comments[:200](限制条数,避免渲染过大) - web/core/orchestrator.py · _run_missing_comments 不再向 step5 传 llm(签名保留 # noqa: ARG001) · register_step("missing_comments", ...) llm_mode="none" + title/desc/detail 全重写 · CRITICAL_STEPS: {"merge_redundancy", "missing_comments"} → {"merge_redundancy"} · 顶部 docstring L9 同步 - CLAUDE.md · 目标 L10 加变更说明 · LLM 依赖表 Step 5: required → none,预检提示改 "Step 2" 【Step 2「表合并与冗余字段分析」UI 隐藏:通用 hidden 机制】 - web/core/orchestrator.py · StepDef 加 hidden: bool = False 字段 · register_step() 同步加 hidden 入参 · merge_redundancy 注册设 hidden=True · 顶部 docstring L7 加 "UI 隐藏" 标注 - web/api/routes.py(/api/analysis-tree) · by_id 过滤 sd.hidden · 遍历 children 时 hidden/unregistered 不记入 missing(避免误导) · 「未分组」兜底组自然不会泄露 hidden step - web/configs/analysis_tree.json · 「基础检查」组直接删掉 merge_redundancy 那行(之前用 // 注释导致 JSON 解析失败,已纠正) - CLAUDE.md · LLM 依赖表 Step 2 加 "2026-08-11 起 UI 隐藏,但代码保留" 【hidden step 提交过滤(隐藏 step 仍被执行 的 bug 修复)】 - web/api/routes.py(/api/steps) · 与 /api/analysis-tree 一致:for sd in get_step_defs() if not sd.hidden - web/static/index.html(loadSteps) · 新增兜底分支:form.steps 非空时也清掉残留 hidden step (应对浏览器未刷新 / Vue 状态缓存) 【关键:hidden 只影响 UI 入口】 - 后端 run_job() 不加 hidden 校验 —— 保留「代码保留可手动触发」的灵活性 - 手动 POST /api/jobs 指定 hidden step 仍能跑(内测可用) - CRITICAL_STEPS 不动 —— hidden step 不在提交路径上,自然不会失败终止 【未提交】 - scripts/_tmp_build_violations_md.py(一次性调试脚本) - data_dictionary/standard_fields_violations_report.md(生成报告) docs/WORKLOG.md 顶部已追加本次 3 个任务的完整记录(含根因 + 验证 + 后续如何加回 LLM)。 -
Data Governance Dev authored
【Oracle 适配 — 端到端接入】 - web/core/db_adapter.py · 新增 to_oracle_kwargs(),oracledb 1.4.x 关键字映射 · _select_driver() 新增 oracle 分支,未安装 oracledb 时给中文友好报错 · _ensure_oracle_client() 自动检测 Instant Client,老 Oracle 切 thick 模式 · DBConfig.oracle_client_dir 字段(显式 lib_dir) · TEXT_TYPES 补 Oracle 类型(nclob / long) - web/sql/info_schema/list_columns.oracle.sql + list_tables.oracle.sql · 新增 Oracle 方言的字典查询模板(ALL_TAB_COLUMNS / ALL_TABLES) · 表注释 LEFT JOIN ALL_TAB_COMMENTS(同达梦结构) - web/sql/standards/{sample_field_groups,sample_field_groups_single, sample_field_pairs,sample_field_pairs_two_text}.sql · \`\${col}\` → \${col | quote} 跨方言重构,加新数据库零 SQL 改动 - web/sql/loader.py:dialect 白名单加 "oracle" - web/requirements.txt:锁定 oracledb>=1.4.2,<2.0(兼容 Oracle 11.2) - web/start.py:start 脚本新增 oracledb / dmPython 可选组件检测 - web/app.py / web/core/__init__.py / web/core/step_impl/__init__.py / web/core/models.py / web/configs/defaults.yaml / web/README.md · 描述/注释/枚举更新为「MySQL / 达梦 / Oracle」 · models.ConnectRequest 加 oracle_client_dir 字段 · README 加 Oracle 行 + 三端口映射说明 【达梦适配 — 跑通实测】 - web/core/db_adapter.py · to_dm_kwargs() 改用 server= 关键字(不是 host=),删 dmPython 不支持的 schema / charset / connect_timeout 参数(C 扩展传错会 SystemError 吞真实异常) · _rows_as_dicts() 统一 PyMySQL Dict / tuple 两种行格式 · fetchall / fetchone 从 cur.description 取列名兜底 · dmPython SystemError 增强日志(提示真实原因 + 给排查脚本路径) - web/sql/info_schema/list_columns.dameng.sql · 列注释 LEFT JOIN ALL_COL_COMMENTS(修 [CODE:-2207] C.COMMENTS) - web/sql/info_schema/list_tables.dameng.sql · BYTES → NULL(达梦 ALL_TABLES 无此列) · COMMENTS → LEFT JOIN ALL_TAB_COMMENTS(达梦 ALL_TABLES 无此列) · CREATED / LAST_DDL_TIME → NULL(达梦 ALL_TABLES 无时间戳) 真要看时间戳得 LEFT JOIN ALL_OBJECTS,按 OBJECT_TYPE='TABLE' 过滤 【UI 改进】 - web/static/index.html · 数据库类型三选项(MySQL / 达梦 / Oracle) · onDbTypeChange 端口切换改用 DB_DEFAULT_PORTS 映射表 (mysql:3306 / dameng:5236 / oracle:1521),加守卫保留用户自定义端口 · loadDbDefaults() 启动时从 /api/db-defaults 读连接默认值填表单 · charset 下拉新增 al32utf8 / zhs16gbk(Oracle NLS 字符集) · Oracle radio 暂未实装完成,先注释隐藏(后端代码保留,放开零成本) 【连接默认值独立配置】 - web/configs/db_defaults.yaml(新增,.gitignore 排除,存真实凭据) - web/api/routes.py:新增 GET /api/db-defaults 端点 - .gitignore:补 web/configs/db_defaults.yaml 防止真实凭据误提交 【诊断与日志】 - scripts/_probe_dm.py:达梦连接独立诊断工具(C 扩展吞异常时排查用) - docs/WORKLOG.md:本次任务完整工作记录(含三库字典表差异表) 【未提交】 - web/configs/db_defaults.yaml(真实密码,gitignore 排除) - scripts/_tmp_build_violations_md.py(一次性调试脚本,硬编码绝对路径) - data_dictionary/standard_fields_violations_report.md(生成报告,非源码)
-
- 10 Aug, 2026 6 commits
-
-
Data Governance Dev authored
- 把 groupedResultTabs (嵌套结构) 重构为 flatResultRows (与 flatCheckRows 同构的扁平行) - 删除 resultGroupsExpanded / toggleResultGroupExpand / setAllResultGroupsExpanded 三个 result 专用函数 - 共用 expandedGroups / toggleGroupExpand / setAllGroupsExpanded - 分析结果折叠树模板完全对齐检测指标的 .tree-row / .tree-caret / group-* / treeRowStyle(row) - 分组行: caret + 标题 + 进度 + 描述 (无 checkbox —— 检测项用, 分析结果不需要) - 子行: caret-spacer + 标题 + status tag + 违规计数 + 查看按钮 - CSS 只保留 result 特有部分 (wrapper / hover / active / 计数) - WORKLOG 记录 bugfix: 上一轮 flatResultRows 读 g.children 但 API 已转成 g.checks —— 44 条结果都掉进「其他」 改用 g.checks || g.children || [] 兼容 -
Data Governance Dev authored
=== 第一批:单位基本信息 7 项 === * IND-012-a 单位名称 格式(length [4,100]) * IND-013-a 单位类型 值域(GB/T 12402-2017) * IND-013-b 经济类型 值域(国统字〔2011〕86 号) * IND-013-c 行业代码 格式(GB/T 4754-2017) * IND-014-a 单位设立日期(GB/T 7408) * IND-014-b 启缴年月(GB/T 7408) * IND-015-a 发薪日 值域 === 第二批:对公账户 + 老代码兼容 3 项 === * IND-002-c USCC 老代码兼容(GB 32100-2015 附录 A.1 + GB/T 12403-1990 MOD 11) * IND-016-a CNAPS 联行号 格式(12 位 + 行别字典) * IND-016-b 银行账号 格式(12~22 位 + 16~19 位 Luhn) === 第三批:跨表/跨字段 2 项 === * IND-901 单位名 全局唯一性(单字段 GROUP BY HAVING) * IND-902 账户名 一致性(同行双字段配对 + 容错归一化) === 配套 === * 11 个已有 indicator 补 comment_keywords 让法人/经办人/单位字段自动匹配 - ind_003a_mobile / 005a_fixed_phone / 006a_address / 006b_postal_code - ind_101_id_type / 201_id_card / 202_passport / 203_hkmacao / 204_foreign - ind_401_name_charset / 402_name_length * orchestrator _derive_target + special_checks 加 12 段描述 * analysis_tree.json 新增 2 个分组: - business_unit(IND-012~15) - business_unit_bank(IND-016 + 901/902) - standards 组加 IND-002-c(老代码兼容归入 USCC 体系) * step7 dispatch 扩展为 4 类执行路径: - 单值 / 跨字段 / 跨表聚合 / 跨表单字段 GROUP BY - 新增 _run_round3_global_uniqueness_one / _run_round3_cross_field_one - run_step7_for_indicator if/elif 链加 IND-901/902 分支 * 2 个新 SQL 模板: - sample_field_groups_single.sql(IND-901) - sample_field_pairs_two_text.sql(IND-902) * WORKLOG.md 加 2 段工作记录(含 GB/T 12403 字符集修正、GB/T 4754 位数修正等关键技术细节) 验证:orchestrator._STEPS 从 36 → 48 个 step(+12)
-
Data Governance Dev authored
字段匹配双路化(comment_keywords 优先于 applies_to_fields): - standards/base.py: BaseStandard 加 comment_keywords: list[str] - web/core/step_impl/step7_standards.py: 新增 _collect_hit_columns() 第 1 路按字段名命中,第 2 路按字段注释 substring 命中(不区分大小写) 两路并集去重(按 (table, column)) - standards/registry.py: list_all_standards() 输出 comment_keywords 8 个 indicator 新增/修改: - IND-003-a (改): 加「不可全 0」前置校验 - IND-005-a (新): GB/T 15835 固定电话(区号 3~4 位 + 号码 7~8 位) - IND-006-a (新): 通讯地址(长度 [4,200],非全空白/符号/数字) - IND-006-b (新): GB/T 23705 邮编(6 位数字) - IND-007-a (新): 个人公积金账号(仅位数 check,10/12/18 位,applies_to_fields 故意留空) - IND-008-a (新): 首次参加工作年月(YYYYMM/MMDD) - IND-009-a (新): 用工类型(6 值枚举 + 文字形式) - IND-010-a (新): 本地户籍标记(1/0、是/否、Y/N、T/F、TRUE/FALSE) - IND-011-a (新): 职工状态(5 值枚举 + 流转规则说明) orchestrator / 前端: - web/core/orchestrator.py: _derive_target / _derive_check 加 8 个新 indicator 分支; _register_indicator_steps() description 同时显示字段名 + 注释关键字 - web/configs/analysis_tree.json: 注册 8 个新 step_id;新增「业务字段规范」组(默认展开) - 国标字段规范组加 std_ind_005_a KPI 去 card 化: - web/static/style.css: 去掉 .kpi-card 的 background / shadow / border / radius / padding; 改为数字带色 + label 灰字的纯文字布局,密排紧凑 已知限制: - IND-011-a 流转限制(销户 → 不可缴存、封存 → 可偿贷)需跨表 SQL JOIN, 本轮仅在 description 写明业务规则,留待后续跨表 indicator WORKLOG: docs/WORKLOG.md 2026-08-10 第二条 -
Data Governance Dev authored
要点: - 后端:StepDetail 从 3 段扩到 4 段(加 check 段,校验规则细节) - BaseStandard 加可选 check_detail 字段(子类可覆写,默认空) - 4 个基础 step 手填 4 段详细说明(含步骤编号 / 阈值 / 处理策略) - 24 个 indicator 通过 _derive_check() 派生:每个 indicator 一段 「业务背景 + 校验要点」摘要(含正则 / MOD 算法 / 号段表 / 国标号 / 业务标准引用) - 前端:每个 leaf 行 checkbox 后加灰色圆 i 图标,hover 弹出 4 段 tooltip,规则段用 <pre> 暗色等宽字体渲染多行 修两个 root cause: 1. <span class="tree-caret-spacer" /> 自闭合写法在 Vue 模板里被吞—— 所有后续兄弟节点(el-checkbox / el-tooltip / info-icon)全被塞进 20px 宽的 spacer 里 overflow:hidden 截掉 → 改为显式 <span class="tree-caret-spacer"></span> 2. flatCheckRows push leaf 时没透出 c.detail,<el-tooltip v-if="row.detail"> 永远不渲染 → 加 detail: c.detail || null 验证:jsdom + 真 Element Plus 跑 leaf 段渲染,info-icon + tooltip 内容完整;后端 4 段全填(merge_redundancy / IND-001-a / IND-301 / IND-502 等抽样验证)。 兼容性:StepDetail.check / BaseStandard.check_detail 都是 Optional, 旧调用 register_step 不传 detail 也不会报错。
-
Data Governance Dev authored
要点: - 后端:从 web/configs/analysis_tree.json 读分组,与 orchestrator 的 step_defs 合并返给前端;JSON 没引到的 step 自动归 __ungrouped__, 避免静默丢失 - 前端:丢掉 el-table tree-props,自己渲染 caret + el-checkbox, 每行固定 28px;caret 从 <button><el-icon><CaretRight/></el-icon></button> 改为 <span>{{ _expanded ? '▼' : '▶ ' }}</span>(不再依赖 svg icon 组件) - 描述:inline ellipsis + :title 悬停(不再用 el-tooltip 包 el-checkbox) - README:新增「调整检查项分组(不改前端)」章节说明 JSON 结构 - 验证:scripts/verify_tree.cjs (23 cases) / verify_caret_span.cjs / verify_prod_tree.cjs(jsdom + Vue 3.5.40 prod build 实际渲染 DOM) 兼容性:/api/steps 保留;form.steps 仍为 flat step_id 列表; step 注册只动 orchestrator,分组只动 JSON。 -
Data Governance Dev authored
国标分析改造两阶段,合并提交: 【阶段 1】拆分 + 新增 5 类分析对象 - STD-001 身份证 → IND-001-a/b/c/d (格式/校验位/出生日期/15位兼容) - STD-002 USCC → IND-002-a/b (格式/校验位) - STD-003 手机 → IND-003-a/b (格式/号段) - STD-004 区划 → IND-004-a/b (格式/编码存在) - 新增 IND-101 证件类型枚举(5 值) - 新增 IND-201~204 4 种证件号码(身份证/护照/港澳台居住证/外国人永居) - 新增 IND-301 跨字段 (证件类型+号码一致性) - 新增 IND-302 跨表 (证件唯一性,GROUP BY HAVING) - 新增 IND-401/402 姓名 (字符集/长度) - 新增 IND-501/502 出生日期 (格式/年龄范围, 性别推断退休年龄) - 新增 IND-601/602/603 区划/民族/婚姻 基础设施: - BaseStandard 加 group/severity/depends_on 类属性 + validate_rows() 默认实现 - registry.list_all_standards / list_standards_by_group - data_loader.py 惰性加载 data/*.json + extracted_standards.json - 新增 data/{id_type,marriage,gender,retirement_age}.json - 旧 STD-001~004 标 [已拆分], applies_to_fields=[] (保留兼容) 【阶段 2】每个 indicator 注册为独立 step - registry.py 新增 load_standard_class / indicator_step_id / step_id_to_indicator_id / list_step_ids 工具函数 - orchestrator.py 动态按 group 顺序注册 24 个 indicator step (国标字段规范=100, 证件信息=200, 身份信息=300, 民政信息=400) - step7_standards.py 新增 run_step7_for_indicator,每个 indicator 独立 section_key (standards_ind_XXX),独立 tab - 旧 run_step7() 保留 (向后兼容: 跑全部按 4 group 输出) 校验层: - IND-301 用 sample_field_pairs.sql - IND-302 用 sample_field_groups.sql - 84 单测覆盖所有 indicator (tests/test_indicators.py) 协议层: - 沿用上轮的 tab_protocol;每个 indicator 一个独立 tab (1 KPI 违规字段 + 1 KPI 检查字段 + 2 表: 指标汇总 + 违规明细) 详细工作记录见 docs/WORKLOG.md。
-
- 07 Aug, 2026 4 commits
-
-
Data Governance Dev authored
把 6 个 tab (merge / redundancy / empty / missing / length / standards) 的展示抽出成通用协议,让每个 step 在 data 里嵌入 _protocol 自描述渲染, 前端一个通用 renderer 按协议渲染;新增 step 只需写 data + 嵌 _protocol, 零前端改动。 后端 - 新建 web/core/tab_protocol.py:dataclass (TabProtocol / KpiSpec / SummarySpec / TableSpec / ColumnSpec / RenderSpec / LinkageSpec) + _eval_path() 路径表达式求值 + make_protocol() 一站式 helper - 5 个 step 文件在 return 里嵌入 _protocol - step2_merge_redundancy.py:2 tab(merge_candidates + redundancy_fields) - step4_empty_fields.py:1 tab + 2 子表 + linkage;summary 加 flat 副本 - step5_missing_comments.py:1 tab - step6_length_check.py:1 tab - step7_standards.py:1 tab + 2 子表 + linkage - orchestrator.py 删 _build_overview 里 KPI 聚合逻辑 - models.py OverviewStats 缩为 5 字段(database / host / db_type / total_tables / total_fields / executed_at) 前端 web/static/index.html 大改 - 8 个硬编码 KPI 卡 → v-for='k in displayedKpis' - 6 个硬编码 <el-tab-pane>(~450 行)→ v-for='t in displayedTabs' - 删 TAB_STEP_MAP / perTableStats / flatEmptyFields / perTableRows / filteredViolations - 新增 displayedTabs / displayedKpis / tabStatus computed - 新增 evalPathExpr / resolvePath / resolveRows / renderSummary / resolveRenderPath 工具函数 - 10 种 render.kind 在 template 里以 v-else-if 分发(text / code / tag / tag_list / two_line / three_line / progress / percent / ratio / number) - 3 个嵌套展开行(merge / standards / empty_fields)保留硬编码 — 展开行内容太特定,WORKLOG 记为后续协议扩展方向 文档与验证 - 新建 docs/TAB_PROTOCOL.md:完整协议规范 + 新增 step 模板 + 真实走读 - 新建 scripts/verify_protocol.cjs(12 case)+ verify_e2e.cjs(9 case) + verify_render.cjs(12 case)+ verify_template.cjs(2 case)—— 共 35 个 case 全过 - verify_template.cjs 用 jsdom + 真实 vue.global.prod.js + Function 劫持 截获编译产物,专门兜底「页面变白 / 编译出坏 JS」回归 - WORKLOG 追加 v-else fallback 编译 bug 修复(Vue 3.5.x 在长 v-else-if 链末尾输出 : () 无条件空 call expression)—— 把 v-else 改为 v-else-if="!cond" 显式条件 构建 - package.json + package-lock.json:jsdom + @vue/compiler-dom(verify 脚本的 dev 依赖) - .gitignore 加 scripts/compiled_*.js(verify_template 失败时的 debug 产物)
-
Data Governance Dev authored
# 需求 用户连续两轮反馈: 1. 「表名 / 注释」外观扁平、长字段名被截断(`bui_history_field_label_table` → `bui_history_field_labe...`) 2. 第一轮我把表名 + 表注释塞在同一 cell 两行后:「错了,两个表还是在同一行, 只是显示表信息的那个表,表名和注释不要挤在一行,显得一行很高, 我希望表名和表注释分两列显示」—— 用户要求真正拆成两列 # 修改 ## 1. style.css — 新增「数据字典浏览器」专属样式块 (+62) ```css .dict-pane { display: flex; gap: 16px; } /* 左右结构保持 */ .dict-pane-left { flex: 0 0 560px; } /* 360 → 480 → 560,容纳 4 列 */ .dict-pane-right { flex: 1; min-width: 0; } .dict-name { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: Consolas; } .dict-name--field{ display: inline-block; max-width: 100%; background: #f5f7fa; padding: 1px 6px; border-radius: 3px; color: #e6a23c; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .dict-comment { font-size: 12px; color: #909399; margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .dict-comment--empty { font-style: italic; opacity: 0.6; } ``` ## 2. index.html — 拆列 + 类替换 (+12 / -17) - 「表名 / 注释」1 列 → 「表名」+「表注释」两列(min-width=220/180) - `<style>` 块里 dict-pane 7 行样式删除(已迁去 style.css 集中管理) - 字段数列 64 → 72,selection 列 40 → 44(按钮点击更稳) - 右侧字段表:表名列 180 → 200,字段名列 160 → min-width=200, 改用 dict-name / dict-name--field 类 # 验证(jsdom 全页 mock + click 测试连接) header: 4 列 [0] 表名 min-width=220 [1] 表注释 min-width=180 [2] 字段数 width=72 [3] (selection) width=44,含全选 checkbox body row[0]: 4 td td[0] "bui_history_field_label_table" ← 表名 td[1] "数据源标识表" ← 表注释 td[2] "1" td[3] "" has-checkbox=true ← selection 列行复选框 body row[2](无注释): td[1] "(无注释)" + dict-comment--empty ← 斜体灰字 0.6 透明 # 兼容性 - dict-pane 仍为 flex-row 左右结构(用户明确要求保持) - .dict-name-cell 类暂保留(无引用,后续可清理) - selection 列放最后约束保持不变(见上一提交 a07db7bb) # 文件清单 - docs/WORKLOG.md | +129 工作记录(拆分两轮反馈) - web/static/index.html | +12 / -17 列结构 + 类替换 - web/static/style.css | +62 数据字典浏览器专属样式块 -
Data Governance Dev authored
# 问题 左侧「数据字典浏览器」表格渲染了表名 / 字段数,但每行没有勾选框,无法单选 / 多选。 # 根因 Element Plus 的列渲染 bug:当 <el-table-column type="selection"> 写在「最前」, 且后面紧跟带 <template #default> slot 的列时: - header 的 selection <th> 被算成 colspan="2" scope="colgroup" (正常应该是 colspan="1" scope="col") - body 行的 selection <td> 完全不渲染 → 整个表只剩 header 的 1 个全选框 # 验证(jsdom 跑了 4 个最小 case) | selection 位置 | 后续列类型 | 结果 | | 1 | 第 1 | 全部 prop |
✅ 3 cell + 3 checkbox | | 2 | 第 1 | 全部 default slot |❌ 2 cell + 1 checkbox(bug)| | 3 | 末尾 | 全部 default slot |✅ 3 cell + 3 checkbox | | 4 | 末尾 | 全部 prop |✅ 3 cell + 3 checkbox | 只有 case 2 复现 bug —— 确认是 selection 列在前 + 后列带 slot 的组合触发。 # 修复 web/static/index.html:142-165 — 把 <el-table-column type="selection"> 从第 1 列移到末尾(第 3 列),并加注释说明这个约束。 # 验证 jsdom 模拟完整页面渲染后: - header 第 3 列:<th class="... el-table-column--selection" colspan="1" scope="col">含全选 checkbox - body 第 3 列:<td class="... el-table-column--selection"> 含 <label class="el-checkbox"> 行复选框 - 3 行 × 1 checkbox = 3 个勾选框(全部渲染) # 兼容性 - 行复选框从视觉上从最左 → 最右;功能(toggleRowSelection / clearSelection / selection-change)不变,依赖的是 row 对象不是列顺序 - 全选 / 清空 / 反选 三个按钮逻辑不依赖列顺序 # 文件清单 - docs/WORKLOG.md | +50 工作记录(排查过程 + 4 个 case 验证表) - web/static/index.html | +4 / -1 selection 列移位 + 约束注释 -
Data Governance Dev authored
## 1. 操作模式重构(核心需求) 按用户要求把 web 端的操作模式从"启动任务时抽数据字典 + 编号步骤"改成 "测试连接时抽数据字典 + 步骤注册式可扩展 + 勾选表后再分析"。 ### 后端 - 新增 `web/core/data_dict.py`:`extract_data_dictionary(cfg)` 函数, connect-test 与 orchestrator 共用(避免重复查询) - 新增 `web/core/data_dict_cache.py`:按连接身份 (db_type/host/port/db/user) 缓存字典,缓存命中走内存,未命中现场再抽 - 删除 `web/core/step_impl/step1_data_dict.py`(从流程中彻底移除) - `web/core/orchestrator.py`: - 流程表从 `[(num, fn, ...), ...]` 改为 `dict[str, StepDef]` - 用 `register_step(...)` 装饰器一行注册一个 Step - `CRITICAL_STEPS` 改为 `{"merge_redundancy", "missing_comments"}` - `run_governance_workflow(..., tables: list[str])` 接受前端勾选的表 - `web/core/models.py`: - `ConnectRequest.tables: list[str]`(必填,空时后端返 400) - `StepInfo.num: int` → `StepInfo.id: str` + `order: int` - `JobStatusResponse.current_step: Optional[int]` → `Optional[str]` - 所有步骤列表 `list[int]` → `list[str]` - `TestConnectionResponse` 新增 `table_summary` / `data_dictionary` 字段 - `web/core/step_impl/step{2,4,5,6,7}.py`: - 全部新增 `table_filter: set[str] | None = None` 参数,开头过滤 `columns` - 全部 `step="N"` 字符串改为 `step="step_id"`(merge_redundancy / empty_fields / ...) - `web/core/job_manager.py`:`Job.current_step` / `steps_planned` / `steps_completed` / `steps_failed` 全部从 `int` 改为 `str`,`_sync_step_start/done` 同步 - `web/api/routes.py`: - `/api/connect/test` 成功后 `extract_data_dictionary` + `cache.put`, 返回 `table_summary` + `data_dictionary` - `/api/jobs` 校验 `tables` 非空,否则 `HTTP 400` - `/api/steps` 从 `get_step_defs()` 动态生成(不再写死编号) ### 前端 (`web/static/index.html` 全量重写) - 卡片 1:连接数据库(保留) - 卡片 2(新增):数据字典浏览器 - 左侧 el-table(reserve-selection):表名 / 注释 / 字段数; 全选 / 清空 / 反选 按钮 + 搜索框 - 右侧 el-table:选中表的所有字段,按 (table_name, ordinal_position) 排序 - 卡片 3:分析配置 - 步骤勾选 + 「开始分析」按钮(label 实时显示 X 张表 / Y 项检查) - 表为空时按钮 disabled 并提示 - 卡片 4:分析进度 + 日志(SSE 流式) - 卡片 5:分析结果(KPI + 多级表格) - `TAB_STEP_MAP` 改用 step_id,不再用编号 - 移除所有 "Step N:" 前缀 ## 2. 修复页面打开白屏 `web/static/index.html` 打开后页面全白,根因两层叠加: ### 2.1 多余 `</el-option>` DB 表单"字符集"里写了 `<el-option ... />` 自闭合 + `</el-option>` 显式闭合, Vue 模板编译器报 `Invalid end tag` (compiler code 23)。 修复:删除第 102 行的 `</el-option>`。 ### 2.2 `v-else-if` 链断裂(Vue 3 compiler code 30) Vue 3 要求 `v-else` / `v-else-if` 必须是上一个 v-if 元素的紧邻兄弟。模板里: - 「重新分析」按钮的 `v-else-if` 与「取消」按钮的 `v-if` 中间夹了一个 无 v-if 的「开始分析」按钮,链断 - 「勾选提示」el-alert 的 `v-else-if` 上方是 `</el-form-item>`,也不是 v-if 修复:去掉 v-else-if,改用独立 v-if 显式写互斥条件。 ## 3. 验证 - `python -c "from web.core import ..."` 全部通过 - `python -m web.app` 启动 OK,注册 5 个 step - `/api/steps` 返回 `{id, order, title, ...}`(无 num) - `/api/connect/test` 无 DB 时 ok=false,含 `table_summary: []`, `data_dictionary: []` - `/api/jobs` 空 tables → `HTTP 400 {"detail": "tables 不能为空:..."}` - 用 jsdom 抓真服务器返回的 `#app.innerHTML`(59914 字符), 喂给浏览器版 Vue 3.5.40 编译:errors=0, warnings=0 - jsdom 完整挂载:`#app` 渲染 2 子元素 / 8484 字符真实 DOM ## 4. 兼容性 - 旧的 `outputs/<db>/<ts>/findings/step_*_data_dict.json` 文件保留(前端不读) - `step8_report.py` 消费的 6 个 section key (`merge_candidates` / `redundancy_fields` / `empty_fields` / `missing_comments` / `length_issues` / `standard_violations`)全部保留 ## 5. 文件清单 新增: - `web/core/data_dict.py` - `web/core/data_dict_cache.py` - `docs/WORKLOG.md` 删除: - `web/core/step_impl/step1_data_dict.py` 修改: - `web/api/routes.py` - `web/core/job_manager.py` - `web/core/models.py` - `web/core/orchestrator.py` - `web/core/step_impl/step{2,4,5,6,7}_*.py` - `web/static/index.html`(全量重写) - `web/README.md` - `CLAUDE.md`(项目说明改为"数据治理工具,主要开发 web 端") - `.gitignore`(加 tags.lock / tags.temp)
-