unis_crm/docs/后台配置SQL驱动的经营分析方案.md

13 KiB
Raw Blame History

后台配置 SQL 驱动的经营分析方案

1. 目标

本方案满足你明确提出的目标:

  • 统计定义在后台管理配置
  • H5 端直接按配置展示
  • 取数 SQL 也可以在后台管理配置
  • 后续口径变化时,尽量不改前端代码
  • 同时兼顾 PC 端与 H5 / 企业微信端

这套方案的核心思想是:

  • 前端不写死报表
  • 后台管理端维护报表定义
  • 后端读取配置 SQL 执行
  • H5 / PC 统一走配置渲染

2. 结论先说

这个方案是可行的,但建议不要做“完全无限制的任意 SQL 执行”,而要做:

  • 后台可配置 SQL
  • 后端受控执行 SQL
  • 带参数模板
  • 带权限注入
  • 带版本管理
  • 带审核发布

也就是说,不是直接把数据库裸露给后台管理员,而是做一个“可配置 SQL 报表平台”。

3. 适合你的整体架构

建议拆成 4 个部分:

3.1 报表定义后台

给管理员使用,用于配置:

  • 报表名称
  • 适用端
  • 筛选条件
  • 图表类型
  • 指标字段
  • 维度字段
  • SQL 模板
  • 参数说明
  • 发布版本

3.2 报表执行引擎

后端新增一个报表引擎服务,职责是:

  • 读取报表配置
  • 校验参数
  • 替换 SQL 模板变量
  • 自动追加权限条件
  • 执行 SQL
  • 返回统一结果结构

3.3 H5 / PC 动态渲染层

前端不再写死每个图表,而是:

  • 先请求报表页面配置
  • 再请求每个组件的数据
  • 根据配置渲染 KPI、柱状图、折线图、饼图、表格

3.4 配置治理层

用于保证 SQL 配置安全可控:

  • 草稿/已发布版本
  • 审核流
  • 执行日志
  • 回滚版本
  • 性能限制

4. 最推荐的实现模式

你要的是“SQL 可配置”,这里推荐两个级别。

4.1 级别一SQL 模板可配置

这是最推荐的。

后台配置的不是完全自由 SQL而是带占位符的模板 SQL例如

select
  owner_user_id as ownerUserId,
  sum(amount) as actualAmount
from crm_opportunity
where status = 'won'
  and won_at between ${startDate} and ${endDate}
  ${dataScopeClause}
  ${orgFilterClause}
group by owner_user_id
order by actualAmount desc

特点:

  • 可配灵活
  • 后端可控
  • 容易注入权限
  • 易于参数校验

4.2 级别二:完全自由 SQL

不建议默认开放。

如果一定要支持,也建议:

  • 仅超级管理员可用
  • 仅允许 select
  • 禁止 update/delete/insert/drop
  • 禁止多语句
  • 禁止访问敏感表
  • 强制走只读数据源
  • 强制超时和行数限制

5. 业务上如何满足“销售完成业绩”和“区域业绩”

这两个场景很适合做成后台配置化报表。

5.1 销售完成业绩

建议报表结构:

  • KPI
    • 销售目标
    • 实际完成
    • 完成率
    • 同比/环比
  • 图表:
    • 销售排行
    • 趋势图
    • 部门分布
  • 明细:
    • 销售员、目标值、完成值、完成率、区域、趋势

5.2 区域业绩

建议报表结构:

  • KPI
    • 区域目标
    • 区域实际
    • 区域完成率
  • 图表:
    • 区域排名
    • 区域趋势
    • 区域构成
  • 明细:
    • 大区、省区、城市、销售数、目标、实际、完成率

这两类都可以通过后台 SQL 配置实现。

6. 推荐的数据模型

建议新增以下表。

6.1 analytics_report

存报表主定义。

建议字段:

  • id
  • report_code
  • report_name
  • report_category
  • description
  • status
  • terminal_scope
  • default_time_granularity
  • visible
  • created_by
  • updated_by
  • created_at
  • updated_at

说明:

  • terminal_scope 用于区分 pc / h5 / both

6.2 analytics_report_version

存报表版本。

建议字段:

  • id
  • report_id
  • version_no
  • version_status
  • change_log
  • published_by
  • published_at
  • config_json
  • created_at

说明:

  • 一个报表允许多个版本
  • H5 默认读已发布版本

6.3 analytics_widget

存一个报表下的组件定义。

建议字段:

  • id
  • report_version_id
  • widget_code
  • widget_name
  • widget_type
  • title
  • subtitle
  • layout_json
  • props_json
  • data_source_id
  • sort_order
  • visible

6.4 analytics_data_source

存数据源定义,也就是 SQL 配置核心。

建议字段:

  • id
  • source_code
  • source_name
  • source_type
  • dataset_code
  • query_sql
  • count_sql
  • parameter_schema_json
  • result_schema_json
  • timeout_ms
  • max_rows
  • cache_ttl_seconds
  • enabled
  • created_at
  • updated_at

