适用版本:EspoCRM 9.2.2+
别小看”显示个数字”,做错了会变成:不准、卡、泄露权限范围。
TL;DR
- 计数必须来自后端聚合,而不是前端猜测
- API 必须走 ACL/过滤条件,计数和可见数据保持一致
- 能扩展默认看板就别重写;重写要把代价锁进模块边界
- 列独立滚动/分页要做到”列内状态独立”
- 多币种宁可分组展示,也不要混算误导用户
1. 轻量增强 —— 阶段计数
1.1 场景:看板要”阶段一眼看懂”
看板的核心诉求很朴素:
- 每个阶段有多少条记录?
- 拖拽卡片后,数字要跟着变
这看似小功能,但最容易被写成”堆前端临时逻辑”:页面上数 DOM、或者从列表数据里猜数量——最后一定不准。
1.2 目标:准确、实时、权限正确
- 准确:基于数据库聚合
- 实时:拖拽后刷新计数
- 权限正确:用户只能看到自己有权限看到的记录计数
1.3 数据流:前端视图扩展 + 后端统计 API
sequenceDiagram participant UI as Kanban View participant API as Entity API participant DB as Database UI->>API: GET /api/v1//kanbanStageCount API->>DB: SELECT stage, COUNT(*) ... WHERE ACL条件 DB-->>API: aggregated counts API-->>UI: {stage: count} UI->>UI: render badge near column title UI->>UI: onDragDrop() UI->>API: refresh counts API-->>UI: updated counts
1.4 后端:为什么一定要聚合查询
你想要的是”真实数据”的计数,而不是”当前前端加载到内存里的一页数据”。
聚合查询的本质是:
- 只返回计数,不返回详情,响应体小
- 可加索引字段(如 stage)提升性能
- 可复用 ACL/过滤条件,保证权限一致
SQL 思路(示意):
1 | SELECT stage, COUNT(id) AS cnt |
PHP 代码骨架(公开版、严格 ACL):
1 |
|
1.5 前端:只做展示与刷新,不做”算数”
前端的职责应该非常克制:
- 请求计数
- 在阶段标题旁渲染徽章(badge)
- 在拖拽成功后触发刷新
- 当 API 失败时做回退(例如隐藏徽章或显示
--)
失败回退(统一英文提示):
1 | try { |
1.6 性能与一致性
常见错误:每个阶段单独请求一次(N 个阶段 = N 次 API)
更稳妥的做法:一次 API 返回全部阶段的计数(1 次请求)
2. 深度定制 —— 可控重写
2.1 什么时候应该”重定制”,什么时候”扩展一下就行”
先说结论:能扩展默认看板就别重写。
重写意味着你要长期对抗:
- EspoCRM 前端内部结构变化
- 过滤/排序/权限/拖拽的细节
- 多浏览器兼容与样式适配
但有些需求默认看板确实做不到:
- 每列独立滚动(避免整页超长)
- 每列独立分页(列内”Show More”懒加载)
- 每列统计区(汇总数值/加权数值/比例)
- 多币种显示避免误读
2.2 目标:功能增强不破坏原有体验
你重定制的底线应该是:
- 不修改核心文件(可升级)
- 不破坏默认过滤/排序/分组能力
- 不破坏 ACL 行为(权限永远正确)
- 统计逻辑可复用、可测试、可观测(日志英文)
2.3 推荐架构:后端统计服务 + 前端自定义视图
flowchart LR
subgraph Backend[Backend - custom module]
S[KanbanStatisticsService]
C[Entity Controller]
R[routes.json]
end
subgraph Frontend[Frontend - custom module]
V[Custom Kanban View]
T[Handlebars Template]
CSS[Styles]
end
V -->|AJAX| C
C --> S
S -->|aggregate| DB[(Database)]
V --> T
V --> CSS
2.4 关键实现点
2.4.1 列独立滚动
1 | .column-container { |
2.4.2 列级分页(Show More)
每列维护自己的 offset/limit:
1 | // 每列独立状态 |
2.4.3 统计区:汇总数值与加权数值
推荐后端统一计算(避免前端重复、避免精度与货币问题):
1 | { |
2.4.4 多币种显示:避免用户误读
最常见事故:
列底部写了 USD,但数据里混入了 HKD,用户以为总额都是 USD。
策略:
- 展示时明确币种
- 统计时按币种分组或统一换算(取决于规则定义)
- 没有明确换算规则就不要混算(宁可多行展示)
2.5 模块边界:把重写代价锁住
1 | custom/Espo/Modules/MyKanban/ |
关键:所有改动都在模块内,不触碰 application/ 目录。
本篇总结
- 阶段计数:后端聚合 + ACL 复用,前端只渲染刷新
- 深度定制:必须重写时,用模块边界锁住代价
- 统一后端计算统计,前端不做”算数”
- 多币种宁可分组展示,也不要混算误导用户