上传源代码版本
This commit is contained in:
473
.trae/documents/metrics_dashboard_improvement_plan.md
Normal file
473
.trae/documents/metrics_dashboard_improvement_plan.md
Normal file
@@ -0,0 +1,473 @@
|
||||
# 指标查询系统改进计划 - 一页式完整汇总
|
||||
|
||||
## 📌 需求分析
|
||||
|
||||
### 用户痛点
|
||||
❌ 需要多个查询页面拼凑指标
|
||||
❌ 用户体验不佳,操作复杂
|
||||
❌ 无法一次性看到所有关键指标
|
||||
|
||||
### 改进目标
|
||||
✅ 用户只需选择一个日期
|
||||
✅ 自动展示该日期的**所有关键指标**
|
||||
✅ 一个仪表盘页面展现完整数据
|
||||
✅ 无需手动计算和拼凑
|
||||
|
||||
---
|
||||
|
||||
## 🎯 实现方案
|
||||
|
||||
### 第一步:改进 metrics-dashboard.html
|
||||
|
||||
#### 方案1: 简化为"一键查询"模式
|
||||
**文件**: metrics-dashboard.html (修改)
|
||||
|
||||
**改进内容**:
|
||||
1. **移除** 5 个独立查询模块
|
||||
2. **保留** 唯一的输入:日期选择
|
||||
3. **新增** "查询汇总"按钮
|
||||
4. **显示** 完整的指标卡片组件
|
||||
|
||||
**展示指标** (20+个):
|
||||
```
|
||||
当天新增换单数、累计要换的总单数、当日应该换单数
|
||||
当日换单完成数、当日STOP数、当日标签推送数
|
||||
当日换单完成率、24小时完成率
|
||||
16点前到仓数、16点后到仓数、16点前完成数、16点后完成数
|
||||
当日失败数、当日成功数、当日未完结失败数
|
||||
当日扫描数、累计积压数
|
||||
等等...
|
||||
```
|
||||
|
||||
**UI 结构**:
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 📊 订单指标日汇总查询系统 │
|
||||
│ 选择日期: [日期选择器] [查询按钮] │
|
||||
└────────────┬────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ 📈 关键指标一览 │
|
||||
│ ├─ 新增/完成/应换 (3个大卡片) │
|
||||
│ ├─ 完成率指标 (2个卡片) │
|
||||
│ └─ 其他指标 (表格 + 卡片) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 第二步:后端 API 优化
|
||||
|
||||
#### 方案: 前端合并或后端聚合
|
||||
|
||||
**选项 A: 前端合并** (简单快速)
|
||||
- 前端一次调用 `getDailySummary` API
|
||||
- API 返回所有 20+ 个指标
|
||||
- 前端直接展示
|
||||
|
||||
**选项 B: 后端聚合** (推荐)
|
||||
- 新增 API: `GET /api/metrics/daily-dashboard`
|
||||
- 后端一次性返回完整汇总
|
||||
- 包含所有必要指标
|
||||
|
||||
### 第三步:JSP 代理增强
|
||||
|
||||
**修改**: metrics-proxy.jsp
|
||||
|
||||
**新增操作**:
|
||||
```
|
||||
action: getDailyDashboard
|
||||
- 参数: date (日期)
|
||||
- 返回: 完整的日汇总数据结构
|
||||
```
|
||||
|
||||
**返回数据示例**:
|
||||
```json
|
||||
{
|
||||
"date": "2026-05-17",
|
||||
"summary": {
|
||||
"dailyNewReplaceCount": 150,
|
||||
"dailyShouldReplaceCount": 150,
|
||||
"dailySuccessCount": 145,
|
||||
"dailyCompletionRate": "96.67%",
|
||||
"rate24Hour": "96.67%"
|
||||
},
|
||||
"breakdown": {
|
||||
"beforeNoon": {
|
||||
"arrived": 80,
|
||||
"passed": 78,
|
||||
"rate": "97.50%"
|
||||
},
|
||||
"afternoon": {
|
||||
"arrived": 70,
|
||||
"passed": 67,
|
||||
"rate": "95.71%"
|
||||
}
|
||||
},
|
||||
"details": {
|
||||
"cumulativeTotal": 500,
|
||||
"dailyStop": 25,
|
||||
"dailyLabelPush": 160,
|
||||
"dailyScanCount": 200,
|
||||
"dailyFailure": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 仪表盘设计
|
||||
|
||||
### 顶部信息区
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 📊 2026-05-17 订单处理指标汇总 │
|
||||
│ 刷新时间: 14:30:45 (UTC-5) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 指标展示区 (四层级)
|
||||
|
||||
#### 一级: 核心指标 (3个大卡片)
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 当天新增 │ │ 应该换单数 │ │ 已完成 │
|
||||
│ 150 │ │ 150 │ │ 145 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
#### 二级: 完成率 (2个卡片)
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ 当日完成率 │ │ 24小时完成率 │
|
||||
│ 96.67% │ │ 96.67% │
|
||||
└──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
#### 三级: 分时段统计 (表格)
|
||||
```
|
||||
┌────────┬───────┬───────┬────────┐
|
||||
│ 时段 │ 到仓数 │ 完成数 │ 完成率 │
|
||||
├────────┼───────┼───────┼────────┤
|
||||
│ 16点前 │ 80 │ 78 │ 97.50% │
|
||||
│ 16点后 │ 70 │ 67 │ 95.71% │
|
||||
└────────┴───────┴───────┴────────┘
|
||||
```
|
||||
|
||||
#### 四级: 详细指标 (信息卡片组)
|
||||
```
|
||||
当日STOP数: 25
|
||||
当日标签推送: 160
|
||||
当日扫描数: 200
|
||||
当日失败数: 5
|
||||
累计积压数: 500
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术实现细节
|
||||
|
||||
### 第一步: 修改 metrics-dashboard.html
|
||||
|
||||
**删除的代码**:
|
||||
- 移除 5 个独立查询模块的 HTML 结构
|
||||
- 移除对应的 AJAX 查询函数
|
||||
|
||||
**新增的代码**:
|
||||
1. **单一日期选择器**
|
||||
2. **"查询汇总"按钮**
|
||||
3. **统一的展示容器**
|
||||
4. **完整的指标卡片组件**
|
||||
|
||||
**新增的 JavaScript** (使用 JSONP 方式,对齐 batch_query.html):
|
||||
```javascript
|
||||
// 定义回调函数容器
|
||||
var dashboardCallbacks = {};
|
||||
|
||||
// 单一查询函数(使用 JSONP)
|
||||
function queryDailyDashboard() {
|
||||
const date = document.getElementById('dashboardDate').value;
|
||||
if (!date) {
|
||||
showError('请选择日期');
|
||||
return;
|
||||
}
|
||||
|
||||
// 生成唯一的回调函数名称
|
||||
const callbackName = 'dashboardCallback_' + new Date().getTime();
|
||||
|
||||
// 定义回调处理函数
|
||||
window[callbackName] = function(response) {
|
||||
handleDashboardResponse(response);
|
||||
// 清理
|
||||
delete window[callbackName];
|
||||
};
|
||||
|
||||
// 构建 JSONP 请求 URL
|
||||
const url = `metrics-proxy.jsp?action=getDailyDashboard&date=${date}&callback=${callbackName}&env=${getEnvironment()}`;
|
||||
|
||||
// 使用 JSONP 请求
|
||||
jsonpRequest(url, callbackName);
|
||||
}
|
||||
|
||||
// JSONP 请求函数(参考 batch_query.html)
|
||||
function jsonpRequest(url, callbackName) {
|
||||
const script = document.createElement('script');
|
||||
script.src = url;
|
||||
script.type = 'text/javascript';
|
||||
|
||||
// 超时处理
|
||||
const timeout = setTimeout(() => {
|
||||
script.remove();
|
||||
delete window[callbackName];
|
||||
showError('请求超时,请重试');
|
||||
}, 10000);
|
||||
|
||||
script.onload = () => {
|
||||
clearTimeout(timeout);
|
||||
script.remove();
|
||||
};
|
||||
|
||||
script.onerror = () => {
|
||||
clearTimeout(timeout);
|
||||
script.remove();
|
||||
delete window[callbackName];
|
||||
showError('请求失败,请检查网络连接');
|
||||
};
|
||||
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
// 处理响应数据
|
||||
function handleDashboardResponse(response) {
|
||||
if (response.success) {
|
||||
displayDashboard(response.data);
|
||||
} else {
|
||||
showError(response.error || '查询失败');
|
||||
}
|
||||
}
|
||||
|
||||
// 展示完整指标仪表盘
|
||||
function displayDashboard(data) {
|
||||
// 构建完整的指标展示 HTML
|
||||
// ... 具体实现
|
||||
}
|
||||
```
|
||||
|
||||
### 第二步: 修改 metrics-proxy.jsp
|
||||
|
||||
**获取 callback 参数**:
|
||||
```jsp
|
||||
String callback = request.getParameter("callback");
|
||||
String format = request.getParameter("format");
|
||||
if (format == null) {
|
||||
format = (callback != null && !callback.isEmpty()) ? "jsonp" : "json";
|
||||
}
|
||||
```
|
||||
|
||||
**新增操作**:
|
||||
```jsp
|
||||
else if ("getDailyDashboard".equals(action)) {
|
||||
// 调用新的聚合 API
|
||||
apiUrl = baseUrl + "/api/metrics/daily-dashboard?date=" + URLEncoder.encode(date, "UTF-8");
|
||||
}
|
||||
```
|
||||
|
||||
**返回格式处理** (响应使用 JSONP 包装):
|
||||
```jsp
|
||||
// 如果是 JSONP 格式,使用 callback 包装
|
||||
if ("jsonp".equals(format) && callback != null && !callback.isEmpty()) {
|
||||
// 验证 callback 名称安全
|
||||
if (callback.matches("^[a-zA-Z_$][a-zA-Z0-9_$]*$")) {
|
||||
out.print(callback + "(" + resultJson.toString() + ");");
|
||||
} else {
|
||||
out.print("jsonp_error({\"error\": \"Invalid callback name\"});");
|
||||
}
|
||||
} else {
|
||||
out.print(resultJson.toString());
|
||||
}
|
||||
```
|
||||
|
||||
### 第三步: 后端 API (可选但推荐)
|
||||
|
||||
**新增 Controller 方法**:
|
||||
```csharp
|
||||
[HttpGet("daily-dashboard")]
|
||||
public async Task<IActionResult> GetDailyDashboard([FromQuery] string date)
|
||||
{
|
||||
// 调用 GetDailySummaryAsync
|
||||
// 返回格式化的完整汇总
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 指标优先级
|
||||
|
||||
### 必显示 (一级重要)
|
||||
- ✅ 当天新增换单数
|
||||
- ✅ 当天应该换单数
|
||||
- ✅ 当日换单完成数
|
||||
- ✅ 当日完成率
|
||||
- ✅ 24小时完成率
|
||||
|
||||
### 次要显示 (二级重要)
|
||||
- 16点前到仓数
|
||||
- 16点前完成数
|
||||
- 16点后到仓数
|
||||
- 16点后完成数
|
||||
|
||||
### 详情显示 (三级信息)
|
||||
- 当日STOP数
|
||||
- 当日标签推送数
|
||||
- 当日扫描数
|
||||
- 当日失败数
|
||||
- 累计积压数
|
||||
|
||||
---
|
||||
|
||||
## 🎨 UI 改进
|
||||
|
||||
### 设计原则
|
||||
1. **一屏即得** - 不需要滚动看所有指标
|
||||
2. **视觉优先级** - 重要数据更大更突出
|
||||
3. **颜色编码** - 好/一般/差用不同颜色
|
||||
4. **实时刷新** - 支持手动刷新最新数据
|
||||
|
||||
### 色彩编码
|
||||
- 🟢 绿色: 完成率 >= 95%
|
||||
- 🟡 黄色: 完成率 85-95%
|
||||
- 🔴 红色: 完成率 < 85%
|
||||
|
||||
---
|
||||
|
||||
## 📝 实现步骤表
|
||||
|
||||
| 步骤 | 操作 | 文件 | 优先级 |
|
||||
|------|------|------|--------|
|
||||
| 1 | 重设计仪表盘布局 | metrics-dashboard.html | 高 |
|
||||
| 2 | 新增日期+查询UI | metrics-dashboard.html | 高 |
|
||||
| 3 | 新增汇总展示容器 | metrics-dashboard.html | 高 |
|
||||
| 4 | 编写查询函数 | metrics-dashboard.html | 高 |
|
||||
| 5 | 更新 JSP 代理 | metrics-proxy.jsp | 中 |
|
||||
| 6 | 新增后端 API (可选) | MetricsController.cs | 低 |
|
||||
|
||||
---
|
||||
|
||||
## ✅ 验收标准
|
||||
|
||||
- ✅ 用户选择日期后,一次调用获取所有指标
|
||||
- ✅ 所有 20+ 个指标在一个仪表盘展示
|
||||
- ✅ 无需多个查询和手动计算
|
||||
- ✅ 指标分层展示,易于查看
|
||||
- ✅ 支持日期范围快速选择 (今天、昨天、本周等)
|
||||
- ✅ 支持数据刷新按钮
|
||||
|
||||
---
|
||||
|
||||
## 📊 预期效果
|
||||
|
||||
### 改进前
|
||||
```
|
||||
用户: 我想看 2026-05-17 的指标
|
||||
流程:
|
||||
1. 选择日期查标签率
|
||||
2. 再查订单评估
|
||||
3. 再查每日汇总
|
||||
4. 手动拼凑计算
|
||||
时间: 5 分钟+
|
||||
```
|
||||
|
||||
### 改进后
|
||||
```
|
||||
用户: 我想看 2026-05-17 的指标
|
||||
流程:
|
||||
1. 选择日期
|
||||
2. 点击查询
|
||||
时间: 2-3 秒
|
||||
结果: 完整汇总一屏显示 ✅
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 整体方案架构
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────┐
|
||||
│ 改进版仪表盘 (新) │
|
||||
│ ├─ 日期选择器 (单一入口) │
|
||||
│ ├─ 查询汇总按钮 │
|
||||
│ └─ 完整指标展示 │
|
||||
│ ├─ 核心指标卡片 (3个) │
|
||||
│ ├─ 完成率卡片 (2个) │
|
||||
│ ├─ 分时段统计 (表格) │
|
||||
│ └─ 详细指标卡片 (4个) │
|
||||
└──────────────────────────────────────┘
|
||||
↓ 调用
|
||||
┌──────────────────────────────────────┐
|
||||
│ metrics-proxy.jsp (改进版) │
|
||||
│ ├─ 新增 getDailyDashboard 操作 │
|
||||
│ └─ 返回聚合后的完整数据 │
|
||||
└──────────────────────────────────────┘
|
||||
↓ 调用
|
||||
┌──────────────────────────────────────┐
|
||||
│ MetricsController (可选) │
|
||||
│ └─ 新增 /daily-dashboard API │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 核心改进点
|
||||
|
||||
1. **入口简化** - 从 5 个查询模块 → 1 个日期选择
|
||||
2. **数据聚合** - 从多次调用 → 1 次 API 调用
|
||||
3. **展示完整** - 从分散显示 → 一屏汇总
|
||||
4. **用户友好** - 从复杂操作 → 一键查询
|
||||
5. **JSONP 支持** - 采用与 batch_query.html 相同的 JSONP 方式调用
|
||||
|
||||
---
|
||||
|
||||
## 🔗 JSONP 调用示例
|
||||
|
||||
### 请求 URL
|
||||
```
|
||||
metrics-proxy.jsp?action=getDailyDashboard&date=2026-05-17&callback=dashboardCallback_1234567890&env=test
|
||||
```
|
||||
|
||||
### 响应格式
|
||||
```javascript
|
||||
dashboardCallback_1234567890({
|
||||
"success": true,
|
||||
"data": {
|
||||
"date": "2026-05-17",
|
||||
"summary": {
|
||||
"dailyNewReplaceCount": 150,
|
||||
"dailyShouldReplaceCount": 150,
|
||||
"dailySuccessCount": 145,
|
||||
"dailyCompletionRate": "96.67%",
|
||||
"rate24Hour": "96.67%"
|
||||
},
|
||||
"breakdown": {
|
||||
"beforeNoon": { "arrived": 80, "passed": 78, "rate": "97.50%" },
|
||||
"afternoon": { "arrived": 70, "passed": 67, "rate": "95.71%" }
|
||||
},
|
||||
"details": {
|
||||
"cumulativeTotal": 500,
|
||||
"dailyStop": 25,
|
||||
"dailyLabelPush": 160,
|
||||
"dailyScanCount": 200,
|
||||
"dailyFailure": 5
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 前端处理
|
||||
```javascript
|
||||
// 自动执行回调,接收数据
|
||||
function handleDashboardResponse(response) {
|
||||
if (response.success) {
|
||||
displayDashboard(response.data);
|
||||
} else {
|
||||
showError(response.error || '查询失败');
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user