# AttributionAnalysis **Repository Path**: luzhongmilu/attribution-analysis ## Basic Information - **Project Name**: AttributionAnalysis - **Description**: 经营归因分析系统 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-16 - **Last Updated**: 2026-10-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 经营归因分析系统 面向企业核心经营场景的智能多维归因分析系统。设计依据: - PRD:《docs/PRD-经营归因分析系统.md》v0.3.1 - 技术方案:《docs/Spec-经营归因分析系统.md》v0.1 ## 架构 前后端分离 + 模块化单体(FastAPI)+ ARQ 异步任务 + SSE 事件流; PostgreSQL 16 单实例双库(attribution 系统库 / warehouse 数仓库,容器端口 3308); 沙箱为 Docker 一次性容器(internal 网络,只读账号,资源配额)。 ## 目录结构 ``` app/ 后端模块化单体 common/ 配置双轨(.env + config.yaml)、错误码、JWT、审计、SSE models/ 全量 ORM 模型(Spec 5.1/5.2) auth/ admin/ 认证、用户角色、审计查询、配置重载 metrics/ engine/ 指标字典、拆解引擎(差额/LMDI/Shapley/What-If 代数) agent/ sandbox/ stats/ LLM 接入、沙箱执行器、统计检验 workspace/ 会话/回合/SSE(已实现基础链路) dashboard/ 异动大盘(指标卡/异常标识/一键发起,已实现) events/ whatif/ reports/ notify/ 业务域路由(TODO 桩) worker.py pipeline.py ARQ Worker 与归因流水线编排 frontend/ Vue 3 + Element Plus + ECharts(大盘页已实现) docker/ compose(pg 3308 + redis)、沙箱镜像、initdb SQL alembic/ 迁移环境 scripts/ seed_rbac / seed_warehouse + warehouse_fixtures(造数数据集) seed_metrics(指标字典 + 三个健康指标) tests/ 守恒属性测试(S1)、下钻/统计/沙箱/大盘等 ``` ## 快速开始(dev) ```bash # 1. Python 依赖(uv,国内镜像) uv sync --extra dev # 2. 基础设施(postgres 3308 双库 + redis;首次自动执行 initdb) docker compose -f docker/compose.yaml up -d # 3. 配置 cp .env.example .env # 填 LLM_API_KEY / LLM_MODEL 等 # 业务阈值默认用 config.default.yaml;如需覆盖则 cp config.default.yaml config.yaml # 4. 建表与种子 uv run alembic revision --autogenerate -m "init schema" uv run alembic upgrade head uv run python scripts/seed_rbac.py uv run python scripts/seed_warehouse.py # 三场景造数 + sandbox_ro 授权 + DATA_SOURCE(自带自检) uv run python scripts/seed_metrics.py # 指标字典(下钻依赖的 source_mapping) uv run python scripts/seed_events.py # 业务事件日历(T-11 匹配演示,锚点对齐 seed_warehouse) # 5. 沙箱镜像(T-09 起必需;容器内 pip 拉取失败时加 --network=host) docker build --network=host -t attribution-sandbox:latest -f docker/sandbox/Dockerfile docker/sandbox # 6. 启动 uv run python main.py # API :8000(含 /api/docs) uv run arq app.worker.WorkerSettings # Worker # 7. 前端 cd frontend && npm install --registry=https://registry.npmmirror.com npm run dev # :5173,/api 代理到 :8000 ``` 管理员账号:`admin / admin@123`(仅 dev)。 ## 已实现 / TODO 对照(任务清单见 Spec 第 10 节) | 模块 | 状态 | |------|------| | 配置双轨、错误码、JWT 认证、审计基础、模型全量、SSE 通道 | 已实现 | | 拆解引擎(加法差额 / LMDI / Shapley / What-If 代数)+ 守恒测试 | 已实现 | | 多维交叉下钻装配(source_mapping 驱动 + 快照 schema + 差额高亮) | 已实现(T-05) | | 会话 CRUD / 分析回合 / 假设看板 / 证据链审核(基础链路) | 已实现 | | 示例数仓三场景造数 + sandbox_ro 只读授权 + DATA_SOURCE 内置记录 | 已实现(T-04) | | 指标字典数据(指标域/指标/口径版本/弹性系数,供下钻取数) | 已实现(T-05 前置) | | LLM 接入:意图解析 / 执行规划 / 假设生成 / 结论生成(LLM 优先 + 规则兜底) | 已实现(T-08) | | 统计检验:方法选择 + 多重比较校正 + 置信度 + 自动排除(FR-14/15) | 已实现(T-10) | | 沙箱验证:一次性容器 + 只读账号 + 越权预检与审计(FR-13/16) | 已实现(T-09) | | 看板落库 + GET /sessions/{id}/board + 阶段耗时(T-07 数据侧,AC-04) | 已实现(T-07) | | 因子贡献瀑布图(FR-31,含守恒校验)+ 工作台看板接入 | 已实现(T-07 前端) | | 动态透视表(FR-33:层级折叠/列头排序/差额染色/一键导出) | 已实现(T-07 前端) | | 异动大盘:指标卡 + 异常标识 + 一键发起归因(FR-23~25) | 已实现(T-06) | | 前端大盘页:筛选条 + 指标卡(迷你趋势/红绿对比)+ 异常列表 + 一键归因 | 已实现(T-06) | | 指标字典 CRUD / 事件 / 报告 / 简报 / 用户管理路由 | 指标字典 CRUD 已实现(T-03);事件关联/日历 已实现(T-11);报告/简报/用户管理已实现(T-13/14/02) | | 前端三栏工作台可视化(瀑布图 / 透视表 / What-If 仿真器 / 因果证据链) | 已实现(T-07/T-12/T-11) | | 指标字典页(左指标树 + 右详情:公式/来源/拆解树/弹性系数/口径版本) | 已实现(T-03 前端) | | 业务事件日历页(列表/筛选/新建/编辑) | 已实现(T-11 前端) | | 因果证据链(异动窗口 ±window_days 匹配 + 证据等级 A/B/C + 驳回/恢复) | 已实现(T-11) | | 报告归档页(七章预览 / 批注 / MD·Excel·PDF 导出 / 发布 / 授权共享) | 已实现(T-13 前端) | | 简报订阅页(周/月订阅 / 退订 / 站内通知 / 手动生成) | 已实现(T-14 前端) | | 系统管理页(用户/角色 / 审计查询 / 任务耗时 P50·P95 / 阈值热重载 / 数据源) | 已实现(T-15/T-16 前端) | | 工作台「生成归因报告」一键装配入口(FR-35) | 已实现(T-13 前端) | CI(`.github/workflows/ci.yml`)会拉起 compose、跑迁移与三份 seed 后执行 pytest; 拆解引擎的守恒属性测试为 CI 强制项(Spec 8.4)。 ## LLM 接入(T-08) 统一策略:**LLM 优先、规则兜底**。模型未配置、调用失败、返回非法 JSON 或字段越界时, 自动切换到确定性规则路径,保证链路始终可跑(PRD 第 5 节可靠性),降级原因全部记日志。 | 模块 | 职责 | 兜底规则 | |------|------|---------| | `agent/intent.py` | 意图解析 + 执行规划 | 关键词识别指标(含 GMV 等英文代号)、"近 N 天/上周/上月"推导周期、同比/环比判定 | | `agent/hypothesis.py` | 3~5 条候选假设(FR-12) | 按因子贡献率排序生成 + 外生事件/数据质量/集中度三条常备视角 | | `agent/conclusion.py` | 核心归因结论 | 严格只引用 facts 中已有的数值,不编造 | | `agent/guard.py` | 出域合规(AC-13) | 白名单字段过滤 + 手机号/邮箱/密钥脱敏;命中连接串或私钥直接拒绝 | | `agent/llm.py` | OpenAI 兼容客户端 | 主力→降级模型;token 配额(LLM_002);调用与降级事件落 LLM_CALL_LOG(AC-12) | | `agent/prompts.py` | 模板与版本 | 版本 `{purpose}-v1`,同步进 PROMPT_VERSION 表,会话冻结 prompt_version(AC-18) | 模型臆造的表/维度会被收敛回指标声明的白名单(`_validate_hypotheses`)。 环境已配百炼 `qwen3.8-flash` 时实测:一句"分析最近30天 GMV 环比下滑的原因", 模型自行定位到付费搜索转化率下降及 3C/服饰/家居三个品类——与造数时植入的异动一致。 ## 统计检验(T-10) `app/stats/verify.py` 检验引擎 + `app/stats/sampling.py` 样本取数。 方法选择规则(FR-14): | 数据类型 | 条件 | 方法 | |---------|------|------| | continuous | 样本量 ≥8 且两组均通过 Shapiro 正态性检验 | Welch t 检验(不等方差) | | continuous | 小样本 / 非正态 / 常量序列 | Mann-Whitney U 非参数 | | proportion | 输入 `[成功数, 总数]` | 双比例 z 检验 | | categorical | 两组等长频数(2×k 列联表) | 卡方独立性检验 | 批量流程:逐条算原始 p → 多重比较校正(config `stats.correction`:fdr / bonferroni / none) → 按校正后 p 映射置信度 → 低于 `hypothesis.confidence_threshold` 自动置"已排除"(FR-15)。 样本取自数仓:按假设关注的维度切片聚合出指标日序列,切成基期/分析期两组。 切片由假设文本匹配下钻行标签得到(假设提到"付费搜索"即定位该渠道); 规则兜底生成的假设不含标签时,按下钻显著性依次分配不同切片以保证区分度。 实测(mom 窗口): - 电商 GMV:三条假设全部落到付费搜索三个品类,p 2.0e-04~3.1e-07,置信度 0.95,全部确认; 其中一条通过正态性检验走 t 检验,另两条走 Mann-Whitney——方法选择确实在生效 - SaaS 续约率:只有植入异动的中型客户切片置信度 0.70 被确认, enterprise(0.118) 与 smb(0.267) 均被自动排除——FR-15 伪相关过滤生效 ## 示例数据(T-04) 三个场景各植入一处主因明确的异动,`seed_warehouse.py` 跑完会用已实现的拆解引擎自检, 三场景全部 PASS 才返回 0(保证后续演示链路可稳定拆出主因): | 场景 | 模型 | 植入异动 | 自检结果 | |------|------|---------|---------| | 电商 GMV | 乘法 / LMDI | 付费搜索渠道转化率 3.2%→1.73%(分析期后 20 天) | GMV 环比约 -10%;转化率贡献 >100%;下钻到渠道可见付费搜索 -29% | | 快消利润率 | 加法 / 差额法 | 棕榈油单价 +35% + 运费 +8% | 营收 +3% 但利润率 -4.2pp(增收不增利);原材料贡献 >130% | | SaaS 续约率 | 分层下钻 | 中型客户续约率 88%→55%,报表导出功能使用量 -75%、故障工单 ×3 | 整体续约率 -20pp;下钻到分层可见 midmarket 为唯一主因 | 窗口:分析期 30 天 / 环比基期 30 天 / 缓冲 30 天 / 同比对齐 30 天; `--anchor YYYY-MM-DD` 固定锚点日可完全复现同一份数据。 ## 下钻装配(T-05) `app/engine/drilldown.py` 依据 `METRIC.source_mapping` 从数仓取数,一次扫描同时聚合 基期与分析期(同一条 SQL,两期口径必然一致),产出透视表结构供 FR-33 渲染。 `source_mapping` 三种形态: | 形态 | 写法 | 用途 | |------|------|------| | 加总型 | `"value": {"expr": "gmv"}` | GMV 等可加总指标 | | 比率型 | `"value": {"numerator": "revenue - raw_material_cost", "denominator": "revenue"}` | 利润率等,先分别聚合再相除,避免辛普森悖论 | | 条件计数 | `"value": {"numerator": "1", "denominator": "1", "numerator_filter": "renewed"}` | 续约率 = 已续约数 / 到期数 | 维度若不在主表,用 `table` + `join_on` 声明(如 SaaS 的 `segment` 需 JOIN `customers`); `label_table/label_key/label_column` 用于取可读名称(`CH_PAI` → 付费搜索)。 表名/列名/表达式均经白名单校验后才拼进 SQL,未声明的维度一律拒绝。 传入 `snapshot_schema` 即切换到会话冻结的快照,防口径漂移(FR-41A)。 已验证的下钻结果(mom,对齐最新数据窗口): - `ecom_gmv × channel`:付费搜索 -202,650(贡献率 +103.4%,高亮),其余两渠道小幅正增长 - `ecom_gmv × channel × category`:9 个交叉单元,付费搜索三个品类全部高亮 - `fmcg_profit_margin × channel`:三个渠道利润率同步下滑约 4pp - `saas_renewal_rate × segment`:整体 90%→70%,midmarket 贡献 +59.7% 居首 ## 沙箱(T-09) `app/sandbox/`:一次性容器执行探查代码,四层纵深防御。 | 层 | 位置 | 作用 | |---|---|---| | 容器边界 | docker:internal 网络(无外网)+ 非特权用户 + CPU/内存/pids 配额 | 真正的隔离边界 | | 应用侧预检 | `permissions.py` | DDL/DML 关键字拦截 + 引用表白名单;`snapshot.*` 永不放行 | | 执行环境 | `docker/sandbox/runner.py` | 受限内建(无 open/exec/eval)+ import 白名单 | | DB 权限层 | `sandbox_ro` 只读账号 | 越权查询被拒(SQLSTATE 42501 → SBX_003),审计留痕 | 错误分类:`SBX_001` 超时 / `SBX_002` 资源或环境 / `SBX_003` 越权 / `SBX_004` 脚本错误。 执行后端(`config.yaml sandbox.backend`): - `docker`(生产必选):一次性容器; - `local`:镜像不可用时的进程内降级,需 `allow_local_fallback: true`(生产置 false)。 必须说明的一点:CPython 无法提供真正安全的进程内沙箱,熟练攻击者仍可经对象图逃逸。 因此 import 拦截的目标是"防误用与防 LLM 生成代码的越界冲动",真正的安全边界是 **容器 + 只读账号**,而非这里的白名单。 已验证(真实容器):SQL 与 pandas 探查正常返回,`import os` / `open()` 被拒, 越权表与 DDL 在预检阶段即被拦下。 ## 端到端 关键路径 T-01 → T-04 → T-05 → T-08 → T-09 → T-10 已全部打通, `run_pipeline` 六个阶段可完整跑通(电商场景约 2.7s): ``` intent_parse -> decompose -> hypothesize -> sandbox_verify -> stat_test -> conclude 规则/LLM LMDI/差额 3~5 条假设 容器探查 校正+置信度 结论 ``` ## 看板落库与断点恢复(T-07) 此前流水线结果只通过 SSE 推送一次,**刷新即丢失**,看板也无数据可读。 现在每阶段完成后把产出合并进 `attribution_session.board`(JSONB): ``` GET /api/v1/sessions/{id}/board ``` 返回拆解 / 下钻 / 沙箱 / 检验 / 结论五个板块 + `stages`(各阶段状态与耗时) + 复现五要素。假设不走看板存储——它已持久化在 `HYPOTHESIS` 表,接口直接读 **检验后**的状态,避免同一份数据两个源头、两种状态。 `board` 与 `context_snapshot` 的分工:board 记录"这一轮算出了什么", context_snapshot 记录"聊过什么"(多轮上下文继承)。 几个实现要点: - **合并而非覆盖**:追问轮次会重跑整条流水线,只刷新对应板块,不抹掉上一轮结论; - **阶段耗时落 `task_stage_timing`**(第 5 节可观测性 / S8),失败与未实现阶段 同样留痕,便于判断任务断在哪; - **先记时再落库**:except 分支里必须先把 `stage_timings` 写了,否则失败阶段耗时永远是 0; - **结论读检验后的假设**:曾用 hypothesize 阶段的候选清单生成结论,而那是检验**之前** 的快照,导致"已确认假设 N 条"永远不会出现(已修,有测试固化)。 ## 端到端验收(T-17 / AC-09) `scripts/run_acceptance.py` 对照 Spec 第 10 节任务清单,对**两个代表性场景** (电商 GMV 乘法/LMDI、快消利润率 加法/差额法)做全链路验收,覆盖: - T-13 报告:看板 → 七章结构化装配(AC-08 章数与标题与 PRD 6.3 一致)→ MD/Excel 导出 → 派生存量行动项(FR-22); - T-14 简报:周/月订阅(BIZ_005 上限 10)→ 退订 → 手动生成一期简报 → 站内通知; - T-15 配置重载:`/admin/config/reload` 热重载并审计(AC-11); - T-16 可观测:审计日志分页查询 + 任务阶段 P50/P95 聚合; - 看板导出入口:工作台「生成归因报告」一键装配。 运行(需可达的 Postgres 双库,本地沙箱无仓库连接时由 `requires_db` 自动跳过): ```bash uv run python scripts/run_acceptance.py ``` > 纯函数装配 `assemble_seven_chapters` 与导出渲染不依赖 LLM/沙箱,故即使在 LLM 未配置 > 或沙箱不可用的环境下,报告/简报链路仍可端到端跑通(LLM 优先、规则兜底)。 全部模块(T-01~T-17)均已落地并随 CI 回归:拆解守恒(S1)、下钻/统计/沙箱/大盘、 指标字典/事件/报告/简报/用户管理、前端大盘/工作台/字典/日历/报告/简报/管理页。 ## 因子贡献瀑布图(FR-31) 工作台右栏「贡献瀑布图」Tab 消费 `GET /sessions/{id}/board` 的 `decomposition` 板块,渲染 基期 → 各因子增减 → 现期 的守恒瀑布: - 每根柱子由「透明占位层 + 可见段」两层堆叠而成,下降的因子视觉上从上往下长; - 柱顶标注绝对贡献值与贡献率,tooltip 补充拉动方向; - 配色遵循 A 股惯例:拉动上升红、拉动下降绿、期初/期末总量灰; - **守恒校验常驻展示**:各级因子贡献之和与总变动的差(AC-02 要求 ≤0.1%), 超差时红色告警——守恒是这套拆解方法的立论之本,不该藏在测试里。 实测电商 GMV:`202.18万 →(-2.92万 客单价)(-20.53万 转化率)(+3.85万 访客数)→ 182.58万`, 三项之和 -19.60万 与总变动 -19.60万 一致,守恒误差 1.75e-9。 因子展示名来自 `source_mapping.factors[code].label`(T-05 新增该字段), 不再裸露 `cvr` / `aov` 这类代号;未配置 label 时退回代号。 两个前端坑(都已修): 1. **图表容器不能放在 `v-if` 里**:看板数据是异步拉取的,mount 时 `data` 还是 null, 容器根本不存在,`echarts.init` 永远不会执行,数据到了也不画。容器必须常驻。 2. **ECharts 不跟随容器尺寸变化**:容器高度随数据从 0 变为 300px,需显式 `chart.resize()`;且 `watch` 默认在 DOM 更新前触发,必须 `flush: 'post'` 才能读到新尺寸(否则 resize 读到的还是 0)。 ## 动态透视表(FR-33) 工作台右栏「下钻透视表」Tab 消费 `board.drilldown`,基于 Element Plus 表格自研 (ADR-07:需求面窄且与差额染色深度耦合,第三方 pivot 组件体积大、定制难): - **多维层级折叠**:按第一维分组,分组行是可展开的小计; - **列头排序**:点击表头排序,子行跟随分组一起排(否则展开后顺序跳变); - **差额高亮染色**:贡献率超阈值的行标"高亮"并淡红底纹,差额按 A 股惯例涨红跌绿; - **一键导出 CSV**:按**当前排序与折叠状态**导出,所见即所得;附带总计行, 避免导出物脱离总量语境后被误读。 两个容易做错的点: 1. **分组小计的贡献率必须重新算**(小计差额 / 总差额),不能把子行比率相加—— 比率不可加,加了就是错的。 2. **覆盖率提示**:下钻按 |差额| 取前 N 切片,表头显示"已覆盖总变动 +100.0%"。 这个数字小于 100% 时说明看到的是局部,用户该去瀑布图看全量——不提示的话, 一张只覆盖 60% 的表很容易被当成全量事实。 代码中统一以 `TODO(T-xx)` 标注,编号对应 Spec 任务分解清单。 ## 异动大盘(T-06) `GET /api/v1/dashboard/metrics?domain_id=&period_start=&period_end=&refresh=`(API-02) 返回指标卡数组与异常列表。指标口径与归因工作台**完全同源**——共用同一份 `METRIC.source_mapping` 与同一套装配规则,不会出现"大盘一个数、下钻另一个数": | 指标形态 | 取数方式 | |---|---| | 加总型(GMV/访客数/营收) | 窗口内 `SUM(表达式)` | | 比率型(利润率) | 先分别聚合分子分母再相除,绝不做"每日比率再平均"(辛普森悖论) | | 条件计数(续约率) | 分子带 `numerator_filter`,分母不带 | 一次扫描取出整个回溯区间的日序列,环比/同比/迷你趋势/异常检测全部基于同一份序列, 避免多次查询落在不同快照而导致口径漂移(FR-41A)。结果按 60s TTL 缓存(Spec 8.2), `refresh=true` 可强制重算。 **异常标识(FR-24)**分两层: - 期间级:环比变动率跌破 `config.yaml anomaly.mom_drop_threshold` → 卡片标"异常"; - 起始日:日序列上以扫描起点前的 7 天为"正常水位"参考,找滚动均值跌破阈值、 且其后 3 天原值均值同样跌破的日子。 起始日刻意**不做单日环比比较**:日环比天然带噪声(演示库 GMV 日波动 ±12%), 单日跌幅超阈值会频繁误报。前视确认同样是必须的——一次仅 2 天的 20% 下跌会让 7 日均线在阈值下方停留 6 天以上,只看滚动均值会把瞬态扰动误判为持续异动 (`tests/test_dashboard.py` 固化了该场景)。 演示库六个指标刻意做成三红三绿,异常标识在有对照时才说得上话: | 指标 | 环比 | 异动起始 | 造数植入的真实起点 | |---|---|---|---| | 电商 GMV | -9.70% | 2026-09-29 | 2026-09-26(+3 天,滚动均值固有滞后) | | 快消利润率 | -12.80% | 2026-09-26 | 2026-09-26(精确命中) | | SaaS 续约率 | -22.22% | 2026-09-16 | 当期批次起点(低续约率客群自此进入) | | 电商访客数 / 快消营收 / SaaS 活跃用户数 | +2.02% / +2.90% / -2.69% | — | 未植入异动 | **一键发起归因(FR-25 / AC-01)**:`POST /api/v1/dashboard/metrics/{metric_id}/attribution-session`, 预填指标、时间范围与基期类型创建会话,委派 `workspace.create_session` 走完全同一条 创建路径(口径版本冻结、审计留痕),返回 `workspace_url` 供前端跳转。 前端 `views/Dashboard.vue` + `components/MetricCard.vue` + `components/Sparkline.vue`: 筛选条、指标卡(现期值/环比/同比/差额/迷你趋势/异常角标)、异常列表与归因入口。 涨跌配色遵循 A 股惯例(涨红跌绿)。 启动大盘: ```bash uv run python scripts/seed_metrics.py # 指标字典 + 三个健康指标 uv run uvicorn app.main:app --port 8000 cd frontend && npm run dev # http://localhost:5173/dashboard ``` ## What-If 情景推演(T-12) 工作台右栏「What-If」Tab 消费 `GET /sessions/{id}/whatif/meta` + `POST /sessions/{id}/whatif` (API-08,FR-20/21,AC-06:纯代数、无 LLM/沙箱,单次推演亚秒级): - **元信息**:基期值取会话看板 `decomposition.current_total`(即上一次归因算出的当期指标值), 可干预因子与弹性系数读 `METRIC_ELASTICITY`(已在 `seed_metrics` 为电商 GMV / 快消利润率 / SaaS 续约率播种);未做归因(无基期值)时前端提示先跑分析。 - **推演模型**:常弹性 `指标相对变动 ≈ Σ(弹性ᵢ × 因子相对变动ᵢ)`(`app/engine/whatif_calc.simulate_scenario`)。 因子滑块范围 ±20%,落库 `WHATIF_SCENARIO` 并返回预期值 / 预期变动 / 收益区间(±20% 弹性不确定性) 与因子效应分解。 - **多情景对比(FR-21)**:每次推演即保存一个情景,右栏下方列出各情景的调整项、预期值与变动, 便于横向比较"若转化率 +5%""若原材料成本 -10%"等假设性干预。 演示库可直接推演的指标:`ecom_gmv`(访客数/转化率/客单价)、`fmcg_profit_margin` (营收/原材料成本/物流履约/渠道佣金,成本项负弹性)、`saas_renewal_rate`(各客群续约因子)。 健康指标(访客数/营收/活跃用户)未配弹性系数,不支持推演。 行动项跟进(FR-22)绑定报告模块,待 T-13 落地后实现。