diff --git a/scripts/mofin_health.py b/scripts/mofin_health.py index 4191f791..3c718e97 100644 --- a/scripts/mofin_health.py +++ b/scripts/mofin_health.py @@ -394,7 +394,17 @@ def build_report(): has_output = len(readers) > 0 # 排除系统表 is_system = tname.startswith("sqlite_") or tname.startswith("_") - orphan = (not has_input or not has_output) and not is_system and cnt > 0 + if is_system: + continue + # 数据流状态:healthy / write_only / read_only / orphan + if has_input and has_output: + flow_status = "healthy" + elif has_input and not has_output: + flow_status = "write_only" + elif not has_input and has_output: + flow_status = "read_only" + else: + flow_status = "orphan" entities.append({ "name": tname, "desc": TABLES_DESC.get(tname, ""), @@ -403,8 +413,9 @@ def build_report(): "writers": writers[:10], "has_input": has_input, "has_output": has_output, - "orphan": orphan, - "warn": orphan or (cnt == 0 and tname not in ("capital_flow_cache","")), + "orphan": flow_status in ("orphan", "read_only", "write_only"), + "flow_status": flow_status, + "warn": flow_status != "healthy", }) # JSON文件 diff --git a/static/mofin_health.html b/static/mofin_health.html index 66774d2f..945cf982 100644 --- a/static/mofin_health.html +++ b/static/mofin_health.html @@ -236,7 +236,10 @@ function loadData() { `生成: ${d.generated_at}` + `功能: ✅${cnt.ok} ⚠️${cnt.warn} ❌${cnt.fail}` + `Cron: ✅${pipeOk} ❌${pipeErr} 共${d.pipelines.length}` + - `数据表: ${d.entities.length} | 孤立: ${d.entities.filter(e=>e.orphan).length}`; + `数据表: ${d.entities.length} | ` + + `孤立${d.entities.filter(e=>e.flow_status==='orphan').length} ` + + `写无读${d.entities.filter(e=>e.flow_status==='write_only').length} ` + + `读无写${d.entities.filter(e=>e.flow_status==='read_only').length}`; // Tab 0: 功能树 document.getElementById('panel0').innerHTML = renderFeatureTree(d.feature_tree); @@ -245,14 +248,17 @@ function loadData() { document.getElementById('panel1').innerHTML = renderPipelineTable(d.pipelines); // Tab 2: 数据实体 - let h2 = ''; + let h2 = '
表名作用行数写入方读取方状态
'; d.entities.forEach(e => { + const flowMap = {healthy:'✅ 正常', write_only:'✏️ 写无读', read_only:'📖 读无写', orphan:'🔴 孤立'}; + const flowColors = {healthy:'#3fb950', write_only:'#d29922', read_only:'#58a6ff', orphan:'#f85149'}; + const badge = flowMap[e.flow_status] || '?'; + const color = flowColors[e.flow_status] || '#8b949e'; const cls = e.orphan ? 'orphan' : ''; - const badge = e.orphan ? '🔴 孤立' : (!e.has_input||!e.has_output) ? '⚠️ 单向' : '✅'; h2 += ``; h2 += ``; h2 += ``; - h2 += ``; + h2 += ``; }); (d.json_files||[]).forEach(j => { h2 += ``;
表名作用行数写入方读取方数据流
${e.name}${e.desc||''}${e.rows}${(e.writers||[]).slice(0,4).join(', ')||''}${(e.readers||[]).slice(0,4).join(', ')||''}${badge}
${badge}
📄 ${j.name}${j.desc||'JSON文件'}${j.size_kb}KB