1. 页面概览

1.1 是什么

数据质量页面(QualityPage.vue)是 LightFoundry 对数据资产做「规则化质检 + 问题闭环 + 四因子评分」的统一界面。页面以三个 Tab 组织三类能力:

这三块能力在 V5 Stage 1(B1-2 质量画像、B1-3 同步引擎 bridge)落地:质量画像的低于阈值评分会经 profileIssueBridge 写入既有的 data_quality_issues 表,复用「质量问题」Tab 的列表与 acknowledge/fix 闭环;同步引擎(sync 包)运行成功后也会经 datasetProfileBridge 自动触发画像评分,形成「同步 → 画像 → 问题」的数据健康链路。

1.2 核心价值

维度说明
规则化质检四类规则(null/format/unique/referential)声明式配置,检查结果带违规行数与样本
问题闭环open → acknowledged → fixed 三段状态机,确认/修复操作有二次确认保护
四因子画像completeness/uniqueness/validity/freshness 加权总分(0~100),阈值可配
诚实标注validity 超 1000 行拉样标注 sampled、缺 pk/水位列标注 na,不静默吞掉
自动联动画像低于阈值自动产生 issue;同步成功自动触发画像;cron 调度定时运行
独立 API 实例画像模块走 qualityProfileApi.js(超时 120 秒),与普通接口隔离

1.3 一句话总结

在 Foundry 用「规则 + 画像」双重手段管理数据质量:规则负责把问题揪出来闭环处理,画像负责给数据集打出可解释的四因子健康分,两者共用一张问题表闭环联动。

2. 访问入口

2.1 路由与菜单

2.2 认证与权限

2.3 端口与 API 前缀

3. 界面布局

页面纵向整体结构如下(三 Tab 横向切换):

┌────────────────────────────────────────────────────────────┐
│ ① 页头:标题「数据质量」                                      │
│ ② 操作结果提示条(alert,成功绿 / 失败红,可关闭)             │
│ ③ Tab 切换:[规则管理] [质量问题] [质量画像]                  │
│ ┌────────────── Tab1 规则管理 ──────────────┐                │
│ │ 卡片:标题(规则管理)+「+ 新建规则」按钮    │                │
│ │  ├─ 创建规则表单(展开后出现,可收起)       │                │
│ │  ├─ 编辑规则表单(选中行后出现:名称/配置/   │                │
│ │  │   严重级别/启用位;类型与作用域只读)     │                │
│ │  ├─ 规则列表表格(ID/名称/范围/对象/类型/    │                │
│ │  │   检查列/严重级别/状态/操作)             │                │
│ │  ├─ 本地分页(每页 10 条)                  │                │
│ │  └─ 诚实提示:列表无服务端分页;规则可改     │                │
│ │      名称/配置/严重级别,作用域与类型不可变  │                │
│ ├────────────── Tab2 质量问题 ──────────────┤                │
│ │ 卡片:状态筛选下拉 +「刷新」按钮             │                │
│ │ 卡片:问题列表表格(含样本展开行)+ 本地分页  │                │
│ ├────────────── Tab3 质量画像 ──────────────┤                │
│ │ QualityProfilePanel:工具栏 + 新建表单 +    │                │
│ │ 画像列表(含本地分页)+ 已删除画像(本次会话)│               │
│ │ + 评分历史抽屉                              │                │
│ └────────────────────────────────────────────┘                │
└────────────────────────────────────────────────────────────┘

各板块职责:

4. 交互元素详解

4.1 Tab 切换

属性
控件三个按钮组成的 Tab 条(.tab-btn,激活态带下划线高亮)
选项「规则管理」「质量问题」「质量画像」,对应 tabs 数组 rules/issues/profiles
交互效果点击切换 activeTabv-if 控制仅渲染当前 Tab 内容

4.2 Tab1 规则管理 —— 新建规则入口

属性
按钮文字「+ 新建规则」(表单展开时变为「收起表单」)
交互效果切换 showCreateForm,展开/收起创建表单;默认收起
表单校验前端 required 标记:规则名称、作用对象 ID、检查列;另有 handleCreate 内的逻辑校验(见 4.4)

4.3 创建规则表单字段

