Insight Dashboard · Architecture Evolution
IKB · 26.08.10 · 01 / 26
ARCHITECTURE EVOLUTION · DASHBOARD PLATFORM

从"一个接口扛所有"
数据驱动的可视化平台

Insight Dashboard项目架构升级分享 · 从传统系统 到 可定制化平台
EIZ Engineering · 2026
→ swipe / arrow keys
OVERVIEW · 目录
02 / 26
ROADMAP · OVERVIEW

六个章节,三十分钟

01

现状痛点

传统模式的性能瓶颈与架构问题

02

目标原则

按需加载 · 数据源无关 · 配置驱动

03

核心架构

Provider 架构与配置模型

04

关键改进

抽象 · 按需 · 配置 · 多数据源

05

效果对比

开发效率 · 代码结构 · 对标业界

06

演进路线

缓存 · 实时推送 · 客户自定义

现状 · ARCHITECTURE
03 / 26
CHAPTER 01 · 传统模式

一个接口返回所有数据

前端请求一个接口,后端一次性查完所有数据,拼成巨大 JSON 返回。

lofko /v3/storefront/overview
lofko /v2/storefront/getNotificationAndDashboard
痛点 · PAIN POINTS
04 / 26
LOFKO · 性能瓶颈

每次打开页面
都是一次全表扫描

01 / CACHE

无缓存机制

同一数据 10 秒内被查 100 次

02 / PAYLOAD

全量返回

只需订单汇总,但返回所有模块

03 / SCAN

大表扫描

查询时间随数据量线性上升

04 / PRESSURE

数据库压力

MySQL CPU 经常飙高

Datadog APM: GET /v3/storefront/overview 耗时 1.07s
痛点 · CODE STRUCTURE
05 / 26

加一个图表,
改动大,还有局限性

意大利面架构(Spaghetti Architecture)——模块之间没有清晰边界,业务逻辑、SQL 查询、数据拼装散落在多个文件里,互相硬编码依赖,改一处牵一串,像纠缠在一起的面条。

routes/web.php
Route::get('/dashboard/overview', DashboardController@index);
DashboardController.php 500+ 行
public function index() {
$orders = DB::select('SELECT ...'); // 100+ 行 SQL
$shipments = DB::select('SELECT ...');
$warehouse = DB::select('SELECT ...');
// ... 拼装所有数据返回
}
DashboardService.php
// SQL 写死在 Service 里,无法复用
public function getOrderSummary() → DB::select('...');
routes → controller service DB::select 改一处牵一串
痛点 · CUSTOMIZATION
06 / 26
LOFKO · FLEXIBILITY GAP

所有人都看同一套

Before

无法自定义

客户 A 只关心订单 → 无法隐藏其他模块

客户 B 想看 30 天 → 全局固定 7 天

客户 C 想加图表 → 需开发介入发版

After

配置驱动

Widget 配置化 → 可按需展示/隐藏

参数白名单 → 时间范围可配置

Provider 抽象 → 新增图表不改旧代码

目标 · OUR GOAL
07 / 26
INDUSTRY BENCHMARK

参照业界标杆
设计我们的目标

按需加载
Widget 级别按需请求,不再一次查完
数据源无关
前端只消费 columns + rows
配置驱动
Dashboard 结构数据库配置,不硬编码
可自定义
每个客户看到自己想看的
AWS CloudWatch Dashboard CloudWatch · Dashboard
AWS CloudWatch Service Map CloudWatch · Service Map
AWS CloudWatch Logs CloudWatch · Logs
Grafana Dashboard Grafana · Dashboard
原则 · DESIGN PRINCIPLES
08 / 26
CORE PRINCIPLES · 设计原则

三条设计原则

01

数据源抽象

不管底层是 MySQL、OpenSearch 还是 MongoDB,前端永远消费 columns + rows。Provider 接口统一,数据源切换对前端零感知。

02

按需加载

页面结构和数据分开请求。用户看到哪个图表,才查哪个图表的数据。首屏只加载页面结构,毫秒级返回。

03

配置驱动

Dashboard 结构通过数据库配置,不硬编码。新增图表不需要改代码,插两条配置即可上线。

架构 · ARCHITECTURE
09 / 26
CHAPTER 03 · 核心架构

New
架构全景

Provider 屏蔽数据源差异,前端只消费统一结构。

OpenSearch / MySQL / MongoDB Controller → Service → Provider Provider Registry
前端 Vue/React Nginx → PHP-FPM PostgreSQL 配置
架构 · CONFIG MODEL
10 / 26
CONFIG-DRIVEN

Dashboard
= 配置,
不是代码

01

