feat(maps): P1 四层因果结构化 map_connections 表 + 迁移脚本 + analysis 只读端点
- 新表 map_connections(entity_id/map_id/from_node/to_node/from_layer/to_layer/ from_objective_id/to_objective_id/effect/label/sort_order),唯一键 (map_id,from,to) 保幂等 - 节点双格式兼容:层:中文目标名(生产存量 31 条)与 层-序号(前端现用) - canvas_data 保留不动(双写期);POST/DELETE 写表 + 同步 JSON,失败仅告警不阻断 - GET /connections 表优先、表空回落 canvas_data;新增 GET /connections/analysis (层统计/跨层分布/断链/反向告警不拦截) - scripts/migrate_map_connections.py 四态(check/apply/idem/rollback)+ canvas 快照回滚点 - tests: 9 条(双格式解析、双写、回落、删除同步、分析统计与告警)
This commit is contained in:
committed by
Hermes CI Fix
parent
0a6525edab
commit
adcd118498
@@ -364,6 +364,37 @@ class MapObjective(Base):
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
class MapConnection(Base):
|
||||
"""战略地图四层因果连线(2026-10-21 P1:canvas_data.connections → 独立表)
|
||||
|
||||
迁移来源 = `strategic_maps.canvas_data->connections`,双写期表与 JSON 并存
|
||||
(JSON 保留供前端渲染;表供归因/校验/分析)。
|
||||
|
||||
节点标识双兼容(生产实况两种格式并存):
|
||||
- `dim:中文目标名`(生产存量实际格式,如 `learning:贡献率思维全员培训`)
|
||||
- `dim-序号`(当前前端 MapCanvas 生成的格式,如 `learning-0`)
|
||||
原始串原样保存在 from_node/to_node,解析结果落 from_layer/to_layer/from_objective_id。
|
||||
"""
|
||||
__tablename__ = "map_connections"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("map_id", "from_node", "to_node", name="uk_map_conn_edge"),
|
||||
)
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
entity_id = Column(Integer, default=1, index=True, comment="企业ID(冗余,便于按账套直查)")
|
||||
map_id = Column(Integer, ForeignKey("strategic_maps.id", ondelete="CASCADE"), nullable=False, index=True, comment="关联战略地图")
|
||||
from_node = Column(String(255), nullable=False, comment="源节点原始标识(原样保留)")
|
||||
to_node = Column(String(255), nullable=False, comment="目标节点原始标识(原样保留)")
|
||||
from_layer = Column(String(20), nullable=True, comment="解析层: learning/process/customer/finance")
|
||||
to_layer = Column(String(20), nullable=True, comment="解析层: learning/process/customer/finance")
|
||||
from_objective_id = Column(Integer, ForeignKey("map_objectives.id", ondelete="SET NULL"), nullable=True, comment="源目标ID(可解析时回填)")
|
||||
to_objective_id = Column(Integer, ForeignKey("map_objectives.id", ondelete="SET NULL"), nullable=True, comment="目标目标ID(可解析时回填)")
|
||||
effect = Column(String(20), default="positive", comment="positive/negative(存量缺省 positive)")
|
||||
label = Column(String(255), nullable=True, comment="连线标签")
|
||||
sort_order = Column(Integer, default=0, comment="画布内原始顺序(保持渲染一致)")
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class KPICausality(Base):
|
||||
"""KPI因果链 — 记录KPI间的因果关系"""
|
||||
__tablename__ = "kpi_causality"
|
||||
|
||||
Reference in New Issue
Block a user