6.5 analytics_filter_def

存筛选器定义。

建议字段:

  • id
  • report_version_id
  • filter_code
  • filter_name
  • filter_type
  • data_type
  • default_value_json
  • options_source_type
  • options_source_config
  • sort_order
  • visible

6.6 analytics_sql_publish_log

存 SQL 发布日志。

建议字段:

  • id
  • data_source_id
  • version_no
  • old_sql
  • new_sql
  • change_summary
  • operator_id
  • created_at

6.7 analytics_query_log

存执行日志。

建议字段:

  • id
  • report_code
  • widget_code
  • data_source_id
  • request_user_id
  • request_params_json
  • final_sql_preview
  • duration_ms
  • row_count
  • success
  • error_message
  • created_at

7. 配置中心怎么设计

后台建议做成 5 个页面。

7.1 报表管理

配置:

  • 报表基本信息
  • 展示端
  • 菜单归属
  • 是否发布

7.2 页面布局管理

配置:

  • KPI 卡片
  • 图表组件
  • 表格组件
  • H5 是否显示
  • PC 是否显示
  • 顺序与显隐

7.3 SQL 数据源管理

配置:

  • SQL 模板
  • 参数定义
  • 字段映射
  • 结果预览
  • 缓存策略
  • 执行限制

7.4 筛选器管理

配置:

  • 时间筛选
  • 区域筛选
  • 销售筛选
  • 部门筛选
  • 自定义枚举

7.5 发布与回滚

配置:

  • 草稿
  • 预览
  • 发布
  • 回滚历史版本

8. SQL 配置方式建议

这是关键设计点。

8.1 SQL 模板结构

建议使用模板 SQL不要直接存“拼好的最终 SQL”。

示例:

select
  region_code as regionCode,
  region_name as regionName,
  sum(actual_amount) as actualAmount,
  sum(target_amount) as targetAmount,
  case when sum(target_amount) = 0 then 0
       else round(sum(actual_amount) / sum(target_amount) * 100, 2)
  end as completionRate
from analytics_sales_performance_fact
where stat_date between ${startDate} and ${endDate}
  ${orgFilterClause}
  ${regionFilterClause}
  ${salesFilterClause}
  ${dataScopeClause}
group by region_code, region_name
order by actualAmount desc
limit ${limit}

8.2 参数定义

每条 SQL 必须配参数定义。

示例:

[
  { "name": "startDate", "type": "date", "required": true },
  { "name": "endDate", "type": "date", "required": true },
  { "name": "orgId", "type": "long", "required": false },
  { "name": "regionCode", "type": "string", "required": false },
  { "name": "salesUserId", "type": "long", "required": false },
  { "name": "limit", "type": "int", "required": false, "defaultValue": 50 }
]

8.3 建议支持的占位符

后端统一支持如下占位符:

  • ${startDate}
  • ${endDate}
  • ${limit}
  • ${offset}
  • ${dataScopeClause}
  • ${orgFilterClause}
  • ${regionFilterClause}
  • ${salesFilterClause}

8.4 动态条件注入方式

例如 regionCode 为空时,不拼条件; 有值时自动生成:

and region_code = :regionCode

不建议把这种逻辑写死在前端。

9. 前端展示怎么实现

虽然 SQL 在后台配置,但前端还是要有统一协议。

9.1 H5 与 PC 共用配置协议

前端请求:

  • 页面定义
  • 筛选器定义
  • Widget 定义
  • Widget 数据

9.2 Widget 类型建议

支持以下组件:

  • kpi
  • line
  • bar
  • stack-bar
  • pie
  • table
  • rank-list

9.3 H5 展示规则

建议在配置里加上:

  • showOnPc
  • showOnH5
  • h5SortOrder
  • pcSortOrder
  • h5ChartType
  • pcChartType

这样同一个报表可以:

  • PC 显示表格 + 图表
  • H5 只显示 KPI + Top10

9.4 H5 页面渲染流程

  1. 获取报表定义
  2. 获取筛选项定义
  3. 渲染页面骨架
  4. 请求组件数据
  5. 渲染图表

10. 后端执行引擎设计

建议新增一个 AnalyticsQueryService

职责:

  • 加载已发布报表版本
  • 解析筛选条件
  • 校验参数类型
  • 生成最终 SQL
  • 注入权限条件
  • 执行查询
  • 做缓存
  • 记录日志

10.1 执行流程

  1. 读取报表配置
  2. 读取组件配置
  3. 读取数据源 SQL 模板
  4. 根据请求参数构造过滤条件
  5. 自动注入数据权限
  6. 生成最终 SQL
  7. 执行查询
  8. 转成统一结果结构

10.2 统一返回结构

建议:

{
  "reportCode": "sales-performance",
  "title": "销售完成业绩",
  "filters": [],
  "widgets": [
    {
      "widgetCode": "sales-rank",
      "widgetType": "bar",
      "title": "销售业绩排名",
      "columns": ["ownerName", "actualAmount"],
      "rows": []
    }
  ]
}

