feat: 数据实体Tab加多写方风险维度(老莫思维提升)——holding_strategies 10写方等高风险标红,孤立死实体标注。修复mofin_db elif缩进
This commit is contained in:
@@ -2131,7 +2131,7 @@ def write_holding_strategy(conn, code: str, name: str, data: dict,
|
||||
data['stop_loss'] = float(_op[2])
|
||||
data['take_profit'] = float(_op[3])
|
||||
print(f" [AUTHORITY-POS] {code} 保护系统仓位'{_old_pos_val[:30]}'", flush=True)
|
||||
elif _old_ra:
|
||||
elif _old_ra:
|
||||
try:
|
||||
from datetime import datetime as _ddt3, timedelta as _dtd3
|
||||
_ra_dt3 = _ddt3.fromisoformat(str(_old_ra)[:19])
|
||||
|
||||
@@ -940,6 +940,24 @@ def build_report():
|
||||
flow_status = "read_only"
|
||||
else:
|
||||
flow_status = "orphan"
|
||||
wcnt, rcnt = len(writers), len(readers)
|
||||
# 2026-08-19 多写方风险(老莫:数据篡改风险的根源)
|
||||
# 写方>=3 → 高风险(多个模块竞争写同一实体,可能互相覆写/篡改)
|
||||
if wcnt >= 3:
|
||||
risk = "high"
|
||||
risk_note = f"⚠️多写方{wcnt}(竞争写,可能篡改)"
|
||||
elif wcnt == 0:
|
||||
risk = "orphan"
|
||||
risk_note = "无写方(死实体)"
|
||||
elif rcnt == 0:
|
||||
risk = "write_only"
|
||||
risk_note = "写无读(幽灵)"
|
||||
elif wcnt == 2:
|
||||
risk = "watch"
|
||||
risk_note = f"{wcnt}写方(需关注)"
|
||||
else:
|
||||
risk = "ok"
|
||||
risk_note = ""
|
||||
entities.append({
|
||||
"name": tname,
|
||||
"desc": TABLES_DESC.get(tname, ""),
|
||||
@@ -947,11 +965,16 @@ def build_report():
|
||||
"rows": cnt,
|
||||
"readers": readers[:10],
|
||||
"writers": writers[:10],
|
||||
"writer_count": wcnt,
|
||||
"reader_count": rcnt,
|
||||
"multi_writer": wcnt >= 3,
|
||||
"risk": risk,
|
||||
"risk_note": risk_note,
|
||||
"has_input": has_input,
|
||||
"has_output": has_output,
|
||||
"orphan": flow_status in ("orphan", "read_only", "write_only"),
|
||||
"flow_status": flow_status,
|
||||
"warn": flow_status != "healthy",
|
||||
"warn": flow_status != "healthy" or wcnt >= 3,
|
||||
"flow_detail": flow_detail,
|
||||
})
|
||||
|
||||
|
||||
@@ -269,6 +269,14 @@ function renderDataFlow(entities, jsonFiles, architecture) {
|
||||
}
|
||||
|
||||
html += `显示 ${filtered.length} 个数据表 + ${jf.length} 个JSON文件的读写流向。绿色→写入,蓝色→读取。</div>`;
|
||||
// 2026-08-19 多写方风险汇总
|
||||
const risky = filtered.filter(e => (e.risk==='high'||(e.writers||[]).length>=3));
|
||||
if (risky.length > 0) {
|
||||
html += `<div style="background:#3d1c02;border:1px solid #f85149;border-radius:6px;padding:8px;margin:8px 0">`;
|
||||
html += `<div style="font-weight:bold;color:#f85149;font-size:12px;margin-bottom:4px">🚨 篡改风险:${risky.length} 个数据实体有多写方竞争</div>`;
|
||||
html += `<div style="font-size:11px;color:#d29922">多写方=多个模块写同一实体,可能互相覆写/篡改。重点:holding_strategies(策略参数)、candidates(候选池)、todos等。</div>`;
|
||||
html += `</div>`;
|
||||
}
|
||||
|
||||
// 按写入方数量排序,最活跃的排前面
|
||||
filtered.sort((a,b) => (b.writers||[]).length - (a.writers||[]).length);
|
||||
@@ -282,7 +290,18 @@ function renderDataFlow(entities, jsonFiles, architecture) {
|
||||
const rDesc = fd.readers || {};
|
||||
|
||||
html += '<div style="background:#161b22;border:1px solid #30363d;border-radius:6px;padding:10px;margin-bottom:8px">';
|
||||
html += `<div style="font-weight:bold;font-size:14px;color:#58a6ff;margin-bottom:4px">🗄️ ${e.name}</div>`;
|
||||
// 2026-08-19 多写方风险徽标(老莫:数据篡改风险)
|
||||
const wcnt = e.writer_count || (e.writers||[]).length;
|
||||
const rcnt = e.reader_count || (e.readers||[]).length;
|
||||
let riskBadge = '';
|
||||
if (e.risk === 'high' || wcnt >= 3) {
|
||||
riskBadge = `<span style="background:#3d1c02;color:#f85149;border:1px solid #f85149;border-radius:4px;padding:1px 6px;font-size:10px;margin-left:6px">⚠️多写方${wcnt}·篡改风险</span>`;
|
||||
} else if (wcnt === 0) {
|
||||
riskBadge = `<span style="color:#f85149;border:1px solid #f85149;border-radius:4px;padding:1px 6px;font-size:10px;margin-left:6px">☠️无写方·死实体</span>`;
|
||||
} else if (wcnt === 2) {
|
||||
riskBadge = `<span style="color:#d29922;border:1px solid #d29922;border-radius:4px;padding:1px 6px;font-size:10px;margin-left:6px">${wcnt}写方·关注</span>`;
|
||||
}
|
||||
html += `<div style="font-weight:bold;font-size:14px;color:#58a6ff;margin-bottom:4px">🗄️ ${e.name}${riskBadge} <span style="font-size:10px;color:#8b949e;font-weight:normal">(${wcnt}写/ ${rcnt}读)</span></div>`;
|
||||
html += `<div style="font-size:11px;color:#8b949e;margin-bottom:4px">${e.desc||''}</div>`;
|
||||
// 综合总结
|
||||
if (fd.summary) {
|
||||
|
||||
Reference in New Issue
Block a user