编辑 | blame | 历史 | 原始文档

管理驾驶舱(PSI 数据分析大屏)优化

涉及页面

  • 管理驾驶舱 / PSI 数据分析大屏

API

方法 路径 说明
GET /home/salesPurchaseStorageProductCount 销售-采购-储存统计(新增日期筛选)
GET /home/productCategoryDistribution 产品大类分布(修复数据)

1. 销售-采购-储存统计接口

请求参数(新增):

参数 类型 必填 说明
startDate String 开始日期(yyyy-MM-dd)
endDate String 结束日期(yyyy-MM-dd)

不传日期参数时默认统计当前月 vs 上月。

响应格式变化:
- 第一个指标名称从 "销售产品数" 改为 "销售订单数"
- 数值统计口径从"销售产品记录数"改为"销售订单数(sales_ledger 表记录数)"

{
  "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. 顶部指标修改 - "销售产品数" → "销售订单数"

<div class="stat-card">
  <div class="stat-label">销售订单数</div>
  <div class="stat-value">{{ salesOrderCount.value }}</div>
  <div class="stat-rate" :class="{ up: salesOrderCount.rate > 0, down: salesOrderCount.rate < 0 }">
    环比 {{ salesOrderCount.rate }}%
  </div>
</div>

2. 日期范围筛选控件

在页面左上角新增日期范围下拉筛选。

<el-date-picker
  v-model="dateRange"
  type="daterange"
  range-separator="至"
  start-placeholder="开始日期"
  end-placeholder="结束日期"
  value-format="yyyy-MM-dd"
  @change="handleDateChange"
  style="margin-right: 16px;" />

3. data 数据

data() {
  return {
    dateRange: [],
    salesOrderCount: { value: 0, rate: 0 },
    purchaseProductCount: { value: 0, rate: 0 },
    storageProductCount: { value: 0, rate: 0 },
    productCategoryData: [],
  }
}

4. 方法

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 展示)