11. 权限与安全控制

这是这个方案能不能上线的关键。

11.1 禁止直接执行危险 SQL

必须限制:

  • 只允许 select
  • 禁止 insert
  • 禁止 update
  • 禁止 delete
  • 禁止 drop
  • 禁止 alter
  • 禁止多语句执行

11.2 必须强制数据权限注入

即使后台配置 SQL也不能信任配置人手动写权限条件。

必须由后端统一追加:

  • 当前租户过滤
  • 当前用户数据范围
  • 组织权限范围

11.3 建议使用只读数据源

报表执行引擎单独使用只读数据库账号。

11.4 超时与数据量限制

每条数据源定义都要支持:

  • 最大执行时长
  • 最大返回行数
  • 最大导出行数

11.5 SQL 审核

建议发布前做 SQL 检查:

  • 关键词校验
  • 表白名单校验
  • 字段白名单校验
  • explain 成本校验

12. 针对“销售完成业绩”和“区域业绩”的配置方式

12.1 销售完成业绩推荐做法

建议先沉淀一个业绩事实层表或视图:

  • analytics_sales_performance_fact

字段建议:

  • stat_date
  • sales_user_id
  • sales_user_name
  • org_id
  • org_name
  • region_code
  • region_name
  • target_amount
  • actual_amount
  • won_amount
  • contract_amount
  • payment_amount
  • adjust_amount

好处:

  • 前端怎么展示都行
  • 后台 SQL 简单很多
  • 口径变更时只改事实层生成逻辑或切换版本

12.2 区域业绩推荐做法

建议同样通过事实层统一:

  • 客户区域
  • 项目区域
  • 销售归属区域

如果口径会改,可以做多个字段:

  • customer_region_code
  • project_region_code
  • owner_region_code

后台 SQL 通过配置选择用哪个字段聚合。

13. 推荐的“SQL 可配置”分层

为了避免后期越来越乱,建议把 SQL 分成两层。

13.1 第一层:事实层 SQL

由研发维护。

职责:

  • 把复杂业务逻辑沉淀成事实表或视图
  • 处理复杂口径、去重、归属、调整项

13.2 第二层:展示层 SQL

由后台管理配置。

职责:

  • 从事实层表/视图做汇总
  • 做 KPI、排行、趋势、区域分组

这是最适合你的方案。

原因:

  • 真正复杂的口径不适合完全交给后台人员写
  • 但展示层统计完全可以后台配置
  • H5 端可以完全动态渲染

14. 如果你坚持“所有 SQL 都后台可配”

也可以做,但我建议加 3 个保护措施。

14.1 只允许访问白名单对象

例如只允许查:

  • analytics_*
  • crm_*
  • work_*
  • 部分 sys_* 维表

14.2 强制 SQL 发布审核

流程建议:

  • 编辑草稿
  • 测试预览
  • 提交审核
  • 审核通过后发布

14.3 强制版本切换

H5 / PC 永远只读“已发布版本”,不读草稿。

15. API 设计建议

15.1 后台管理端

  • GET /api/admin/analytics/reports
  • POST /api/admin/analytics/reports
  • PUT /api/admin/analytics/reports/{id}
  • GET /api/admin/analytics/reports/{id}/versions
  • POST /api/admin/analytics/data-sources
  • PUT /api/admin/analytics/data-sources/{id}
  • POST /api/admin/analytics/data-sources/{id}/preview
  • POST /api/admin/analytics/reports/{id}/publish

15.2 前台 H5 / PC

  • GET /api/analytics/reports/{reportCode}
  • POST /api/analytics/reports/{reportCode}/query

16. 实施步骤建议

第一阶段

目标:

  • 先把基础平台搭起来

内容:

  • 报表定义表
  • 数据源定义表
  • Widget 定义表
  • H5 动态渲染页
  • PC 动态渲染页
  • SQL 安全校验

第二阶段

目标:

  • 上线销售完成业绩、区域业绩

内容:

  • 销售业绩事实表
  • 区域业绩事实表
  • 报表管理页
  • SQL 配置预览
  • 发布与回滚

第三阶段

目标:

  • 真正进入“后台可运营”

内容:

  • 版本对比
  • 审核流
  • 执行监控
  • 性能报警
  • 缓存策略

17. 最终建议

如果你想实现:

  • 后台管理定义
  • H5 自动展示
  • SQL 可配置
  • 后期口径频繁修改

那么我最推荐的是:

  1. 做一个 报表定义 + SQL 数据源 + Widget 配置 的后台管理平台
  2. H5 与 PC 统一走动态渲染
  3. SQL 采用“模板化 + 参数化 + 权限注入 + 发布审核”
  4. 真正复杂的业绩口径优先沉淀为事实层视图或事实表
  5. 展示层 SQL 再交给后台配置

一句话总结:

这个方案完全可以做而且很适合你当前“口径复杂、变化频繁、H5要快速展示”的场景但最佳实践不是裸放任意 SQL而是做受控的后台 SQL 配置平台。