字段控件必填默认值说明
规则名称<input>orders_amount_not_null,创建时 trim()
作用范围 scope_type<select>objectpipeline(管道)/ object(本体对象)
作用对象 ID scope_id<input type=number>1数字,如 1
规则类型 rule_type<select>nullnull/format/unique/referential
严重级别 severity<select>warningwarning/error(error 违规会使管道 run 标 failed)
检查列 column<input>被检查属性列,如 amount
格式正则 format_regex<input>format 时是rule_type=format 时显示,如 ^[0-9]{11}$
引用表 ref_table<input>referential 时是rule_type=referential 时显示,如 customers
引用列 ref_column<input>referential 时是rule_type=referential 时显示,如 id
创建后即启用<checkbox>勾选对应 enabled 字段

动态提示:当 rule_typenullunique 时,表单下方显示「规则类型「null」仅需指定检查列,无需额外配置。」(文案随类型变化)。

提交按钮:「创建规则」(提交中变「提交中...」并禁用)与「取消」(调 resetCreateForm 清空表单并收起)。

4.4 创建规则逻辑校验与提交

点击「创建规则」后 handleCreate 先做前端校验:

校验通过后 buildRuleConfig() 按类型组装 rule_configcolumn 恒有;format 追加 format_regexreferential 追加 referential:{ref_table, ref_column}),再 POST /quality/rules 提交 {name, scope_type, scope_id, rule_type, rule_config, severity, enabled}。成功后提示「规则创建成功 id=...」并刷新列表;失败提示「规则创建失败:<后端 error>」。

4.5 规则列表表格

说明
ID规则主键
名称加粗展示
作用范围scope_type 原文
作用对象# + scope_id
规则类型rule_type 原文
检查列ruleColumn(r) 拼接:column,format 追加 · 正则,referential 追加 · 引用 表.列
严重级别徽章 sev-warning(黄)/sev-error(红)
状态徽章「启用」(绿)/「停用」(灰)
操作「编辑」+「停用/启用」+「删除」三个小按钮

启用/停用handleTogglePUT /quality/rules/:id,请求体 {enabled: !r.enabled},成功后提示「规则"xxx"已停用/启用」并刷新。删除:先 confirm 二次确认「确定删除规则"xxx"吗?(历史问题保留)」,确认后 DELETE /quality/rules/:id,成功提示「规则已删除」,历史问题保留(只删规则定义,data_quality_issues 不受影响)。

编辑规则:行内「编辑」按钮(startEditRule)回填 editForm(名称 / 严重级别 / rule_config / 启用位),在创建表单下方展开编辑表单(类型与作用域只读展示)。保存(handleUpdateRule)调 PUT /quality/rules/:id,请求体 {name, severity, rule_config, enabled};成功后提示「规则"xxx"已更新」并刷新列表。作用域(scope_type/scope_id)与规则类型(rule_type)不可变更(后端刻意留作不可变:变更等同重建规则并令历史问题归属失真),需更换请删除后重建——表单以只读字段标注。

本地分页pagedRules 按每页 10 条切片,分页条仅规则数 > 10 时显示;GET /quality/rules 无分页参数(见 5.2),故为渲染层分页,仍一次全量拉取。

4.6 Tab2 质量问题 —— 状态筛选与刷新

属性
控件状态筛选下拉(selectmin-width:160px)+「刷新」按钮
筛选选项全部 / open(待处理)/ acknowledged(已确认)/ fixed(已修复)
交互效果下拉 change 立即触发 fetchIssues;「刷新」手动重新拉取;请求带 ?status= 参数(空值不带参数)

4.7 问题列表表格

说明
ID问题主键
规则 ID# + rule_id
受影响表affected_table
违规行数issueCount(it):取 affected_rows.count,缺失显示 -
状态徽章 issue-open(红)/issue-acknowledged(黄)/issue-fixed(绿)
创建时间formatTime(created_at)2026-08-09T10:00:00Z → 2026-08-09 10:00:00
操作「样本」+「确认」+「修复」

样本展开:点击「样本」切换 expandedId,展开行跨 7 列显示「违规样本 sample(N 行)」子表格,列头由 sampleColumns(it) 取样本首行对象的键生成,值 row[k] 逐格渲染;无样本显示「无样本数据」。

确认:仅 status=open 时可点(否则禁用),先 confirm「确认问题 #N(表 xxx)吗?」,再 POST /quality/issues/:id/acknowledge,成功提示「问题 #N 已确认(状态:acknowledged)」。

