feat: DAMA数据治理规则检查(财务七规则)— 后端/check-governance + 前端数据质量中心升级
后端 backend/app/api/data_quality.py: - 新增 GET /api/cma/data-quality/check-governance?entity_id= 端点 - 7条规则: unit_check单位校验/dup_alert重复预警/orphan_check孤儿预警/virtual_pollution虚拟污染/entity_check实体归属/kpi_completeness KPI完整性/reconciliation勾稽验证 - 质量评分: error扣10/warning扣5, 每条规则最多扣一次, 最低0分 - 兼容实体筛选(0全部/1酣客/2博海), 向后兼容既有/check端点 前端 frontend/src/api/index.ts + views/DataQuality.vue: - dataQualityApi.checkGovernance() 新增 - 页面新增治理规则区: 质量评分仪表盘 + 7规则红黄绿状态表 + 异常明细展开 + 重新检查按钮 + 实体筛选
This commit is contained in:
@@ -344,6 +344,8 @@ export const dataQualityApi = {
|
||||
logs: (params?: any) => api.get('/data-quality/logs', { params }),
|
||||
updateLog: (id: number, data: any) => api.put(`/data-quality/logs/${id}`, data),
|
||||
deleteLog: (id: number) => api.delete(`/data-quality/logs/${id}`),
|
||||
// DAMA数据治理规则检查(财务七规则)
|
||||
checkGovernance: (params?: any) => api.get('/data-quality/check-governance', { params }),
|
||||
}
|
||||
|
||||
export const biReportApi = {
|
||||
|
||||
@@ -121,6 +121,80 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- DAMA 数据治理规则检查(财务七规则) -->
|
||||
<el-card shadow="never" class="section-gap">
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">
|
||||
<span>🛡️ DAMA数据治理规则检查(财务七规则)</span>
|
||||
<div>
|
||||
<el-select v-model="govEntity" style="width:130px;margin-right:8px;" @change="runGovernanceCheck">
|
||||
<el-option label="全部实体" :value="0" />
|
||||
<el-option label="酣客" :value="1" />
|
||||
<el-option label="博海" :value="2" />
|
||||
</el-select>
|
||||
<el-button type="primary" @click="runGovernanceCheck" :loading="govChecking">重新检查</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<div style="text-align:center;padding:20px 0;">
|
||||
<el-progress type="dashboard" :percentage="govScore" :color="govScoreColor" :width="150">
|
||||
<template #default>
|
||||
<div style="font-size:32px;font-weight:700;line-height:1.2;">{{ govScore }}</div>
|
||||
<div style="font-size:12px;color:#999;">质量评分</div>
|
||||
</template>
|
||||
</el-progress>
|
||||
<div style="font-size:12px;color:#999;margin-top:10px;line-height:1.8;">
|
||||
检查时间: {{ govCheckedAt || '-' }}<br />
|
||||
通过 {{ govPassedCount }} / {{ govIssues.length }} 条规则
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-table :data="govIssues" size="small" border>
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<div style="padding:10px 18px;background:#fafafa;">
|
||||
<div v-if="row.detail && row.detail.length" style="font-size:12px;line-height:24px;color:#606266;">
|
||||
<div v-for="(d, i) in row.detail" :key="i">• {{ d }}</div>
|
||||
</div>
|
||||
<div v-else style="font-size:12px;color:#67c23a;">✓ 未发现异常</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="govRuleStatus(row)" size="small">{{ govRuleStatusText(row) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规则" width="160">
|
||||
<template #default="{ row }">
|
||||
<span style="font-weight:600;">{{ govRuleName(row.rule) }}</span>
|
||||
<div style="font-size:11px;color:#999;">{{ row.rule }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检查内容" min-width="240">
|
||||
<template #default="{ row }">{{ govRuleDesc(row.rule) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="级别" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.level === 'error' ? 'danger' : 'warning'" size="small">
|
||||
{{ row.level === 'error' ? '异常' : '警告' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="异常数" width="90">
|
||||
<template #default="{ row }">
|
||||
<span :style="{ color: row.count > 0 ? '#f56c6c' : '#67c23a', fontWeight: 600 }">{{ row.count }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!-- 质量日志列表 -->
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
@@ -199,6 +273,14 @@ const checking = ref(false)
|
||||
const filterSeverity = ref('')
|
||||
const filterStatus = ref('')
|
||||
|
||||
// DAMA 数据治理规则检查状态
|
||||
const govScore = ref(0)
|
||||
const govIssues = ref<any[]>([])
|
||||
const govCheckedAt = ref('')
|
||||
const govEntity = ref(0)
|
||||
const govChecking = ref(false)
|
||||
const govRuleMeta = ref<any>({})
|
||||
|
||||
const typeChartOption = computed(() => ({
|
||||
tooltip: { trigger: 'item' },
|
||||
series: [{
|
||||
@@ -228,6 +310,33 @@ const staleDataColor = computed(() => {
|
||||
return '#f56c6c'
|
||||
})
|
||||
|
||||
// ── DAMA治理规则 computed ──
|
||||
const govPassedCount = computed(() => govIssues.value.filter((i: any) => i.count === 0).length)
|
||||
|
||||
const govScoreColor = computed(() => {
|
||||
if (govScore.value >= 90) return '#67c23a'
|
||||
if (govScore.value >= 60) return '#e6a23c'
|
||||
return '#f56c6c'
|
||||
})
|
||||
|
||||
function govRuleStatus(row: any) {
|
||||
if (row.count > 0) return row.level === 'error' ? 'danger' : 'warning'
|
||||
return 'success'
|
||||
}
|
||||
|
||||
function govRuleStatusText(row: any) {
|
||||
if (row.count > 0) return row.level === 'error' ? '异常' : '警告'
|
||||
return '通过'
|
||||
}
|
||||
|
||||
function govRuleName(rule: string) {
|
||||
return govRuleMeta.value?.[rule]?.name || rule
|
||||
}
|
||||
|
||||
function govRuleDesc(rule: string) {
|
||||
return govRuleMeta.value?.[rule]?.desc || ''
|
||||
}
|
||||
|
||||
async function loadStats() {
|
||||
try { const r: any = await dataQualityApi.stats(); stats.value = r } catch (e) {}
|
||||
}
|
||||
@@ -257,6 +366,24 @@ async function runCheck() {
|
||||
checking.value = false
|
||||
}
|
||||
|
||||
async function runGovernanceCheck() {
|
||||
govChecking.value = true
|
||||
try {
|
||||
const params: any = {}
|
||||
if (govEntity.value) params.entity_id = govEntity.value
|
||||
const r: any = await dataQualityApi.checkGovernance(params)
|
||||
govScore.value = r.score ?? 0
|
||||
govIssues.value = r.issues || []
|
||||
govCheckedAt.value = (r.checked_at || '').replace('T', ' ').slice(0, 19)
|
||||
govRuleMeta.value = r.rules_meta || {}
|
||||
const bad = (r.issues || []).filter((i: any) => i.count > 0).length
|
||||
ElMessage.success(`治理检查完成: 评分${r.score}分, 异常规则${bad}条`)
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.response?.data?.detail || '治理检查失败')
|
||||
}
|
||||
govChecking.value = false
|
||||
}
|
||||
|
||||
async function updateStatus(id: number, status: string) {
|
||||
try {
|
||||
await dataQualityApi.updateLog(id, { status })
|
||||
@@ -269,6 +396,7 @@ async function updateStatus(id: number, status: string) {
|
||||
onMounted(() => {
|
||||
loadStats()
|
||||
loadLogs()
|
||||
runGovernanceCheck()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user