1
xiazhengtongxue
2 天以前 5b34a1458e74f8902d01ebd844c2954f554c9e74
Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
@@ -1,26 +1,10 @@
<template>
  <div class="dashboard-container">
    <!-- 顶部:本月出入库趋势 (全宽) -->
    <!-- 各仓库月度出入库对比图 -->
    <div class="chart-row full-width">
      <div class="chart-card">
        <div class="card-title">每月出入库趋势</div>
        <div id="chart-monthly-trend" class="chart-content"></div>
      </div>
    </div>
    <!-- 第二行:每日出入库趋势 (全宽) -->
    <div class="chart-row full-width">
      <div class="chart-card">
        <div class="card-title">每日出入库趋势</div>
        <div id="chart-daily" class="chart-content"></div>
      </div>
    </div>
    <!-- 第四行:仓库分布 -->
    <div class="chart-row">
      <div class="chart-card">
        <div class="card-title">各仓库库存分布</div>
        <div id="chart-warehouse" class="chart-content"></div>
        <div class="card-title">各仓库月度出入库对比</div>
        <div id="chart-warehouse-monthly" class="chart-content"></div>
      </div>
    </div>
  </div>
@@ -34,9 +18,8 @@
  data() {
    return {
      charts: {},
      dailyData: [],
      monthlyData: [],
      warehouseData: []
      warehouseNames: ['FJSC1', 'ZJSC1', 'GWSC1', 'CWSC1', 'HCSC1']
    };
  },
  mounted() {
@@ -54,212 +37,190 @@
    },
    initCharts() {
      this.charts.monthlyTrend = echarts.init(document.getElementById("chart-monthly-trend"));
      this.charts.daily = echarts.init(document.getElementById("chart-daily"));
      this.charts.warehouse = echarts.init(document.getElementById("chart-warehouse"));
      this.charts.warehouseMonthly = echarts.init(document.getElementById("chart-warehouse-monthly"));
    },
    async loadData() {
      await this.loadMonthlyStats();
      await this.loadDailyStats();
      await this.loadStockByWarehouse();
    },
    async loadMonthlyStats() {
      try {
        const res = await this.http.get("/api/Dashboard/MonthlyStats", { months: 12 });
        if (res.status && res.data) {
          console.log("每月统计数据:", res.data);
          this.monthlyData = res.data;
          this.updateMonthlyTrendChart();
        }
        const promises = this.warehouseNames.map(warehouse =>
          this.http.get("/api/Dashboard/MonthlyStats", {
            months: 6,
            Roadway: warehouse
          })
        );
        const results = await Promise.all(promises);
        this.monthlyData = results.map((res, index) => ({
          warehouse: this.warehouseNames[index],
          warehouseName: this.getWarehouseName(this.warehouseNames[index]),
          data: res.data || []
        }));
        this.updateWarehouseMonthlyChart();
      } catch (e) {
        console.error("加载每月统计失败", e);
      }
    },
    async loadDailyStats() {
      try {
        const res = await this.http.get("/api/Dashboard/DailyStats", { days: 30 });
        if (res.status && res.data) {
          console.log("每日统计数据:", res.data);
          this.dailyData = res.data;
          this.updateDailyChart();
        }
      } catch (e) {
        console.error("加载每日统计失败", e);
      }
    },
    async loadStockByWarehouse() {
      try {
        const res = await this.http.get("/api/Dashboard/StockByWarehouse");
        if (res.status && res.data) {
          console.log("仓库分布数据:", res.data);
          this.warehouseData = res.data.data || res.data;
          this.updateWarehouseChart();
        }
      } catch (e) {
        console.error("加载仓库分布失败", e);
      }
    },
    updateMonthlyTrendChart() {
      const option = {
        tooltip: { trigger: "axis" },
        legend: { data: ["入库", "出库"], textStyle: { color: "#fff" } },
        xAxis: {
          type: "category",
          data: this.monthlyData.map(m => m.month),
          axisLabel: { color: "#fff", rotate: 45 }
        },
        yAxis: [
          {
            type: "value",
            name: "数量",
            axisLabel: { color: "#fff" }
          }
        ],
        series: [
          { name: "入库", type: "bar", data: this.monthlyData.map(m => m.inbound), itemStyle: { color: "#5470c6" } },
          { name: "出库", type: "line", data: this.monthlyData.map(m => m.outbound), itemStyle: { color: "#91cc75" } }
        ]
    getWarehouseName(code) {
      const nameMap = {
        'FJSC1': '负极卷1号仓库',
        'ZJSC1': '正极卷1号仓库',
        'GWSC1': '高温1号仓库',
        'CWSC1': '常温1号仓库',
        'HCSC1': '分容1号仓库'
      };
      this.charts.monthlyTrend.setOption(option, true);
      return nameMap[code] || code;
    },
    updateDailyChart() {
      const option = {
        tooltip: { trigger: "axis" },
        legend: { data: ["入库", "出库"], textStyle: { color: "#fff" } },
        xAxis: {
          type: "category",
          data: this.dailyData.map(d => d.date),
          axisLabel: {
            color: "#fff",
            interval: 0,
            rotate: 45,
            fontSize: 12,
            margin: 10
          },
          axisTick: {
            alignWithLabel: true
          }
        },
        yAxis: {
          type: "value",
          axisLabel: { color: "#fff" }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '15%',
          top: '10%',
          containLabel: true
        },
        series: [
          { name: "入库", type: "bar", data: this.dailyData.map(d => d.inbound), itemStyle: { color: "#5470c6" } },
          { name: "出库", type: "bar", data: this.dailyData.map(d => d.outbound), itemStyle: { color: "#91cc75" } }
        ]
      };
      this.charts.daily.setOption(option, true);
    },
    updateWarehouseChart() {
      const warehouseNames = this.warehouseData.map(w => w.warehouse);
      const totalStocks = this.warehouseData.map(w => w.total);
      const hasStocks = this.warehouseData.map(w => w.hasStock);
      const noStocks = this.warehouseData.map(w => w.noStock);
      const hasStockPercentages = this.warehouseData.map(w => w.hasStockPercentage);
      const noStockPercentages = this.warehouseData.map(w => w.noStockPercentage);
    updateWarehouseMonthlyChart() {
      // 获取所有月份
      const months = this.monthlyData[0]?.data.map(d => `${d.month}月`) || [];
      
      // 为每个仓库生成系列数据
      const series = [];
      this.monthlyData.forEach((warehouseData, index) => {
        const data = warehouseData.data;
        series.push({
          name: warehouseData.warehouseName,
          type: 'bar',
          data: data.map(d => ({
            value: (d.inbound || 0) + (d.outbound || 0),
            inbound: d.inbound || 0,
            outbound: d.outbound || 0,
            label: {
              show: true,
              position: 'top',
              formatter: function(params) {
                return `入:${params.data.inbound}\n出:${params.data.outbound}`;
              },
              fontSize: 10,
              color: '#fff',
              lineHeight: 15
            }
          })),
          barWidth: '15%',
          barGap: '10%',
          itemStyle: {
            color: this.getBarColor(index),
            borderRadius: [3, 3, 0, 0]
          }
        });
      });
      const option = {
        title: {
          text: '各仓库月度出入库对比',
          textStyle: {
            color: '#00ffff',
            fontSize: 16
          },
          left: 'center',
          top: 10
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          },
          formatter: function(params) {
            let tip = params[0].name + '<br/>';
            let tip = `<strong>${params[0].axisValue}</strong><br/>`;
            params.forEach(param => {
              const dataIndex = param.dataIndex;
              const warehouse = window.homeComponent.warehouseData[dataIndex];
              if (param.seriesName === '已用容量') {
                tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.hasStockPercentage})<br/>`;
                tip += `有库存: ${warehouse.hasStock}<br/>`;
                tip += `无库存: ${warehouse.noStock}<br/>`;
                tip += `总容量: ${warehouse.total}`;
              } else if (param.seriesName === '剩余容量') {
                tip += `${param.marker}${param.seriesName}: ${param.value} (${warehouse.noStockPercentage})<br/>`;
                tip += `有库存: ${warehouse.hasStock}<br/>`;
                tip += `无库存: ${warehouse.noStock}<br/>`;
                tip += `总容量: ${warehouse.total}`;
              }
              tip += `<span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:${param.color};margin-right:5px;"></span>`;
              tip += `${param.seriesName}: `;
              tip += `入库:${param.data.inbound} | 出库:${param.data.outbound} | 总计:${param.value}<br/>`;
            });
            return tip;
          }
        },
        legend: {
          data: ['已用容量', '剩余容量'],
          textStyle: { color: '#fff' }
          data: this.monthlyData.map(d => d.warehouseName),
          textStyle: { color: '#fff', fontSize: 11 },
          top: 45,
          left: 'center',
          type: 'scroll'
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '10%',
          top: '20%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: warehouseNames,
          axisLabel: { color: '#fff', rotate: 30 }
          data: months,
          axisLabel: {
            color: '#fff',
            fontSize: 11
          },
          axisLine: {
            lineStyle: { color: 'rgba(255,255,255,0.3)' }
          },
          splitLine: {
            show: true,
            lineStyle: {
              color: 'rgba(255,255,255,0.1)',
              type: 'dashed'
            }
          }
        },
        yAxis: {
          type: 'value',
          axisLabel: { color: '#fff' }
          name: '数量',
          nameTextStyle: { color: '#fff' },
          axisLabel: { color: '#fff' },
          splitLine: {
            lineStyle: {
              color: 'rgba(255,255,255,0.1)',
              type: 'dashed'
            }
          }
        },
        series: [
        dataZoom: [
          {
            name: '已用容量',
            type: 'bar',
            data: hasStocks.map((value, index) => ({
              value: value,
              label: {
                show: true,
                position: 'top',
                formatter: '{c} {a|' + hasStockPercentages[index] + '}',
                rich: {
                  a: {
                    lineHeight: 20,
                    borderColor: '#91cc75',
                    color: '#91cc75'
                  }
                }
              }
            })),
            itemStyle: { color: '#91cc75' }
            type: 'inside',
            start: 0,
            end: 100
          },
          {
            name: '剩余容量',
            type: 'bar',
            data: noStocks.map((value, index) => ({
              value: value,
              label: {
                show: true,
                position: 'top',
                formatter: '{c} {a|' + noStockPercentages[index] + '}',
                rich: {
                  a: {
                    lineHeight: 20,
                    borderColor: '#fac858',
                    color: '#fac858'
                  }
                }
              }
            })),
            itemStyle: { color: '#fac858' }
            start: 0,
            end: 100,
            height: 20,
            bottom: 0,
            borderColor: 'rgba(255,255,255,0.3)',
            fillerColor: 'rgba(0,255,255,0.1)',
            handleStyle: {
              color: '#00ffff',
              borderColor: '#00ffff'
            },
            textStyle: {
              color: '#fff'
            }
          }
        ]
        ],
        series: series
      };
      window.homeComponent = this;
      this.charts.warehouse.setOption(option, true);
      this.charts.warehouseMonthly.setOption(option, true);
    },
    getBarColor(index) {
      const colors = [
        '#5470c6', // 蓝
        '#fac858', // 黄
        '#73c0de', // 天蓝
        '#fc8452', // 橙
        '#ea7ccc'  // 粉
      ];
      return colors[index] || '#5470c6';
    }
  }
};
@@ -331,22 +292,6 @@
  box-shadow: 2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
}
.chart-card::before,
.chart-card::after {
  animation: neon-flicker 2s infinite alternate;
}
@keyframes neon-flicker {
  0%, 100% {
    opacity: 1;
    box-shadow: -2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
  }
  50% {
    opacity: 0.8;
    box-shadow: -2px -2px 5px #00ffff, 0 0 5px rgba(0, 255, 255, 0.5);
  }
}
.card-title {
  color: #00ffff;
  font-size: 16px;
@@ -357,21 +302,19 @@
}
.chart-content {
  height: 280px;
  height: 500px;
  width: 100%;
}
/* 全宽图表 */
.full-width .chart-card {
  flex: none;
  width: 100%;
}
.full-width .chart-content {
  height: 350px;
  height: 500px;
}
/* 添加网格线效果 */
.dashboard-container::before {
  content: "";
  position: fixed;