wanshenmean
3 天以前 ff006f77f6267fc0d2c4ee810d897a85165f5b8f
Code/WMS/WIDESEA_WMSClient/src/views/Home.vue
@@ -1,24 +1,332 @@
<template>
  <div class="title"></div>
  <div class="dashboard-container">
    <!-- 各仓库月度出入库对比图 -->
    <div class="chart-row full-width">
      <div class="chart-card">
        <div class="card-title">各仓库月度出入库对比</div>
        <div id="chart-warehouse-monthly" class="chart-content"></div>
      </div>
    </div>
  </div>
</template>
<script>
import { ref, reactive } from 'vue'
import * as echarts from "echarts";
export default {
  setup() {
  name: "Home",
  data() {
    return {
      charts: {},
      monthlyData: [],
      warehouseNames: ['FJSC1', 'ZJSC1', 'GWSC1', 'CWSC1', 'HCSC1']
    };
  },
  mounted() {
    this.initCharts();
    this.loadData();
    window.addEventListener("resize", this.handleResize);
  },
  beforeUnmount() {
    window.removeEventListener("resize", this.handleResize);
    Object.values(this.charts).forEach(chart => chart.dispose());
  },
  methods: {
    handleResize() {
      Object.values(this.charts).forEach(chart => chart.resize());
    },
    initCharts() {
      this.charts.warehouseMonthly = echarts.init(document.getElementById("chart-warehouse-monthly"));
    },
    async loadData() {
      await this.loadMonthlyStats();
    },
    async loadMonthlyStats() {
      try {
        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);
      }
    },
    getWarehouseName(code) {
      const nameMap = {
        'FJSC1': '负极卷1号仓库',
        'ZJSC1': '正极卷1号仓库',
        'GWSC1': '高温1号仓库',
        'CWSC1': '常温1号仓库',
        'HCSC1': '分容1号仓库'
      };
      return nameMap[code] || code;
    },
    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 = `<strong>${params[0].axisValue}</strong><br/>`;
            params.forEach(param => {
              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: 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: 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',
          name: '数量',
          nameTextStyle: { color: '#fff' },
          axisLabel: { color: '#fff' },
          splitLine: {
            lineStyle: {
              color: 'rgba(255,255,255,0.1)',
              type: 'dashed'
            }
          }
        },
        dataZoom: [
          {
            type: 'inside',
            start: 0,
            end: 100
          },
          {
            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
      };
      this.charts.warehouseMonthly.setOption(option, true);
    },
    getBarColor(index) {
      const colors = [
        '#5470c6', // 蓝
        '#fac858', // 黄
        '#73c0de', // 天蓝
        '#fc8452', // 橙
        '#ea7ccc'  // 粉
      ];
      return colors[index] || '#5470c6';
    }
  }
}
};
</script>
<style scoped>
.title {
  line-height: 70vh;
.dashboard-container {
  padding: 20px;
  color: #e0e0e0;
  min-height: calc(100vh - 60px);
  background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
  background-attachment: fixed;
}
.chart-row {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}
.chart-row.full-width {
  width: 100%;
}
.chart-card {
  flex: 1;
  background: rgba(10, 16, 35, 0.6);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(64, 224, 208, 0.3);
  border-radius: 12px;
  padding: 15px;
  position: relative;
  box-shadow:
    0 0 15px rgba(0, 255, 255, 0.1),
    inset 0 0 10px rgba(64, 224, 208, 0.1);
  transition: all 0.3s ease;
  overflow: hidden;
}
.chart-card:hover {
  transform: translateY(-5px);
  box-shadow:
    0 0 25px rgba(0, 255, 255, 0.3),
    inset 0 0 15px rgba(64, 224, 208, 0.2);
  border: 1px solid rgba(64, 224, 208, 0.6);
}
.chart-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 10px;
  height: 10px;
  border-top: 2px solid #00ffff;
  border-left: 2px solid #00ffff;
  box-shadow: -2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
}
.chart-card::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 10px;
  height: 10px;
  border-top: 2px solid #00ffff;
  border-right: 2px solid #00ffff;
  box-shadow: 2px -2px 10px #00ffff, 0 0 10px rgba(0, 255, 255, 0.7);
}
.card-title {
  color: #00ffff;
  font-size: 16px;
  text-align: center;
  font-size: 28px;
  color: orange;
  margin-bottom: 10px;
  text-shadow: 0 0 10px rgba(0, 255, 255, 0.7);
  font-weight: 500;
}
.chart-content {
  height: 500px;
  width: 100%;
}
.full-width .chart-card {
  flex: none;
  width: 100%;
}
.full-width .chart-content {
  height: 500px;
}
.dashboard-container::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image:
    linear-gradient(rgba(64, 224, 208, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(64, 224, 208, 0.05) 1px, transparent 1px);
  background-size: 30px 30px;
  pointer-events: none;
  z-index: -1;
}
</style>