修复status=fixed 时禁用,先 confirm「确定将问题 #N(表 xxx)标记为已修复吗?」,再 POST /quality/issues/:id/fix,成功提示「问题 #N 已修复(状态:fixed)」。

本地分页pagedIssues 按每页 10 条切片,分页条仅问题数 > 10 时显示;GET /quality/issues 无分页参数(见 5.2),故为渲染层分页。切换状态筛选或点「刷新」后页码重置为第 1 页并收起样本展开行(避免展开行不在当前页导致错位)。

4.8 Tab3 质量画像 —— 工具栏与创建表单

工具栏:「+ 新建画像」(展开时变「收起表单」)+「刷新」按钮(fetchAll 并行拉画像与数据集)。

新建画像表单QualityProfilePanel.vue):

字段控件必填默认说明
画像名称<input>orders_quality_daily
作用范围 scope_type<select>datasetdataset(数据集)/ object(本体对象,本版仅登记)
作用对象 scope_iddataset 下拉 / object 输入框dataset 时下拉展示 名称(N 行),value 为数据集 id
阈值 threshold<input type=number>600~100,总分低于阈值产生质量问题
completeness 完整度<input type=number step=0.05>0.45权重
uniqueness 唯一度<input type=number step=0.05>0.25权重
validity 有效性<input type=number step=0.05>0.15权重
freshness 新鲜度<input type=number step=0.05>0.15权重
主键列 pk_column<input>唯一度用,缺省按 1 记并标注 na
水位列 watermark_col<input>新鲜度用,缺省按 1 记并标注 na
调度 schedule<input>5/6 段 cron 或 @ 描述符,如 0 9 * * *

关键提示文案:四因子权重「留空使用默认 0.45/0.25/0.15/0.15;不必凑 1,后端自动归一」;计算配置下方说明「四因子 SQL 下推计算;validity 对 date 列与下推困难的列拉 ≤1000 行样本计算并标注 sampled;低于 threshold 产生质量问题(连续低于阈值自动去重,恢复后再次跌破重新触发)。」

提交:「创建」(创建中变「创建中...」)与「取消」。handleCreate 组装 payload:{name, scope_type, scope_id} 必填,threshold 非空转数字、权重按非空逐项填入 weightspk_column/watermark_col 非空填入 configschedule 非空直接透传,然后 POST /quality/profiles。成功提示「画像创建成功」并刷新。

4.9 画像列表表格

说明
名称加粗展示
作用范围徽章 scope-dataset(蓝)/scope-object(紫)+ 作用对象名(scopeName:dataset 反查数据集名)
权重(c/u/v/f)weightsSummary 解析 JSON 后四段数字,如 0.45 / 0.25 / 0.15 / 0.15
阈值threshold 数字
调度code 展示 cron,空显示「手动」
最新总分徽章 score-high(≥80 绿)/score-mid(≥60 橙)/score-low(<60 红),未运行显示「未运行」
状态徽章「启用」(status-on 绿)/「停用」(status-off 灰)
更新时间fmtTime(updated_at)
操作「运行」「历史」「停用/启用」「删除」

已删除画像(本次会话保留):删除画像只删 fq_profiles 定义,评分历史 fq_scores 在后端保留,且 GET /quality/profiles/:id/scoresprofile_id 直查、不校验画像是否存在foundry/quality/profile.go:882-896 ListScores 无非存在性判断),故删除后仍可查历史。前端在删除时把画像对象(附 deleted_at)推入会话级 deletedProfiles,在画像列表下方渲染「已删除画像(本次会话保留 · N)」卡片,每行保留「历史」按钮可继续打开评分历史抽屉。后端没有枚举已删除画像的端点,因此该入口只存在于本次会话(刷新页面后消失),卡片内常驻诚实提示。

4.10 评分历史抽屉

右侧滑出抽屉(宽度 min(920px, 94vw)),含画像信息(scope 徽章 + 名称 + 阈值 + 调度任务名 quality:<id>)与「关闭」按钮。

评分记录表格:时间 / 总分(徽章)/ 完整度 / 唯一度 / 有效性 / 新鲜度 / 行数 / 备注 / 明细。备注列展示:已产生 issue(红标签,details.issue_created)、issue_skipped 说明(未接问题出口)、note-;明细列「展开/收起」按钮切换因子级与列级明细。