Dashboard → Section → Widget

页面结构完全由数据库配置驱动

02

Widget.result_key → DashboardResult

组件通过 result_key 关联数据结果定义

03

provider_key → Provider.execute()

Result 通过 provider_key 找到代码中的 Provider

架构 · PROVIDER CATALOG
11 / 26
DASHBOARDPROVIDER · INTERFACE

Provider
数据源的统一入口

OPENSEARCH
订单 3 + 发货 4
MYSQL
退货 1 + 库存 5
MONGODB
物流 3
UNIFIED
{ type, columns, rows }
MySQL · ReturnsDashboardRepository.php
SELECT
$dateCase AS date,
$tagCase AS tag_name,
COUNT(*) AS return_job_total
FROM return_jobs
WHERE account_id IN (...)
AND created_at BETWEEN $startUtc AND $endUtc
GROUP BY date, tag_name
OpenSearch · OrdersDashboardRepository.php
{ "query": { "bool": { "filter": [
{ "term": { "account_id": 3331 }},
{ "terms": { "orderStatus": ["completed", ...] }},
{ "range": { "createdAt": { "gte": "..." }}},
]}}, "aggs": { "by_day": { ... } }}
MongoDB · TrackingDeliveryMedianRepository.php
[ { "$match": {
"account_id": { "$in": [...] },
"trackingCode": 6,
"created_at": { "$gte": ..., "$lt": ... }
}}, { "$group": { "_id": "$account_id", ... }} ]
架构 · ON-DEMAND
12 / 26
LOADING STRATEGY

用户看到什么,才查什么

Before

一次性查完

页面加载 → 查完所有数据 → 返回巨大 JSON

总耗时 = 最慢查询 × 1.5

After

按需加载

页面加载 → 只返回结构(毫秒级)

滚动到区域 → 才请求 Provider 数据

首屏 = 页面结构查询时间

改进 · KEY IMPROVEMENTS
13 / 26
CHAPTER 04 · 关键改进

我们做了什么

01 / ABSTRACT

数据源抽象

Provider 接口统一,底层对前端透明

02 / LAZY

按需加载

页面结构与数据分离,Widget 级别按需请求

03 / CONFIG

配置驱动

Dashboard / Section / Widget 全部数据库配置

04 / MULTI

多数据源

同一页面混合 MySQL、OpenSearch、MongoDB

canva /dashboard/{code} API 响应
改进 · ENGINEERING
14 / 26
INFRASTRUCTURE · CAPABILITY

工程化能力补齐

CHAIN
请求链路
Middleware → Controller
TRACE
可观测性
Datadog / SkyWalking
DOCKER
容器化
K8s Kustomize 三环境
DEPLOY
一键部署
make deploy ENV=prod
TEST
测试覆盖
PHPUnit 全链路
RESPONSE
统一响应
{ code, requestId, data }
Datadog APM: GET /dashboard/{code} 全链路追踪
对比 · DEV EFFICIENCY
15 / 26
CHAPTER 05 · 效果对比

新增一个图表
要多久?

Before

2-3 天

Controller 加查询逻辑

SQL 写死,和现有代码耦合

测试覆盖整个接口

改 4-5 个文件,风险高

After

0.5 天

新建 Provider 类

在 Registry 注册

数据库插 2 条配置

加 1 个文件 + 2 条配置

对比 · CODE STRUCTURE
16 / 26
ARCHITECTURE · BEFORE vs AFTER

从意大利面到乐高积木

Before · 意大利面
📁 app/
📁 Http/Controllers/
📄 DashboardController.php ← 500+ 行
📄 AuthController.php
📄 OrderController.php
📁 Models/
📄 Dashboard.php
📁 Services/
📄 DashboardService.php ← SQL 写死
📁 routes/
📄 web.php ← 路由耦合
SQL 写死 无分层 改一处牵一串
After · 乐高积木
📁 app/Dashboard/
📁 Controllers/
📄 DashboardController.php
📁 Providers/
📄 OrdersSummaryProvider.php
📄 ShipmentsSummaryProvider.php
📄 WarehouseStockProvider.php
📄 ...16 个独立 Provider
📁 Repositories/
📄 MySQL/ · OpenSearch/ · Mongo/
📁 Services/
📄 DashboardResultService.php
📁 Registries/
📄 ProviderRegistry.php
独立互不影响 清晰分层 加 1 个文件即可
成果 · CURRENT RESULTS
17 / 26
CHAPTER 05 · 阶段成果

当前阶段成果

