·
huangxiaoqiang
2025-12-25 9aaa5a60d9dc29d8db588bc066ccf43b0231affc
·
已添加1个文件
已修改2个文件
903 ■■■■■ 文件已修改
项目代码/WIDESEA_WMSClient/package-lock.json 174 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/router/viewGird.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WIDESEA_WMSClient/src/views/charts/wms-dashboard.vue 725 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WIDESEA_WMSClient/package-lock.json
@@ -3612,6 +3612,11 @@
      "dev": true,
      "optional": true
    },
    "@popperjs/core": {
      "version": "npm:@sxzz/popperjs-es@2.11.7",
      "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
    },
    "@soda/friendly-errors-webpack-plugin": {
      "version": "1.8.0",
      "resolved": "https://registry.npm.taobao.org/@soda/friendly-errors-webpack-plugin/download/@soda/friendly-errors-webpack-plugin-1.8.0.tgz?cache=0&sync_timestamp=1607927406873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40soda%2Ffriendly-errors-webpack-plugin%2Fdownload%2F%40soda%2Ffriendly-errors-webpack-plugin-1.8.0.tgz",
@@ -4386,87 +4391,6 @@
        "webpack-chain": "^6.4.0",
        "webpack-dev-server": "^3.11.0",
        "webpack-merge": "^4.2.2"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        },
        "vue-loader-v16": {
          "version": "npm:vue-loader@16.8.3",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/vue-loader/-/vue-loader-16.8.3.tgz",
          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
          "dev": true,
          "optional": true,
          "requires": {
            "chalk": "^4.1.0",
            "hash-sum": "^2.0.0",
            "loader-utils": "^2.0.0"
          }
        }
      }
    },
    "@vue/cli-shared-utils": {
@@ -7637,13 +7561,6 @@
        "lodash-unified": "^1.0.2",
        "memoize-one": "^6.0.0",
        "normalize-wheel-es": "^1.2.0"
      },
      "dependencies": {
        "@popperjs/core": {
          "version": "npm:@sxzz/popperjs-es@2.11.7",
          "resolved": "https://mirrors.huaweicloud.com/repository/npm/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
          "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
        }
      }
    },
    "element-ui": {
@@ -15471,6 +15388,87 @@
        }
      }
    },
    "vue-loader-v16": {
      "version": "npm:vue-loader@16.8.3",
      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
      "dev": true,
      "optional": true,
      "requires": {
        "chalk": "^4.1.0",
        "hash-sum": "^2.0.0",
        "loader-utils": "^2.0.0"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "4.3.0",
          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-convert": "^2.0.1"
          }
        },
        "chalk": {
          "version": "4.1.2",
          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
          "dev": true,
          "optional": true,
          "requires": {
            "ansi-styles": "^4.1.0",
            "supports-color": "^7.1.0"
          }
        },
        "color-convert": {
          "version": "2.0.1",
          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
          "dev": true,
          "optional": true,
          "requires": {
            "color-name": "~1.1.4"
          }
        },
        "color-name": {
          "version": "1.1.4",
          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
          "dev": true,
          "optional": true
        },
        "has-flag": {
          "version": "4.0.0",
          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
          "dev": true,
          "optional": true
        },
        "loader-utils": {
          "version": "2.0.4",
          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
          "dev": true,
          "optional": true,
          "requires": {
            "big.js": "^5.2.2",
            "emojis-list": "^3.0.0",
            "json5": "^2.1.2"
          }
        },
        "supports-color": {
          "version": "7.2.0",
          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
          "dev": true,
          "optional": true,
          "requires": {
            "has-flag": "^4.0.0"
          }
        }
      }
    },
    "vue-qrcode": {
      "version": "2.2.2",
      "resolved": "https://registry.npmmirror.com/vue-qrcode/-/vue-qrcode-2.2.2.tgz",
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/router/viewGird.js
@@ -247,6 +247,10 @@
    path: '/takeStockOrderDetail',
    name: 'takeStockOrderDetail',
    component: () => import('@/views/inbound/takeStockOrderDetail.vue')
  }, {
    path: '/dashboard',
    name: 'dashboard',
    component: () => import('@/views/charts/wms-dashboard.vue')
  }
]
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/views/charts/wms-dashboard.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,725 @@
<template>
  <div class="wms-dashboard">
    <!-- é¡¶éƒ¨æ ‡é¢˜æ  -->
    <div class="header">
      <h1>WMS仓储可视化图表看板</h1>
      <div class="header-right">
        <span>2025-12-24 16:11:44</span>
        <el-select v-model="month" placeholder="本月" style="margin-left: 10px; width: 80px;">
          <el-option label="本月" value="month"></el-option>
          <el-option label="上月" value="lastMonth"></el-option>
        </el-select>
        <el-button type="primary" style="margin-left: 10px;" @click="refreshCharts">刷新</el-button>
      </div>
    </div>
    <!-- ç»Ÿè®¡å¡ç‰‡åŒºåŸŸ -->
    <el-row :gutter="20" class="stats-card-row">
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">总库存(件)</div>
          <div class="card-value">269,225</div>
          <div class="card-change"><el-tag type="success">↑ 2.1% è¾ƒæ˜¨æ—¥</el-tag></div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">待出库订单</div>
          <div class="card-value">425</div>
          <div class="card-change"><el-tag type="warning">↑ 5.3% è¾ƒ1小时前</el-tag></div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">今日作业完成率</div>
          <div class="card-value">93.9%</div>
          <div class="card-change"><el-tag type="success">↑ 1.8% è¾ƒæ˜¨æ—¥</el-tag></div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card">
          <div class="card-title">未处理异常</div>
          <div class="card-value">7</div>
          <div class="card-change"><el-tag type="danger">↑ 1 è¾ƒ30分钟前</el-tag></div>
        </el-card>
      </el-col>
    </el-row>
    <!-- å›¾è¡¨åŒºåŸŸï¼ˆç¬¬ä¸€è¡Œï¼‰ -->
    <el-row :gutter="20" class="chart-row">
      <el-col :span="12">
        <el-card class="chart-card">
          <div class="chart-title">库存库位分布(图像化占比)<el-button type="text" class="view-btn">切换视图</el-button></div>
          <div ref="inventoryPieRef" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="chart-card">
          <div class="chart-title">近7日出入库趋势(图像化走势)
            <el-button-group class="btn-group">
              <el-button type="primary" size="small">全部</el-button>
              <el-button type="default" size="small">入库</el-button>
              <el-button type="default" size="small">出库</el-button>
            </el-button-group>
          </div>
          <div ref="stockTrendRef" class="chart-container"></div>
        </el-card>
      </el-col>
    </el-row>
    <!-- å›¾è¡¨åŒºåŸŸï¼ˆç¬¬äºŒè¡Œï¼‰ -->
    <el-row :gutter="20" class="chart-row">
      <el-col :span="8">
        <el-card class="chart-card">
          <div class="chart-title">库位利用率</div>
          <div ref="locationRateRef" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="chart-card">
          <div class="chart-title">作业类型分布<el-button type="text" class="view-btn">查看详情</el-button></div>
          <div ref="operationRadarRef" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="chart-card">
          <div class="chart-title">异常类型统计趋势<el-button type="text" class="view-btn">筛选</el-button></div>
          <div ref="exceptionTrendRef" class="chart-container"></div>
        </el-card>
      </el-col>
    </el-row>
    <!-- è¡¨æ ¼åŒºåŸŸ -->
    <el-row :gutter="20" class="table-row">
      <el-col :span="12">
        <el-card class="table-card">
          <div class="table-title">订单处理进度<el-select v-model="orderType" placeholder="退货入库"
              style="width: 100px; margin-left: 10px;">
              <el-option label="退货入库" value="return"></el-option>
              <el-option label="普通出库" value="normal"></el-option>
            </el-select></div>
          <el-table :data="orderList" border style="width: 100%;">
            <el-table-column prop="orderNo" label="订单号" />
            <el-table-column prop="type" label="类型" />
            <el-table-column prop="priority" label="优先级">
              <template #default="scope">
                <el-tag
                  :type="scope.row.priority === '紧急' ? 'danger' : scope.row.priority === '加急' ? 'warning' : 'success'">
                  {{ scope.row.priority }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="progress" label="进度">
              <template #default="scope">
                <el-progress :percentage="scope.row.progress" :color="scope.row.progressColor" />
              </template>
            </el-table-column>
          </el-table>
          <div class="table-pagination">
            <el-button type="text">加载更多订单</el-button>
            <el-pagination layout="prev, pager, next, jumper" :current-page="1" :total="50" />
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="table-card">
          <div class="table-title">实时作业监控
            <el-button-group class="btn-group">
              <el-button type="primary" size="small">全部作业</el-button>
              <el-button type="default" size="small">入库</el-button>
              <el-button type="default" size="small">出库</el-button>
              <el-button type="default" size="small">盘点</el-button>
            </el-button-group>
          </div>
          <el-table :data="operationList" border style="width: 100%;">
            <el-table-column prop="opNo" label="作业单号" />
            <el-table-column prop="opType" label="作业类型" />
            <el-table-column prop="operator" label="操作人员" />
            <el-table-column prop="startTime" label="开始时间" />
            <el-table-column prop="status" label="当前状态">
              <template #default="scope">
                <el-tag :type="scope.row.status === '处理中' ? 'info' : scope.row.status === '已完成' ? 'success' : 'danger'">
                  {{ scope.row.status }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作"><el-button type="text">详情</el-button></el-table-column>
          </el-table>
          <div class="table-pagination">
            <el-pagination layout="prev, pager, next, jumper" :current-page="1" :total="50" />
          </div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
// å“åº”式数据
const month = ref('month');
const orderType = ref('return');
// æ¨¡æ‹Ÿæ•°æ®
const orderList = ref([
  { orderNo: 'OD20251224001', type: '普通出库', priority: '紧急', progress: 60, progressColor: '#ff4d4f' },
  { orderNo: 'OD20251224002', type: '退货入库', priority: '普通', progress: 80, progressColor: '#1890ff' },
  { orderNo: 'OD20251224003', type: '调拨订单', priority: '加急', progress: 40, progressColor: '#faad14' },
  { orderNo: 'OD20251224004', type: '普通出库', priority: '常规', progress: 100, progressColor: '#52c41a' }
]);
const operationList = ref([
  { opNo: 'JW251224001', opType: '入库', operator: '张三', startTime: '15:30:22', status: '处理中' },
  { opNo: 'CK251224002', opType: '出库', operator: '李四', startTime: '15:25:10', status: '已完成' },
  { opNo: 'PD251224003', opType: '盘点', operator: '王五', startTime: '15:20:05', status: '待确认' },
  { opNo: 'SC251224005', opType: '上架', operator: '孙七', startTime: '15:10:18', status: '异常' }
]);
// å›¾è¡¨å®¹å™¨
const inventoryPieRef = ref(null);
const stockTrendRef = ref(null);
const locationRateRef = ref(null);
const operationRadarRef = ref(null);
const exceptionTrendRef = ref(null);
// å›¾è¡¨å®žä¾‹
let inventoryPieChart = null;
let stockTrendChart = null;
let locationRateChart = null;
let operationRadarChart = null;
let exceptionTrendChart = null;
// åˆå§‹åŒ–库存库位分布饼图
const initInventoryPie = () => {
  if (!inventoryPieRef.value) return;
  if (inventoryPieChart) {
    inventoryPieChart.dispose();
  }
  inventoryPieChart = echarts.init(inventoryPieRef.value);
  const option = {
    tooltip: {
      trigger: 'item',
      formatter: '{a} <br/>{b}: {c}%'
    },
    legend: {
      bottom: 0,
      left: 'center',
      data: ['常温区A区', '冷藏区B区', '保税区C区', '残次品区D区']
    },
    series: [{
      name: '库存库位分布',
      type: 'pie',
      radius: ['40%', '70%'],
      center: ['50%', '40%'],
      avoidLabelOverlap: false,
      itemStyle: {
        borderRadius: 10,
        borderColor: '#fff',
        borderWidth: 2
      },
      label: {
        show: false,
        position: 'center'
      },
      emphasis: {
        label: {
          show: true,
          fontSize: 20,
          fontWeight: 'bold'
        }
      },
      labelLine: {
        show: false
      },
      data: [
        { value: 48.7, name: '常温区A区', itemStyle: { color: '#5470c6' } },
        { value: 29.2, name: '冷藏区B区', itemStyle: { color: '#91cc75' } },
        { value: 21.9, name: '保税区C区', itemStyle: { color: '#fac858' } },
        { value: 2.2, name: '残次品区D区', itemStyle: { color: '#ee6666' } }
      ]
    }]
  };
  inventoryPieChart.setOption(option);
  return inventoryPieChart;
};
// åˆå§‹åŒ–è¿‘7日出入库趋势图
const initStockTrend = () => {
  if (!stockTrendRef.value) return;
  if (stockTrendChart) {
    stockTrendChart.dispose();
  }
  stockTrendChart = echarts.init(stockTrendRef.value);
  const option = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      }
    },
    legend: {
      data: ['入库量', '出库量'],
      top: 10
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      top: '15%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: true,
      data: ['12-18', '12-19', '12-20', '12-21', '12-22', '12-23', '12-24']
    },
    yAxis: {
      type: 'value',
      name: '数量(千件)',
      max: 25
    },
    series: [
      {
        name: '入库量',
        type: 'bar',
        barWidth: '30%',
        data: [10, 12, 10, 12, 10, 12, 12],
        itemStyle: { color: '#52c41a' }
      },
      {
        name: '出库量',
        type: 'bar',
        barWidth: '30%',
        data: [16, 18, 14, 18, 16, 18, 20],
        itemStyle: { color: '#1890ff' }
      }
    ]
  };
  stockTrendChart.setOption(option);
  return stockTrendChart;
};
// åˆå§‹åŒ–库位利用率环形图
const initLocationRate = () => {
  if (!locationRateRef.value) return;
  if (locationRateChart) {
    locationRateChart.dispose();
  }
  locationRateChart = echarts.init(locationRateRef.value);
  const option = {
    tooltip: {
      formatter: '{a} <br/>{b} : {c}%'
    },
    series: [{
      name: '库位利用率',
      type: 'gauge',
      min: 0,
      max: 100,
      splitNumber: 10,
      radius: '90%',
      center: ['50%', '55%'],
      startAngle: 180,
      endAngle: 0,
      progress: {
        show: true,
        width: 20,
        itemStyle: {
          color: '#1890ff'
        }
      },
      axisLine: {
        lineStyle: {
          width: 20,
          color: [[1, 'rgba(200,200,200,0.3)']]
        }
      },
      axisTick: {
        distance: -30,
        splitNumber: 5,
        lineStyle: {
          width: 2,
          color: '#999'
        }
      },
      splitLine: {
        distance: -30,
        length: 14,
        lineStyle: {
          width: 3,
          color: '#999'
        }
      },
      axisLabel: {
        distance: -20,
        color: '#999',
        fontSize: 12
      },
      anchor: {
        show: false
      },
      title: {
        show: true,
        offsetCenter: [0, '30%'],
        fontSize: 16,
        fontWeight: 'bold'
      },
      detail: {
        valueAnimation: true,
        formatter: '{value}%',
        fontSize: 20,
        fontWeight: 'bold',
        offsetCenter: [0, '70%']
      },
      data: [{
        value: 86.2,
        name: '库位利用率'
      }]
    }]
  };
  locationRateChart.setOption(option);
  return locationRateChart;
};
// åˆå§‹åŒ–作业类型雷达图
const initOperationRadar = () => {
  if (!operationRadarRef.value) return;
  if (operationRadarChart) {
    operationRadarChart.dispose();
  }
  operationRadarChart = echarts.init(operationRadarRef.value);
  const option = {
    tooltip: {
      trigger: 'item'
    },
    legend: {
      show: false
    },
    radar: {
      indicator: [
        { name: '出库作业', max: 100 },
        { name: '入库作业', max: 100 },
        { name: '调拨作业', max: 100 },
        { name: '盘点作业', max: 100 }
      ],
      shape: 'circle',
      splitNumber: 5,
      axisName: {
        color: '#666'
      },
      splitLine: {
        lineStyle: {
          color: 'rgba(0,0,0,0.1)'
        }
      },
      splitArea: {
        show: true,
        areaStyle: {
          color: ['rgba(255,255,255,0.8)', 'rgba(200,200,200,0.2)']
        }
      }
    },
    series: [{
      name: '作业类型分布',
      type: 'radar',
      symbolSize: 8,
      areaStyle: {
        color: 'rgba(24,144,255,0.3)'
      },
      lineStyle: {
        width: 2
      },
      itemStyle: {
        color: '#1890ff'
      },
      data: [{
        value: [45, 30, 15, 10],
        name: '作业占比',
        label: {
          show: true,
          formatter: function (params) {
            return params.value + '%';
          }
        }
      }]
    }]
  };
  operationRadarChart.setOption(option);
  return operationRadarChart;
};
// åˆå§‹åŒ–异常趋势折线图
const initExceptionTrend = () => {
  if (!exceptionTrendRef.value) return;
  if (exceptionTrendChart) {
    exceptionTrendChart.dispose();
  }
  exceptionTrendChart = echarts.init(exceptionTrendRef.value);
  const option = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      }
    },
    legend: {
      data: ['库存不足', '订单超时', '库位异常', '盘点差异'],
      top: 10
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      top: '15%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: ['12-18', '12-19', '12-20', '12-21', '12-22', '12-23', '12-24']
    },
    yAxis: {
      type: 'value',
      name: '异常数量'
    },
    series: [
      {
        name: '库存不足',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [10, 11, 9, 12, 10, 13, 12],
        itemStyle: { color: '#ff4d4f' },
        lineStyle: {
          width: 3
        }
      },
      {
        name: '订单超时',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [8, 9, 7, 8, 7, 9, 8],
        itemStyle: { color: '#faad14' },
        lineStyle: {
          width: 3
        }
      },
      {
        name: '库位异常',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [4, 5, 2, 4, 3, 5, 4],
        itemStyle: { color: '#722ed1' },
        lineStyle: {
          width: 3
        }
      },
      {
        name: '盘点差异',
        type: 'line',
        smooth: true,
        symbol: 'circle',
        symbolSize: 8,
        data: [2, 3, 1, 2, 1, 3, 2],
        itemStyle: { color: '#13c2c2' },
        lineStyle: {
          width: 3
        }
      }
    ]
  };
  exceptionTrendChart.setOption(option);
  return exceptionTrendChart;
};
// åˆ·æ–°æ‰€æœ‰å›¾è¡¨
const refreshCharts = () => {
  const charts = [
    initInventoryPie,
    initStockTrend,
    initLocationRate,
    initOperationRadar,
    initExceptionTrend
  ];
  charts.forEach(initFunc => {
    const chart = initFunc();
    if (chart) {
      chart.resize();
    }
  });
};
// ç›‘听窗口大小变化
const handleResize = () => {
  const charts = [
    inventoryPieChart,
    stockTrendChart,
    locationRateChart,
    operationRadarChart,
    exceptionTrendChart
  ];
  charts.forEach(chart => {
    if (chart) {
      chart.resize();
    }
  });
};
// æŒ‚载后初始化图表
onMounted(() => {
  nextTick(() => {
    initInventoryPie();
    initStockTrend();
    initLocationRate();
    initOperationRadar();
    initExceptionTrend();
    window.addEventListener('resize', handleResize);
  });
});
// ç»„件卸载时清理
onUnmounted(() => {
  const charts = [
    inventoryPieChart,
    stockTrendChart,
    locationRateChart,
    operationRadarChart,
    exceptionTrendChart
  ];
  charts.forEach(chart => {
    if (chart) {
      chart.dispose();
    }
  });
  window.removeEventListener('resize', handleResize);
});
</script>
<style scoped>
.wms-dashboard {
  padding: 20px;
  background: #f5f7fa;
  min-height: 100vh;
  box-sizing: border-box;
}
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  background: white;
  padding: 15px 20px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.stats-card-row,
.chart-row,
.table-row {
  margin-bottom: 20px;
}
.stats-card {
  height: 120px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 20px;
  transition: all 0.3s ease;
}
.stats-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.card-title {
  font-size: 14px;
  color: #666;
  margin-bottom: 8px;
}
.card-value {
  font-size: 28px;
  font-weight: bold;
  margin: 8px 0 4px;
  color: #333;
}
.card-change {
  margin-top: 8px;
}
.chart-card {
  height: 320px;
  padding: 15px;
  display: flex;
  flex-direction: column;
}
.chart-container {
  width: 100%;
  height: 100%;
  min-height: 250px;
  flex: 1;
}
.chart-title,
.table-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  font-size: 16px;
  font-weight: bold;
  color: #333;
}
.view-btn {
  font-size: 12px;
}
.table-pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 15px;
}
.btn-group {
  margin-left: 10px;
}
/* ç¡®ä¿å›¾è¡¨å®¹å™¨æœ‰æ˜Žç¡®å°ºå¯¸ */
:deep(.el-card__body) {
  height: 100%;
  display: flex;
  flex-direction: column;
}
</style>