因子明细表:因子 / 分值 / 方式(method-pushdown 下推蓝、method-sampled 抽样橙、method-na 灰色)/ 说明。列级明细表:列 / 因子 / 分值 / 方式 / 说明,列为 * 表示全表级。空明细显示「无因子明细」「无列级明细」。

5. 后端关联

5.1 API 客户端

5.2 端点表

方法路径请求体说明
GET/quality/rules—(无分页参数,可选 ?scope_type=&scope_id= 过滤)规则列表(全量返回)
POST/quality/rules{name, scope_type, scope_id, rule_type, rule_config, severity, enabled}创建规则,返回 {id}
PUT/quality/rules/:id{enabled}仅此一字段,缺省 400 enabled is required启用/停用(不支持改配置)
DELETE/quality/rules/:id删除规则(历史问题保留)
GET/quality/issues—(无分页参数,可选 ?status=open|acknowledged|fixed问题列表(全量返回)
POST/quality/issues/:id/acknowledgeopen → acknowledged
POST/quality/issues/:id/fixopen/acknowledged → fixed
GET/quality/profiles—(无分页参数,可选 ?scope_type=&scope_id=画像列表(全量返回)
POST/quality/profiles{name, scope_type, scope_id, weights?, threshold?, schedule?, config?, enabled?}创建画像
GET/quality/profiles/:id详情(含解析后 weights/config 与 job_name
PUT/quality/profiles/:id指针字段更新(未提供保留原值)
DELETE/quality/profiles/:id删除画像(评分历史保留)
POST/quality/profiles/:id/run{}立即运行,返回本次评分+明细
GET/quality/profiles/:id/scores评分历史(?limit=,created_at 倒序)

5.3 响应结构

统一成功包装 {code: 0, data: ...};失败 {code, error}(HTTP 状态取自 ierr)。示例:

// GET /quality/rules
{ "code": 0, "data": [
  { "id": 1, "name": "orders_amount_not_null", "scope_type": "object",
    "scope_id": 1, "rule_type": "null",
    "rule_config": { "column": "amount" },
    "severity": "warning", "enabled": true,
    "created_at": "2026-08-29T10:00:00Z", "updated_at": "2026-08-29T10:00:00Z" }
]}

// GET /quality/issues
{ "code": 0, "data": [
  { "id": 3, "rule_id": 1, "affected_table": "ds_orders",
    "affected_rows": { "count": 12, "sample": [ { "id": 1, "amount": null } ] },
    "status": "open", "created_at": "2026-08-29T10:00:00Z", "updated_at": "2026-08-29T10:00:00Z" }
]}

// POST /quality/profiles/:id/run
{ "code": 0, "data": {
  "score": { "id": 7, "profile_id": 2, "total": 85.4, "completeness": 0.98,
    "uniqueness": 1.0, "validity": 0.95, "freshness": 0.6,
    "details": "{\"row_count\":12000,...}", "created_at": "..." },
  "details": { "row_count": 12000, "factors": [ {"factor":"completeness","value":0.98,"method":"pushdown","detail":"..."} ],
    "columns": [ {"column":"amount","factor":"validity","value":1,"method":"pushdown","detail":"..."} ] }
}}

5.4 关联模块表

后端包职责
foundry/pipelineQualityService:规则 CRUD、CheckQuality 检查执行、问题闭环(ListIssues/AcknowledgeIssue/FixIssue/CreateIssue);DataQualityRule/DataQualityIssue 模型
foundry/qualityProfileService:四因子画像评分、RegisterSchedule 调度注册、IssueCreator 接口(低于阈值产 issue)
foundry/syncdatasetProfileBridge:同步成功后自动触发画像运行
foundry/serverpipeline_handlers.go/quality/rules|issues 路由;quality/rest.go/quality/profiles 路由;profileIssueBridge 适配问题写入

5.5 关键机制

问题状态机open → acknowledged → fixed。确认仅 open 可执行;修复 open/acknowledged 均可。修复/确认后不自动产生新问题。

画像四因子 SQL 下推

诚实标注:任何降级/失败/na 均写入评分 detailsnote 与列级 method/detail),计算失败按 na(值 1)降级并记 Warn 日志,不阻断调度运行。

阈值 → 问题:总分低于 threshold 时经 profileIssueBridgeCreateProfileIssue)合成规则+检查结果写入 data_quality_issues;连续低于阈值自动去重(不重复造问题),恢复后再次跌破重新触发。

指针语义更新PUT /quality/profiles/:id 的请求字段全为指针类型,未提供的字段保留原值(例如启停只传 {enabled})。

6. 核心流程详解

6.1 主流程一:创建质量规则

  1. 进入「规则管理」Tab,点「+ 新建规则」展开表单;
  2. 填写名称、选择 scope_type、填 scope_id、选 rule_type、选 severity;
  3. 在 rule_config 区填检查列;format 类型补格式正则,referential 类型补引用表/列;
  4. 勾选「创建后即启用」(默认勾选);
  5. 点「创建规则」→ 前端校验 → POST /quality/rules → 成功提示并刷新列表。

分支:rule_type 为 null/unique 时无额外配置项;为 referential 时前端强制校验 ref_table/ref_column 非空。

6.2 主流程二:处理质量问题

  1. 进入「质量问题」Tab(onMounted 已拉取全部问题);
  2. 点「样本」展开违规样本,核对违规明细;
  3. 对 open 问题点「确认」→ confirm → POST /quality/issues/:id/acknowledge → 状态变 acknowledged;
  4. 点「修复」→ confirm → POST /quality/issues/:id/fix → 状态变 fixed;
  5. 可通过状态筛选只关注待处理(open)问题。

6.3 主流程三:创建并运行质量画像

  1. 进入「质量画像」Tab,点「+ 新建画像」展开表单;
  2. 填名称,选 dataset 作用域,下拉选数据集;
  3. 按需调整四因子权重(留空用默认)、阈值(默认 60)、pk_column、watermark_col、schedule cron;
  4. 点「创建」→ POST /quality/profiles → 列表出现新画像;
  5. 点「运行」→ POST /quality/profiles/:id/run → 顶部提示总分;
  6. 点「历史」→ 抽屉内「展开」查看四因子趋势与列级明细。

分支:配置了 schedule 后由统一调度器按 cron 定时运行;同步引擎(sync)运行成功也会自动触发画像(datasetProfileBridge);画像总分低于阈值自动写入问题表,可在「质量问题」Tab 看到。

6.4 任务终态语义

本页无独立任务化机制(run 为同步等待式,超时放宽到 120 秒);调度运行由统一调度器承载,任务名前缀 quality:<profileID>。run 返回的评分即终态,不轮询。

7. 权限与安全

8. 常见问题与排错

8.1 创建规则提示「加载质量规则失败」或一直转圈

8.2 创建 referential 规则提交失败

8.3 画像「运行」后总分异常偏低

8.4 问题「确认」按钮置灰无法点击

8.5 画像列表「最新总分」显示「未运行」

9. 已知缺陷与边界

说明
object scope 画像仅登记画像 scope_type=object 本版仅登记不计算(运行时明确报错/不执行),后续批次接线
schedule 变更不实时增删调度条目画像 schedule 只在服务启动时注册一次(RegisterSchedule),运行中修改 cron 需重启生效
规则作用域/类型不可改(设计取舍,非缺口)PUT /quality/rules/:id 已支持 name/rule_config/severity/enabledfoundry/server/pipeline_handlers.go:258-320pipeline.QualityService.UpdateRule);scope_type/scope_id/rule_type 刻意不可变——变更等同重建规则并令历史问题归属失真,故前端以只读字段展示并在提示中说明需删除后重建
画像删除后历史可查(本次会话)DELETE /quality/profiles/:id 保留 fq_scoresGET /quality/profiles/:id/scores 不校验画像存在(foundry/quality/profile.go:882-896),前端已补「已删除画像(本次会话)」入口继续查看历史。边界:后端无枚举已删除画像的端点,刷新页面后入口消失(属后端缺口)
调度器未注册时 run 不受影响立即运行 POST /quality/profiles/:id/run 与调度器无关,可随时手动触发
列表无服务端分页GET /quality/rules/quality/issues/quality/profiles 均无分页参数(pipeline_handlers.go:226-241 / :300-308quality/rest.go:48-58),前端已补渲染层分页(每页 10 条)但仍一次全量拉取,数据量大时首屏请求体积不变;画像评分历史保持服务端 limit(默认 100,上限 500)。最新总分为当前页画像按 limit=1 拉取(避免全量 N+1)

后端文件

项目文档

相邻页面链接