3种数据源
16个 Provider
5大业务领域
4种 Widget 类型
订单 3 Provider 发货 4 Provider 退货 1 Provider 库存 5 Provider 物流 3 Provider Provider Layer metadata() + execute() → { type, columns, rows } { type, columns, rows } MySQL 退货 · 库存 OpenSearch 订单 · 发货 MongoDB 物流 tracking PostgreSQL · Dashboard 配置层
路线图 · ROADMAP
18 / 26

接下来 —
演进路线图

— 从已完成到未来愿景
路线图 · FOUR PHASES
19 / 26
ROADMAP · EVOLUTION

四阶段演进路线图

Phase 1 已完成
16P
数据源抽象 · Provider 架构
按需加载 · 配置驱动
容器化 · 测试覆盖
2 Phase 2 近期
4
缓存层接入
前端懒加载
更多 Widget · 批量接口
3 Phase 3 中期
5
WebSocket 实时推送
数据变更刷新 · 多租户隔离
告警规则 · 历史对比
4 Phase 4 远期
5
客户自定义 Dashboard
拖拽式管理后台 · 租户配置
AI 辅助 · 自然语言查询
← 当前位置 未来愿景 →
Phase 2 · NEAR TERM
20 / 26
PHASE 2 · 近期优化

让页面更快

01 / CACHE

缓存层接入

refresh_policy 已就位,接入 Redis

02 / LAZY

前端懒加载

Intersection Observer 按需触发

03 / WIDGET

更多 Widget

折线图 · 饼图 · 热力图 · 趋势卡片

04 / BATCH

批量接口

一次请求多个 Result

CACHE App Redis Cache MySQL 命中缓存 → 跳过 DB
LAZY LOAD 图表 A ✓ 图表 B ✓ viewport 图表 C → 加载中 未进入视口
WIDGETS 柱状图 折线图 饼图 热力图 新增 4 种可视化组件
BATCH Before req1 req2 req3 3 次往返 After batch [r1,r2,r3] 1 次往返 3x faster
Phase 3 · REALTIME
21 / 26
PHASE 3 · 中期能力

数据变了
页面自动更新

01数据源变更(binlog / 索引 / 计算)
02后端感知并处理
03WebSocket + Redis Pub/Sub 推送
04前端 Diff 更新,无全量重渲染
变更 感知 推送 更新 LOOP REALTIME
Phase 4 · CUSTOMER
22 / 26
PHASE 4 · 远期愿景

每个客户
看到自己想看的

拖拽式编辑
Widget 自由拖拽排列,所见即所得
租户隔离
每个客户独立配置,数据互不可见
权限体系
角色控制可见模块和数据范围
AI 辅助
自然语言查询,智能推荐图表
Dashboard Builder 保存 预览
组件库
📊 柱状图
📈 折线图
🔢 KPI 卡片
📋 数据表格
订单汇总
发货趋势
库存状态
+ 拖入新组件
客户 A
订单 + 发货
客户 B
库存 + 物流
客户 C
全量 + 自定义
对标 · BENCHMARK
23 / 26
INDUSTRY COMPARISON

对标业界:我们走到了哪一步?

能力
CloudWatch
Grafana
传统
当前
数据源抽象
按需加载
配置驱动
多数据源混合
实时推送
P3
缓存机制
P2
客户自定义
P4
CORE CAPABILITIES SHIPPED 4 项核心能力已对标 CloudWatch / Grafana
总结 · MANIFESTO
24 / 26
TRANSFORMATION · 总结

从意大利面
到乐高积木

Before 500+ 行 Controller · SQL 写死 改一处牵一串 EVOLVE After 订单 发货 退货 库存 Provider × 16 { columns, rows } 独立互不影响 · 配置驱动 加 1 个文件即可上线
每个 Provider 是一块积木,可以自由组合
25 / 26
CLOSING
MANIFESTO

数据驱动,
配置先行

Data-Driven, Config-First. 每一次架构决策都服务于可扩展性与可维护性。
EIZ Engineering · Insight Team
26.08.10
TAKEAWAYS
03 RULES
01

架构解耦

Provider 屏蔽数据源差异,前端只消费统一结构。

02

按需高效

页面结构与数据分离,Widget 级别按需请求。

03

未来可期

实时推送、客户自定义、AI 辅助——路线清晰,节奏可控。

→ 完 · END OF PRESENTATION
Q&A · Insight Dashboard
26 / 26

Q&A

感谢聆听 · 欢迎提问
Insight Dashboard · 2026
[必填] 章节英文 / Section En

[必填] 中文主标题
(≤ 12 字,可在某字加 italic 微强调)

[必填] 一段 1-2 行的副标 / 引子,定调全场.
[选填] 作者 · 日期 · 出处
→ swipe / arrow keys