# 管理驾驶舱(PSI 数据分析大屏)优化
## 涉及页面
- 管理驾驶舱 / PSI 数据分析大屏
## API
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /home/salesPurchaseStorageProductCount | 销售-采购-储存统计(新增日期筛选) |
| GET | /home/productCategoryDistribution | 产品大类分布(修复数据) |
### 1. 销售-采购-储存统计接口
**请求参数(新增):**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| startDate | String | 否 | 开始日期(yyyy-MM-dd) |
| endDate | String | 否 | 结束日期(yyyy-MM-dd) |
不传日期参数时默认统计当前月 vs 上月。
**响应格式变化:**
- 第一个指标名称从 `"销售产品数"` 改为 `"销售订单数"`
- 数值统计口径从"销售产品记录数"改为"销售订单数(sales_ledger 表记录数)"
```json
{
"code": 200,
"data": [
{ "name": "销售订单数", "value": "156", "rate": "12.50" },
{ "name": "采购产品数", "value": "89", "rate": "-5.30" },
{ "name": "储存产品数", "value": "234", "rate": "8.20" }
]
}
```
### 2. 产品大类分布接口
修复了小类 value/rate 数据为 0 的问题,现在返回实际的采购数据。
**响应格式:**
```json
{
"code": 200,
"data": {
"items": [
{
"name": "原材料",
"value": "45",
"rate": "40.50",
"children": [
{ "name": "钢材", "value": "20", "rate": "44.44", "children": [] },
{ "name": "塑料", "value": "15", "rate": "33.33", "children": [] },
{ "name": "电子元件", "value": "10", "rate": "22.22", "children": [] }
]
}
]
}
}
```
## 前端修改点
### 1. 顶部指标修改 - "销售产品数" → "销售订单数"
```html
销售订单数
{{ salesOrderCount.value }}
环比 {{ salesOrderCount.rate }}%
```
### 2. 日期范围筛选控件
在页面左上角新增日期范围下拉筛选。
```html
```
### 3. data 数据
```js
data() {
return {
dateRange: [],
salesOrderCount: { value: 0, rate: 0 },
purchaseProductCount: { value: 0, rate: 0 },
storageProductCount: { value: 0, rate: 0 },
productCategoryData: [],
}
}
```
### 4. 方法
```js
async loadSalesPurchaseStorageCount() {
const params = {};
if (this.dateRange && this.dateRange.length === 2) {
params.startDate = this.dateRange[0];
params.endDate = this.dateRange[1];
}
const res = await this.$http.get('/home/salesPurchaseStorageProductCount', { params });
const data = res.data || [];
this.salesOrderCount = this.extractStatData(data[0]);
this.purchaseProductCount = this.extractStatData(data[1]);
this.storageProductCount = this.extractStatData(data[2]);
},
extractStatData(item) {
return item ? {
value: parseInt(item.value) || 0,
rate: parseFloat(item.rate) || 0,
} : { value: 0, rate: 0 };
},
handleDateChange(val) {
this.loadSalesPurchaseStorageCount();
},
async loadProductCategoryDistribution() {
const res = await this.$http.get('/home/productCategoryDistribution');
this.productCategoryData = res.data.items || [];
this.renderCategoryChart();
},
renderCategoryChart() {
const chart = this.$echarts.init(this.$refs.categoryChart);
const seriesData = [];
const legendData = [];
this.productCategoryData.forEach(major => {
legendData.push(major.name);
seriesData.push({
name: major.name,
value: parseInt(major.value) || 0,
children: (major.children || []).map(child => ({
name: child.name,
value: parseInt(child.value) || 0,
}))
});
});
chart.setOption({
tooltip: { trigger: 'item' },
legend: { data: legendData, orient: 'vertical', right: 10, top: 20 },
series: [{
type: 'sunburst',
data: seriesData,
radius: [0, '90%'],
label: { rotate: 'radial' }
}]
});
},
```
## 注意事项
- "销售订单数"统计的是 sales_ledger 表中的订单记录数(按 entry_date),而非 sales_ledger_product 表中的产品记录数
- 日期范围筛选为空时,默认展示当前月 vs 上月的数据
- 采购品分布环形图中各小类的 value 现在来自实际的采购数据(sales_ledger_product type=2),而非写死的 0
- 所有统计指标上标注当前筛选时段(前端用 dateRange 展示)