From 32898366256ac7a99c4ecdd094e05e54f8a7e621 Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期五, 26 十二月 2025 09:28:58 +0800
Subject: [PATCH] Merge branch 'htq20251215' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu into htq20251215
---
项目代码/WIDESEA_WMSClient/src/extension/stock/stockView.js | 8
项目代码/Dashboard/src/router/index.js | 45
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs | 13
项目代码/Dashboard/.gitignore | 24
项目代码/Dashboard/src/App.vue | 28
项目代码/WIDESEA_WMSClient/src/extension/outbound/extend/printView.vue | 26
项目代码/Dashboard/vite.config.js | 23
项目代码/Dashboard/src/utils/http.js | 107 +
项目代码/Dashboard/src/views/Production.vue | 837 ++++++++
项目代码/Dashboard/package-lock.json | 945 +++++++++
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/StockStatusEmun.cs | 3
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db | 0
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs | 26
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db | 0
项目代码/Dashboard/src/main.js | 17
项目代码/Dashboard/src/views/Inventory.vue | 831 ++++++++
项目代码/Dashboard/API使用指南.md | 400 ++++
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs | 4
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs | 1
项目代码/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue | 1
项目代码/Dashboard/README.md | 172 +
项目代码/Dashboard/src/utils/index.js | 111 +
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs | 2
项目代码/Dashboard/src/examples/ApiExample.vue | 618 ++++++
项目代码/Dashboard/src/views/Dashboard.vue | 729 +++++++
项目代码/WIDESEA_WMSClient/src/views/outbound/printForm.vue | 44
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/QuartzJobMildd.cs | 13
项目代码/Dashboard/src/api/index.js | 143 +
项目代码/Dashboard/src/views/Warehouse.vue | 582 ++++++
项目代码/Dashboard/index.html | 12
项目代码/Dashboard/package.json | 24
31 files changed, 5,718 insertions(+), 71 deletions(-)
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/.gitignore" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/.gitignore"
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/.gitignore"
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/API\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/API\344\275\277\347\224\250\346\214\207\345\215\227.md"
new file mode 100644
index 0000000..620d640
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/API\344\275\277\347\224\250\346\214\207\345\215\227.md"
@@ -0,0 +1,400 @@
+# API 璋冪敤鎺ュ彛浣跨敤鎸囧崡
+
+## 蹇�熷紑濮�
+
+### 1. 鍩虹 HTTP 璋冪敤
+
+浣跨敤 `http` 宸ュ叿鐩存帴璋冪敤鎺ュ彛锛�
+
+```javascript
+import { http } from '@/utils/http'
+
+// GET 璇锋眰
+const getUsers = async () => {
+ const res = await http.get('/api/user/list', { page: 1, pageSize: 10 })
+ return res.data
+}
+
+// POST 璇锋眰
+const createUser = async () => {
+ const res = await http.post('/api/user/create', {
+ name: '寮犱笁',
+ age: 25
+ })
+ return res.data
+}
+
+// PUT 璇锋眰
+const updateUser = async (id) => {
+ const res = await http.put(`/api/user/${id}`, {
+ name: '鏉庡洓'
+ })
+ return res.data
+}
+
+// DELETE 璇锋眰
+const deleteUser = async (id) => {
+ const res = await http.delete(`/api/user/${id}`)
+ return res.data
+}
+```
+
+### 2. 浣跨敤灏佽鐨� API 妯″潡
+
+鎵�鏈夋帴鍙e凡缁熶竴灏佽鍦� `/src/api/index.js` 涓細
+
+```javascript
+import { warehouseApi, inventoryApi, taskApi } from '@/api'
+
+// 鑾峰彇浠撳簱鐘舵��
+const warehouse = await warehouseApi.getWarehouseStatus()
+
+// 鑾峰彇搴撳瓨鍒楄〃
+const inventory = await inventoryApi.getInventoryList({ page: 1 })
+
+// 鑾峰彇浠诲姟鍒楄〃
+const tasks = await taskApi.getTaskList({ status: '杩涜涓�' })
+
+// 鍒涘缓浠诲姟
+const newTask = await taskApi.createTask({
+ taskNo: 'RK001',
+ type: '鍏ュ簱',
+ material: '閽㈡澘',
+ quantity: 100
+})
+```
+
+## 鍦� Vue 缁勪欢涓娇鐢�
+
+### 绀轰緥1: 绠�鍗曟暟鎹幏鍙�
+
+```vue
+<template>
+ <div>
+ <el-button @click="fetchData" :loading="loading">鑾峰彇鏁版嵁</el-button>
+ <div v-if="data">{{ data }}</div>
+ </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { http } from '@/utils/http'
+
+const loading = ref(false)
+const data = ref(null)
+
+const fetchData = async () => {
+ loading.value = true
+ try {
+ const res = await http.get('/api/data')
+ data.value = res.data
+ } catch (error) {
+ console.error('璇锋眰澶辫触:', error)
+ } finally {
+ loading.value = false
+ }
+}
+</script>
+```
+
+### 绀轰緥2: 浣跨敤 API 妯″潡
+
+```vue
+<template>
+ <div>
+ <el-table :data="warehouseList" v-loading="loading">
+ <el-table-column prop="name" label="浠撳簱鍚嶇О" />
+ <el-table-column prop="capacity" label="瀹归噺" />
+ </el-table>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import { warehouseApi } from '@/api'
+
+const loading = ref(false)
+const warehouseList = ref([])
+
+const fetchWarehouse = async () => {
+ loading.value = true
+ try {
+ const res = await warehouseApi.getAreas()
+ warehouseList.value = res.data
+ } catch (error) {
+ ElMessage.error('鑾峰彇浠撳簱鍒楄〃澶辫触')
+ } finally {
+ loading.value = false
+ }
+}
+
+onMounted(() => {
+ fetchWarehouse()
+})
+</script>
+```
+
+### 绀轰緥3: 琛ㄥ崟鎻愪氦
+
+```vue
+<template>
+ <el-form @submit.prevent="handleSubmit">
+ <el-form-item label="浠诲姟缂栧彿">
+ <el-input v-model="form.taskNo" />
+ </el-form-item>
+ <el-form-item label="浠诲姟绫诲瀷">
+ <el-select v-model="form.type">
+ <el-option label="鍏ュ簱" value="鍏ュ簱" />
+ <el-option label="鍑哄簱" value="鍑哄簱" />
+ </el-select>
+ </el-form-item>
+ <el-button type="primary" native-type="submit" :loading="submitting">
+ 鎻愪氦
+ </el-button>
+ </el-form>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import { taskApi } from '@/api'
+
+const submitting = ref(false)
+const form = ref({
+ taskNo: '',
+ type: '鍏ュ簱'
+})
+
+const handleSubmit = async () => {
+ submitting.value = true
+ try {
+ const res = await taskApi.createTask(form.value)
+ ElMessage.success('鍒涘缓鎴愬姛')
+ // 澶勭悊杩斿洖鏁版嵁...
+ } catch (error) {
+ ElMessage.error('鍒涘缓澶辫触')
+ } finally {
+ submitting.value = false
+ }
+}
+</script>
+```
+
+### 绀轰緥4: 骞跺彂璇锋眰
+
+```vue
+<script setup>
+import { ref, onMounted } from 'vue'
+import { warehouseApi, inventoryApi, taskApi } from '@/api'
+
+const dashboardData = ref({
+ warehouse: null,
+ inventory: null,
+ tasks: null
+})
+
+const fetchDashboardData = async () => {
+ try {
+ // 鍚屾椂鍙戣捣澶氫釜璇锋眰锛岀瓑寰呭叏閮ㄥ畬鎴�
+ const [warehouse, inventory, tasks] = await Promise.all([
+ warehouseApi.getWarehouseStatus(),
+ inventoryApi.getInventoryOverview(),
+ taskApi.getTaskList({ status: '杩涜涓�' })
+ ])
+
+ dashboardData.value = {
+ warehouse: warehouse.data,
+ inventory: inventory.data,
+ tasks: tasks.data
+ }
+ } catch (error) {
+ console.error('鑾峰彇鐪嬫澘鏁版嵁澶辫触:', error)
+ }
+}
+
+onMounted(() => {
+ fetchDashboardData()
+})
+</script>
+```
+
+## API 妯″潡瀹屾暣鍒楄〃
+
+### warehouseApi - 浠撳簱鐩稿叧
+
+```javascript
+// 鑾峰彇浠撳簱鐘舵�佹瑙�
+warehouseApi.getWarehouseStatus()
+
+// 鑾峰彇浠撳簱鍖哄煙淇℃伅
+warehouseApi.getAreas()
+
+// 鑾峰彇搴撲綅淇℃伅
+warehouseApi.getLocations(params)
+
+// 鑾峰彇娓╂箍搴︽暟鎹�
+warehouseApi.getEnvData()
+```
+
+### inventoryApi - 搴撳瓨鐩稿叧
+
+```javascript
+// 鑾峰彇搴撳瓨姒傝
+inventoryApi.getInventoryOverview()
+
+// 鑾峰彇搴撳瓨鍒楄〃
+inventoryApi.getInventoryList(params)
+
+// 搴撳瓨棰勮鍒楄〃
+inventoryApi.getLowStockAlerts(params)
+
+// 搴撳瓨绉帇鍒楄〃
+inventoryApi.getOverStockAlerts(params)
+
+// 鍗冲皢杩囨湡鐗╂枡
+inventoryApi.getExpiringItems(params)
+
+// 搴撳瓨鍛ㄨ浆鐜�
+inventoryApi.getTurnoverRate(params)
+
+// ABC鍒嗙被缁熻
+inventoryApi.getABCStats()
+```
+
+### taskApi - 浠诲姟鐩稿叧
+
+```javascript
+// 鑾峰彇浠诲姟鍒楄〃
+taskApi.getTaskList(params)
+
+// 鍒涘缓浠诲姟
+taskApi.createTask(data)
+
+// 鏇存柊浠诲姟鐘舵��
+taskApi.updateTaskStatus(taskId, data)
+
+// 鑾峰彇浠诲姟璇︽儏
+taskApi.getTaskDetail(taskId)
+```
+
+### ioApi - 鍑哄叆搴撶浉鍏�
+
+```javascript
+// 鍏ュ簱鍗曞垪琛�
+ioApi.getInboundList(params)
+
+// 鍑哄簱鍗曞垪琛�
+ioApi.getOutboundList(params)
+
+// 鍒涘缓鍏ュ簱鍗�
+ioApi.createInbound(data)
+
+// 鍒涘缓鍑哄簱鍗�
+ioApi.createOutbound(data)
+
+// 鍑哄叆搴撶粺璁�
+ioApi.getIOStats(params)
+```
+
+### productionApi - 鐢熶骇鐩稿叧
+
+```javascript
+// 鑾峰彇鐢熶骇绾跨姸鎬�
+productionApi.getProductionLines()
+
+// 鑾峰彇璁惧鐘舵��
+productionApi.getDeviceStatus(lineId)
+
+// 鑾峰彇鐢熶骇浠诲姟鍒楄〃
+productionApi.getProductionTasks(params)
+
+// 浜ч噺缁熻
+productionApi.getProductionStats(params)
+
+// 鑹搧鐜囩粺璁�
+productionApi.getQualityStats(params)
+
+// 璁惧OEE
+productionApi.getDeviceOEE(params)
+```
+
+### reportApi - 鎶ヨ〃鐩稿叧
+
+```javascript
+// 缁煎悎鐪嬫澘鏁版嵁
+reportApi.getDashboardData()
+
+// 鍑哄叆搴撹秼鍔�
+reportApi.getTrendData(params)
+
+// 鍒嗙被鍗犳瘮
+reportApi.getCategoryStats()
+
+// 浣滀笟鏁堢巼缁熻
+reportApi.getEfficiencyStats(params)
+```
+
+## 閿欒澶勭悊
+
+http 宸ュ叿宸茬粡鍐呯疆浜嗛敊璇鐞嗭細
+
+```javascript
+import { http } from '@/utils/http'
+
+try {
+ const res = await http.get('/api/data')
+ // res.data 鏄悗绔繑鍥炵殑鏁版嵁
+} catch (error) {
+ // 閿欒宸茬粡琚嫤鎴櫒澶勭悊骞舵樉绀烘彁绀�
+ // 杩欓噷鍙互鍋氶澶栫殑閿欒澶勭悊
+ console.error('鑷畾涔夐敊璇鐞�:', error)
+}
+```
+
+## 璇锋眰/鍝嶅簲鎷︽埅鍣�
+
+璇锋眰鎷︽埅鍣ㄤ細鑷姩娣诲姞 baseURL 鍜� headers锛�
+
+```javascript
+// 鍦� src/utils/http.js 涓厤缃�
+const request = axios.create({
+ baseURL: '/api', // 浼氳嚜鍔ㄦ坊鍔犲埌鎵�鏈夎姹傚墠
+ timeout: 30000,
+ headers: {
+ 'Content-Type': 'application/json;charset=UTF-8'
+ }
+})
+```
+
+鍝嶅簲鎷︽埅鍣ㄤ細鑷姩澶勭悊閿欒锛�
+
+```javascript
+// 缁熶竴閿欒鎻愮ず
+ElMessage.error(res.message || '璇锋眰澶辫触')
+
+// 缁熶竴杩斿洖鏍煎紡
+// 鍋囪鍚庣杩斿洖: { code: 200, data: {}, message: '' }
+// 鎷︽埅鍣ㄤ細杩斿洖 res.data
+```
+
+## 浠g悊閰嶇疆
+
+鍦� `vite.config.js` 涓厤缃唬鐞嗭細
+
+```javascript
+server: {
+ port: 3000,
+ proxy: {
+ '/api': {
+ target: 'http://localhost:8080', // 淇敼涓哄疄闄呭悗绔湴鍧�
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, '')
+ }
+ }
+}
+```
+
+## 璁块棶绀轰緥椤甸潰
+
+鍚姩椤圭洰鍚庯紝璁块棶 http://localhost:3000/api-example 鏌ョ湅瀹屾暣鐨凙PI璋冪敤绀轰緥鍜屼氦浜掓紨绀恒��
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/README.md" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/README.md"
new file mode 100644
index 0000000..49b19df
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/README.md"
@@ -0,0 +1,172 @@
+# WMS鐪嬫澘绯荤粺
+
+鍒堕�犱笟WMS浠撳簱绠$悊绯荤粺鐩戞帶鐪嬫澘锛屼娇鐢╒ue3+Vite鏋勫缓锛屾棤闇�鐧诲綍鍗冲彲璁块棶銆�
+
+## 鎶�鏈爤
+
+- Vue 3
+- Vite
+- Vue Router
+- Element Plus
+- ECharts
+- Axios
+- Day.js
+
+## 椤圭洰缁撴瀯
+
+```
+vue-vite-js/
+鈹溾攢鈹� src/
+鈹� 鈹溾攢鈹� api/ # API鎺ュ彛瀹氫箟
+鈹� 鈹溾攢鈹� router/ # 璺敱閰嶇疆
+鈹� 鈹溾攢鈹� utils/ # 宸ュ叿绫�
+鈹� 鈹� 鈹溾攢鈹� http.js # Axios灏佽
+鈹� 鈹� 鈹斺攢鈹� index.js # 閫氱敤宸ュ叿鍑芥暟
+鈹� 鈹溾攢鈹� views/ # 椤甸潰缁勪欢
+鈹� 鈹� 鈹溾攢鈹� Dashboard.vue # 缁煎悎鐪嬫澘
+鈹� 鈹� 鈹溾攢鈹� Warehouse.vue # 浠撳簱鐩戞帶
+鈹� 鈹� 鈹溾攢鈹� Production.vue# 鐢熶骇鐩戞帶
+鈹� 鈹� 鈹斺攢鈹� Inventory.vue # 搴撳瓨棰勮
+鈹� 鈹溾攢鈹� App.vue # 鏍圭粍浠�
+鈹� 鈹斺攢鈹� main.js # 鍏ュ彛鏂囦欢
+鈹溾攢鈹� index.html
+鈹溾攢鈹� vite.config.js
+鈹斺攢鈹� package.json
+```
+
+## 蹇�熷紑濮�
+
+### 1. 瀹夎渚濊禆
+
+```bash
+npm install
+```
+
+### 2. 鍚姩寮�鍙戞湇鍔″櫒
+
+```bash
+npm run dev
+```
+
+璁块棶 http://localhost:3000
+
+### 3. 鏋勫缓鐢熶骇鐗堟湰
+
+```bash
+npm run build
+```
+
+## 鎺ュ彛璋冪敤绀轰緥
+
+椤圭洰涓凡灏佽濂� `http` 宸ュ叿锛屼娇鐢ㄩ潪甯哥畝鍗曪細
+
+```javascript
+import { http } from '@/utils/http'
+
+// GET 璇锋眰
+const getData = async () => {
+ const res = await http.get('/api/list', { page: 1, size: 10 })
+ console.log(res.data)
+}
+
+// POST 璇锋眰
+const postData = async () => {
+ const res = await http.post('/api/create', { name: '娴嬭瘯' })
+ console.log(res.data)
+}
+
+// PUT 璇锋眰
+const updateData = async () => {
+ const res = await http.put('/api/update/1', { name: '鏇存柊' })
+}
+
+// DELETE 璇锋眰
+const deleteData = async () => {
+ const res = await http.delete('/api/delete/1')
+}
+```
+
+## API 缁熶竴绠$悊
+
+鍦� `src/api/index.js` 涓凡缁忓畾涔夊ソ鎵�鏈変笟鍔℃帴鍙o細
+
+```javascript
+import { warehouseApi, inventoryApi, taskApi } from '@/api'
+
+// 浣跨敤绀轰緥
+const fetchData = async () => {
+ // 鑾峰彇浠撳簱鐘舵��
+ const status = await warehouseApi.getWarehouseStatus()
+
+ // 鑾峰彇搴撳瓨鍒楄〃
+ const inventory = await inventoryApi.getInventoryList({ page: 1 })
+
+ // 鑾峰彇浠诲姟鍒楄〃
+ const tasks = await taskApi.getTaskList({ status: '杩涜涓�' })
+}
+```
+
+## 浠g悊閰嶇疆
+
+鍦� `vite.config.js` 涓凡閰嶇疆API浠g悊锛�
+
+```javascript
+server: {
+ port: 3000,
+ proxy: {
+ '/api': {
+ target: 'http://localhost:8080', // 淇敼涓哄疄闄呭悗绔湴鍧�
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, '')
+ }
+ }
+}
+```
+
+## 宸ュ叿鍑芥暟
+
+```javascript
+import { formatDateTime, formatDate, formatTime, formatNumber } from '@/utils'
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+formatDateTime(new Date()) // '2024-12-24 14:30:00'
+
+// 鏍煎紡鍖栨棩鏈�
+formatDate(new Date()) // '2024-12-24'
+
+// 鏍煎紡鍖栨暟瀛�
+formatNumber(12345.67, 2) // '12,345.67'
+```
+
+## 椤甸潰璇存槑
+
+- **缁煎悎鐪嬫澘** - WMS鏁翠綋杩愯惀鏁版嵁姒傝
+- **浠撳簱鐩戞帶** - 浠撳簱鍖哄煙銆佸簱浣嶃�佺幆澧冩俯婀垮害鐩戞帶
+- **鐢熶骇鐩戞帶** - 鐢熶骇绾裤�佽澶囩姸鎬併�佷骇閲忕粺璁�
+- **搴撳瓨棰勮** - 搴撳瓨涓嶈冻銆佺Н鍘嬨�佽繃鏈熼璀�
+
+## 鍝嶅簲寮忔敮鎸�
+
+椤圭洰宸插疄鐜板搷搴斿紡璁捐锛屾敮鎸佷互涓嬪垎杈ㄧ巼锛�
+
+| 鍒嗚鲸鐜囪寖鍥� | 閫傞厤璇存槑 |
+|-----------|---------|
+| 1920px+ | 鏈�浣虫樉绀烘晥鏋滐紝4鍒楀竷灞� |
+| 1600px | 2-3鍒楀竷灞�锛屽瓧浣撳拰闂磋窛閫備腑 |
+| 1366px | 2鍒楀竷灞�涓轰富锛屽浘琛ㄩ珮搴﹁皟鏁� |
+| 1024px | 绱у噾甯冨眬锛岄儴鍒嗗唴瀹规敼涓哄崟鍒� |
+| 768px | 绉诲姩绔�傞厤锛屽崟鍒楀竷灞�锛屼紭鍖栬Е鎽告搷浣� |
+
+**涓昏閫傞厤鍐呭锛�**
+- 缃戞牸甯冨眬鑷�傚簲璋冩暣
+- 瀛椾綋澶у皬鍔ㄦ�佺缉鏀�
+- 闂磋窛鍜屽唴杈硅窛浼樺寲
+- 瀵艰埅鑿滃崟鍦ㄥ皬灞忓箷涓嬭嚜鍔ㄦ崲琛�
+- 琛ㄦ牸鍦ㄧЩ鍔ㄧ鏄剧ず浼樺寲
+- 鍥捐〃楂樺害鑷姩璋冩暣
+
+## 娉ㄦ剰浜嬮」
+
+1. 淇敼 `vite.config.js` 涓殑 `target` 涓哄疄闄呯殑鍚庣API鍦板潃
+2. 鏍规嵁鍚庣杩斿洖鏍煎紡璋冩暣 `src/utils/http.js` 涓殑鍝嶅簲鎷︽埅鍣�
+3. 鎵�鏈夐〉闈㈤兘鍙洿鎺ヨ闂紝鏃犻渶鐧诲綍璁よ瘉
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/index.html" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/index.html"
new file mode 100644
index 0000000..815f58f
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/index.html"
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>WMS鐪嬫澘绯荤粺</title>
+</head>
+<body>
+ <div id="app"></div>
+ <script type="module" src="/src/main.js"></script>
+</body>
+</html>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/package-lock.json" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/package-lock.json"
new file mode 100644
index 0000000..3ec41ba
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/package-lock.json"
@@ -0,0 +1,945 @@
+{
+ "name": "wms-dashboard",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="
+ },
+ "@babel/parser": {
+ "version": "7.28.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
+ "requires": {
+ "@babel/types": "^7.28.5"
+ }
+ },
+ "@babel/types": {
+ "version": "7.28.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
+ "requires": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ }
+ },
+ "@ctrl/tinycolor": {
+ "version": "3.6.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+ "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA=="
+ },
+ "@element-plus/icons-vue": {
+ "version": "2.3.2",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
+ "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A=="
+ },
+ "@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "dev": true,
+ "optional": true
+ },
+ "@floating-ui/core": {
+ "version": "1.7.3",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@floating-ui/core/-/core-1.7.3.tgz",
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "requires": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "@floating-ui/dom": {
+ "version": "1.7.4",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@floating-ui/dom/-/dom-1.7.4.tgz",
+ "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
+ "requires": {
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
+ },
+ "@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=="
+ },
+ "@rollup/rollup-android-arm-eabi": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.54.0.tgz",
+ "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-android-arm64": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.54.0.tgz",
+ "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-darwin-arm64": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.54.0.tgz",
+ "integrity": "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-darwin-x64": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.54.0.tgz",
+ "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-freebsd-arm64": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.54.0.tgz",
+ "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-freebsd-x64": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.54.0.tgz",
+ "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.54.0.tgz",
+ "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.54.0.tgz",
+ "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.54.0.tgz",
+ "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-arm64-musl": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.54.0.tgz",
+ "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.54.0.tgz",
+ "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.54.0.tgz",
+ "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.54.0.tgz",
+ "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.54.0.tgz",
+ "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.54.0.tgz",
+ "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-x64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.54.0.tgz",
+ "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-linux-x64-musl": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.54.0.tgz",
+ "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-openharmony-arm64": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.54.0.tgz",
+ "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.54.0.tgz",
+ "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.54.0.tgz",
+ "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-win32-x64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.54.0.tgz",
+ "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@rollup/rollup-win32-x64-msvc": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.54.0.tgz",
+ "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==",
+ "dev": true,
+ "optional": true
+ },
+ "@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true
+ },
+ "@types/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ=="
+ },
+ "@types/lodash-es": {
+ "version": "4.17.12",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/lodash-es/-/lodash-es-4.17.12.tgz",
+ "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
+ "requires": {
+ "@types/lodash": "*"
+ }
+ },
+ "@types/web-bluetooth": {
+ "version": "0.0.20",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
+ "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
+ },
+ "@vitejs/plugin-vue": {
+ "version": "5.2.4",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+ "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+ "dev": true
+ },
+ "@vue/compiler-core": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/compiler-core/-/compiler-core-3.5.26.tgz",
+ "integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==",
+ "requires": {
+ "@babel/parser": "^7.28.5",
+ "@vue/shared": "3.5.26",
+ "entities": "^7.0.0",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "@vue/compiler-dom": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz",
+ "integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==",
+ "requires": {
+ "@vue/compiler-core": "3.5.26",
+ "@vue/shared": "3.5.26"
+ }
+ },
+ "@vue/compiler-sfc": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz",
+ "integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==",
+ "requires": {
+ "@babel/parser": "^7.28.5",
+ "@vue/compiler-core": "3.5.26",
+ "@vue/compiler-dom": "3.5.26",
+ "@vue/compiler-ssr": "3.5.26",
+ "@vue/shared": "3.5.26",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.21",
+ "postcss": "^8.5.6",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "@vue/compiler-ssr": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz",
+ "integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==",
+ "requires": {
+ "@vue/compiler-dom": "3.5.26",
+ "@vue/shared": "3.5.26"
+ }
+ },
+ "@vue/devtools-api": {
+ "version": "6.6.4",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
+ },
+ "@vue/reactivity": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/reactivity/-/reactivity-3.5.26.tgz",
+ "integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==",
+ "requires": {
+ "@vue/shared": "3.5.26"
+ }
+ },
+ "@vue/runtime-core": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/runtime-core/-/runtime-core-3.5.26.tgz",
+ "integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==",
+ "requires": {
+ "@vue/reactivity": "3.5.26",
+ "@vue/shared": "3.5.26"
+ }
+ },
+ "@vue/runtime-dom": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz",
+ "integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==",
+ "requires": {
+ "@vue/reactivity": "3.5.26",
+ "@vue/runtime-core": "3.5.26",
+ "@vue/shared": "3.5.26",
+ "csstype": "^3.2.3"
+ }
+ },
+ "@vue/server-renderer": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/server-renderer/-/server-renderer-3.5.26.tgz",
+ "integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==",
+ "requires": {
+ "@vue/compiler-ssr": "3.5.26",
+ "@vue/shared": "3.5.26"
+ }
+ },
+ "@vue/shared": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vue/shared/-/shared-3.5.26.tgz",
+ "integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A=="
+ },
+ "@vueuse/core": {
+ "version": "10.11.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vueuse/core/-/core-10.11.1.tgz",
+ "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==",
+ "requires": {
+ "@types/web-bluetooth": "^0.0.20",
+ "@vueuse/metadata": "10.11.1",
+ "@vueuse/shared": "10.11.1",
+ "vue-demi": ">=0.14.8"
+ }
+ },
+ "@vueuse/metadata": {
+ "version": "10.11.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vueuse/metadata/-/metadata-10.11.1.tgz",
+ "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw=="
+ },
+ "@vueuse/shared": {
+ "version": "10.11.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/@vueuse/shared/-/shared-10.11.1.tgz",
+ "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==",
+ "requires": {
+ "vue-demi": ">=0.14.8"
+ }
+ },
+ "async-validator": {
+ "version": "4.2.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/async-validator/-/async-validator-4.2.5.tgz",
+ "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "axios": {
+ "version": "1.13.2",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
+ "requires": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "requires": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "csstype": {
+ "version": "3.2.3",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="
+ },
+ "dayjs": {
+ "version": "1.11.19",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/dayjs/-/dayjs-1.11.19.tgz",
+ "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+ },
+ "dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "requires": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ }
+ },
+ "echarts": {
+ "version": "5.6.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/echarts/-/echarts-5.6.0.tgz",
+ "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
+ "requires": {
+ "tslib": "2.3.0",
+ "zrender": "5.6.1"
+ }
+ },
+ "element-plus": {
+ "version": "2.13.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/element-plus/-/element-plus-2.13.0.tgz",
+ "integrity": "sha512-qjxS+SBChvqCl6lU6ShiliLMN6WqFHiXQENYbAY3GKNflG+FS3jqn8JmQq0CBZq4koFqsi95NT1M6SL4whZfrA==",
+ "requires": {
+ "@ctrl/tinycolor": "^3.4.1",
+ "@element-plus/icons-vue": "^2.3.2",
+ "@floating-ui/dom": "^1.0.1",
+ "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
+ "@types/lodash": "^4.17.20",
+ "@types/lodash-es": "^4.17.12",
+ "@vueuse/core": "^10.11.0",
+ "async-validator": "^4.2.5",
+ "dayjs": "^1.11.19",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "lodash-unified": "^1.0.3",
+ "memoize-one": "^6.0.0",
+ "normalize-wheel-es": "^1.2.0"
+ }
+ },
+ "entities": {
+ "version": "7.0.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/entities/-/entities-7.0.0.tgz",
+ "integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ=="
+ },
+ "es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
+ },
+ "es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
+ },
+ "es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "requires": {
+ "es-errors": "^1.3.0"
+ }
+ },
+ "es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "requires": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ }
+ },
+ "esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "requires": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+ },
+ "follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="
+ },
+ "form-data": {
+ "version": "4.0.5",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+ },
+ "get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "requires": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ }
+ },
+ "get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "requires": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ }
+ },
+ "gopd": {
+ "version": "1.2.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="
+ },
+ "has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
+ },
+ "has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "requires": {
+ "has-symbols": "^1.0.3"
+ }
+ },
+ "hasown": {
+ "version": "2.0.2",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "requires": {
+ "function-bind": "^1.1.2"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "lodash-es": {
+ "version": "4.17.22",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/lodash-es/-/lodash-es-4.17.22.tgz",
+ "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q=="
+ },
+ "lodash-unified": {
+ "version": "1.0.3",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/lodash-unified/-/lodash-unified-1.0.3.tgz",
+ "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ=="
+ },
+ "magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "requires": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
+ },
+ "memoize-one": {
+ "version": "6.0.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/memoize-one/-/memoize-one-6.0.0.tgz",
+ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+ },
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+ },
+ "mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
+ "nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
+ },
+ "normalize-wheel-es": {
+ "version": "1.2.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+ "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
+ },
+ "picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+ },
+ "postcss": {
+ "version": "8.5.6",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "requires": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
+ "rollup": {
+ "version": "4.54.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/rollup/-/rollup-4.54.0.tgz",
+ "integrity": "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==",
+ "dev": true,
+ "requires": {
+ "@rollup/rollup-android-arm-eabi": "4.54.0",
+ "@rollup/rollup-android-arm64": "4.54.0",
+ "@rollup/rollup-darwin-arm64": "4.54.0",
+ "@rollup/rollup-darwin-x64": "4.54.0",
+ "@rollup/rollup-freebsd-arm64": "4.54.0",
+ "@rollup/rollup-freebsd-x64": "4.54.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.54.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.54.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.54.0",
+ "@rollup/rollup-linux-arm64-musl": "4.54.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.54.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.54.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.54.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.54.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.54.0",
+ "@rollup/rollup-linux-x64-gnu": "4.54.0",
+ "@rollup/rollup-linux-x64-musl": "4.54.0",
+ "@rollup/rollup-openharmony-arm64": "4.54.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.54.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.54.0",
+ "@rollup/rollup-win32-x64-gnu": "4.54.0",
+ "@rollup/rollup-win32-x64-msvc": "4.54.0",
+ "@types/estree": "1.0.8",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
+ },
+ "tslib": {
+ "version": "2.3.0",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/tslib/-/tslib-2.3.0.tgz",
+ "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+ },
+ "vite": {
+ "version": "5.4.21",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/vite/-/vite-5.4.21.tgz",
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
+ "dev": true,
+ "requires": {
+ "esbuild": "^0.21.3",
+ "fsevents": "~2.3.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ }
+ },
+ "vue": {
+ "version": "3.5.26",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/vue/-/vue-3.5.26.tgz",
+ "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==",
+ "requires": {
+ "@vue/compiler-dom": "3.5.26",
+ "@vue/compiler-sfc": "3.5.26",
+ "@vue/runtime-dom": "3.5.26",
+ "@vue/server-renderer": "3.5.26",
+ "@vue/shared": "3.5.26"
+ }
+ },
+ "vue-demi": {
+ "version": "0.14.10",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="
+ },
+ "vue-router": {
+ "version": "4.6.4",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/vue-router/-/vue-router-4.6.4.tgz",
+ "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
+ "requires": {
+ "@vue/devtools-api": "^6.6.4"
+ }
+ },
+ "zrender": {
+ "version": "5.6.1",
+ "resolved": "https://mirrors.huaweicloud.com/repository/npm/zrender/-/zrender-5.6.1.tgz",
+ "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
+ "requires": {
+ "tslib": "2.3.0"
+ }
+ }
+ }
+}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/package.json" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/package.json"
new file mode 100644
index 0000000..c86bf53
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/package.json"
@@ -0,0 +1,24 @@
+{
+ "name": "wms-dashboard",
+ "version": "1.0.0",
+ "type": "module",
+ "description": "鍒堕�犱笟WMS鐪嬫澘鍙婂ぇ灞忓睍绀虹郴缁�",
+ "scripts": {
+ "dev": "vite --host",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "vue": "^3.4.21",
+ "vue-router": "^4.3.0",
+ "axios": "^1.6.8",
+ "element-plus": "^2.7.0",
+ "@element-plus/icons-vue": "^2.3.1",
+ "echarts": "^5.5.0",
+ "dayjs": "^1.11.10"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^5.0.4",
+ "vite": "^5.2.0"
+ }
+}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/App.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/App.vue"
new file mode 100644
index 0000000..067d968
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/App.vue"
@@ -0,0 +1,28 @@
+<template>
+ <div id="app">
+ <router-view />
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'App'
+}
+</script>
+
+<style>
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+html, body, #app {
+ width: 100%;
+ height: 100%;
+ font-family: 'Microsoft YaHei', Arial, sans-serif;
+ background: #0a0e27;
+ color: #fff;
+ overflow: hidden;
+}
+</style>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/api/index.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/api/index.js"
new file mode 100644
index 0000000..d93a7ed
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/api/index.js"
@@ -0,0 +1,143 @@
+/**
+ * API 鎺ュ彛缁熶竴绠$悊
+ * 鎵�鏈夋帴鍙i兘鍦ㄨ繖閲屽畾涔夛紝鏂逛究缁存姢
+ */
+import { http } from '@/utils/http'
+
+// ==================== 鐢ㄦ埛鐩稿叧 ====================
+export const userApi = {
+ // 鑾峰彇鐢ㄦ埛淇℃伅
+ getUserInfo: () => http.get('/user/info'),
+
+ // 鑾峰彇鐢ㄦ埛鍒楄〃
+ getUserList: (params) => http.get('/user/list', params)
+}
+
+// ==================== 浠撳簱鐩稿叧 ====================
+export const warehouseApi = {
+ // 鑾峰彇浠撳簱鐘舵�佹瑙�
+ getWarehouseStatus: () => http.get('/wms/warehouse/status'),
+
+ // 鑾峰彇浠撳簱鍖哄煙淇℃伅
+ getAreas: () => http.get('/wms/warehouse/areas'),
+
+ // 鑾峰彇搴撲綅淇℃伅
+ getLocations: (params) => http.get('/wms/warehouse/locations', params),
+
+ // 鑾峰彇娓╂箍搴︽暟鎹�
+ getEnvData: () => http.get('/wms/warehouse/env')
+}
+
+// ==================== 搴撳瓨鐩稿叧 ====================
+export const inventoryApi = {
+ // 鑾峰彇搴撳瓨姒傝
+ getInventoryOverview: () => http.get('/wms/inventory/overview'),
+
+ // 鑾峰彇搴撳瓨鍒楄〃
+ getInventoryList: (params) => http.get('/wms/inventory/list', params),
+
+ // 搴撳瓨棰勮鍒楄〃
+ getLowStockAlerts: (params) => http.get('/wms/inventory/low-stock', params),
+
+ // 搴撳瓨绉帇鍒楄〃
+ getOverStockAlerts: (params) => http.get('/wms/inventory/over-stock', params),
+
+ // 鍗冲皢杩囨湡鐗╂枡
+ getExpiringItems: (params) => http.get('/wms/inventory/expiring', params),
+
+ // 搴撳瓨鍛ㄨ浆鐜�
+ getTurnoverRate: (params) => http.get('/wms/inventory/turnover', params),
+
+ // ABC鍒嗙被缁熻
+ getABCStats: () => http.get('/wms/inventory/abc-stats')
+}
+
+// ==================== 浣滀笟浠诲姟鐩稿叧 ====================
+export const taskApi = {
+ // 鑾峰彇浠诲姟鍒楄〃
+ getTaskList: (params) => http.get('/wms/task/list', params),
+
+ // 鍒涘缓浠诲姟
+ createTask: (data) => http.post('/wms/task/create', data),
+
+ // 鏇存柊浠诲姟鐘舵��
+ updateTaskStatus: (taskId, data) => http.put(`/wms/task/${taskId}/status`, data),
+
+ // 鑾峰彇浠诲姟璇︽儏
+ getTaskDetail: (taskId) => http.get(`/wms/task/${taskId}`)
+}
+
+// ==================== 鍑哄叆搴撶浉鍏� ====================
+export const ioApi = {
+ // 鍏ュ簱鍗曞垪琛�
+ getInboundList: (params) => http.get('/wms/inbound/list', params),
+
+ // 鍑哄簱鍗曞垪琛�
+ getOutboundList: (params) => http.get('/wms/outbound/list', params),
+
+ // 鍒涘缓鍏ュ簱鍗�
+ createInbound: (data) => http.post('/wms/inbound/create', data),
+
+ // 鍒涘缓鍑哄簱鍗�
+ createOutbound: (data) => http.post('/wms/outbound/create', data),
+
+ // 鍑哄叆搴撶粺璁�
+ getIOStats: (params) => http.get('/wms/io/stats', params)
+}
+
+// ==================== 鐢熶骇鐩稿叧 ====================
+export const productionApi = {
+ // 鑾峰彇鐢熶骇绾跨姸鎬�
+ getProductionLines: () => http.get('/wms/production/lines'),
+
+ // 鑾峰彇璁惧鐘舵��
+ getDeviceStatus: (lineId) => http.get(`/wms/production/line/${lineId}/devices`),
+
+ // 鑾峰彇鐢熶骇浠诲姟鍒楄〃
+ getProductionTasks: (params) => http.get('/wms/production/tasks', params),
+
+ // 浜ч噺缁熻
+ getProductionStats: (params) => http.get('/wms/production/stats', params),
+
+ // 鑹搧鐜囩粺璁�
+ getQualityStats: (params) => http.get('/wms/production/quality', params),
+
+ // 璁惧OEE
+ getDeviceOEE: (params) => http.get('/wms/production/oee', params)
+}
+
+// ==================== 鎶ヨ〃鐩稿叧 ====================
+export const reportApi = {
+ // 缁煎悎鐪嬫澘鏁版嵁
+ getDashboardData: () => http.get('/wms/report/dashboard'),
+
+ // 鍑哄叆搴撹秼鍔�
+ getTrendData: (params) => http.get('/wms/report/trend', params),
+
+ // 鍒嗙被鍗犳瘮
+ getCategoryStats: () => http.get('/wms/report/category'),
+
+ // 浣滀笟鏁堢巼缁熻
+ getEfficiencyStats: (params) => http.get('/wms/report/efficiency', params)
+}
+
+// ==================== 鐗╂枡鐩稿叧 ====================
+export const materialApi = {
+ // 鑾峰彇鐗╂枡鍒楄〃
+ getMaterialList: (params) => http.get('/wms/material/list', params),
+
+ // 鑾峰彇鐗╂枡璇︽儏
+ getMaterialDetail: (materialId) => http.get(`/wms/material/${materialId}`),
+
+ // 鑾峰彇鐗╂枡搴撳瓨鍘嗗彶
+ getMaterialHistory: (materialId, params) => http.get(`/wms/material/${materialId}/history`, params)
+}
+
+// ==================== 绯荤粺閰嶇疆鐩稿叧 ====================
+export const configApi = {
+ // 鑾峰彇绯荤粺閰嶇疆
+ getConfig: () => http.get('/wms/system/config'),
+
+ // 鏇存柊绯荤粺閰嶇疆
+ updateConfig: (data) => http.put('/wms/system/config', data)
+}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/examples/ApiExample.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/examples/ApiExample.vue"
new file mode 100644
index 0000000..3657616
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/examples/ApiExample.vue"
@@ -0,0 +1,618 @@
+<template>
+ <div class="api-example-container">
+ <div class="header">
+ <h1 class="title">API璋冪敤绀轰緥</h1>
+ <p class="subtitle">灞曠ず濡備綍浣跨敤灏佽濂界殑http宸ュ叿鍜宎pi妯″潡璋冪敤鍚庣鎺ュ彛</p>
+ </div>
+
+ <div class="content">
+ <!-- 绀轰緥1: 鍩虹GET璇锋眰 -->
+ <div class="example-section">
+ <div class="section-title">
+ <el-icon><Document /></el-icon>
+ <span>绀轰緥1: 鍩虹GET璇锋眰</span>
+ </div>
+ <div class="code-block">
+ <pre><code>// 鏂瑰紡涓�锛氫娇鐢� http 宸ュ叿鐩存帴璋冪敤
+import { http } from '@/utils/http'
+
+const fetchData = async () => {
+ try {
+ const res = await http.get('/api/user/list', { page: 1, pageSize: 10 })
+ console.log('杩斿洖鏁版嵁:', res.data)
+ } catch (error) {
+ console.error('璇锋眰澶辫触:', error)
+ }
+}
+
+// 鏂瑰紡浜岋細浣跨敤灏佽濂界殑api妯″潡
+import { warehouseApi } from '@/api'
+
+const fetchWarehouse = async () => {
+ try {
+ const res = await warehouseApi.getWarehouseStatus()
+ console.log('浠撳簱鐘舵��:', res.data)
+ } catch (error) {
+ console.error('璇锋眰澶辫触:', error)
+ }
+}</code></pre>
+ </div>
+ <el-button type="primary" @click="example1" :loading="loading1">
+ 杩愯绀轰緥1
+ </el-button>
+ <div v-if="result1" class="result-box">
+ <div class="result-title">杩斿洖缁撴灉:</div>
+ <pre>{{ JSON.stringify(result1, null, 2) }}</pre>
+ </div>
+ </div>
+
+ <!-- 绀轰緥2: POST璇锋眰 -->
+ <div class="example-section">
+ <div class="section-title">
+ <el-icon><Document /></el-icon>
+ <span>绀轰緥2: POST璇锋眰锛堝垱寤烘暟鎹級</span>
+ </div>
+ <div class="code-block">
+ <pre><code>// 浣跨敤 http 宸ュ叿鍙戦�丳OST璇锋眰
+import { http } from '@/utils/http'
+
+const createData = async () => {
+ try {
+ const res = await http.post('/api/task/create', {
+ taskNo: 'RK001',
+ type: '鍏ュ簱',
+ material: '閽㈡澘',
+ quantity: 100
+ })
+ console.log('鍒涘缓鎴愬姛:', res.data)
+ return res.data
+ } catch (error) {
+ console.error('鍒涘缓澶辫触:', error)
+ }
+}
+
+// 浣跨敤灏佽鐨刟pi
+import { taskApi } from '@/api'
+
+const createTask = async () => {
+ const res = await taskApi.createTask({
+ taskNo: 'RK001',
+ type: '鍏ュ簱',
+ material: '閽㈡澘',
+ quantity: 100
+ })
+ return res.data
+}</code></pre>
+ </div>
+ <el-button type="success" @click="example2" :loading="loading2">
+ 杩愯绀轰緥2
+ </el-button>
+ <div v-if="result2" class="result-box">
+ <div class="result-title">杩斿洖缁撴灉:</div>
+ <pre>{{ JSON.stringify(result2, null, 2) }}</pre>
+ </div>
+ </div>
+
+ <!-- 绀轰緥3: PUT/DELETE璇锋眰 -->
+ <div class="example-section">
+ <div class="section-title">
+ <el-icon><Document /></el-icon>
+ <span>绀轰緥3: PUT/DELETE璇锋眰</span>
+ </div>
+ <div class="code-block">
+ <pre><code>// PUT璇锋眰 - 鏇存柊鏁版嵁
+const updateTask = async (taskId) => {
+ const res = await http.put(`/api/task/${taskId}`, {
+ status: '宸插畬鎴�'
+ })
+ return res.data
+}
+
+// DELETE璇锋眰 - 鍒犻櫎鏁版嵁
+const deleteTask = async (taskId) => {
+ const res = await http.delete(`/api/task/${taskId}`)
+ return res.data
+}
+
+// 浣跨敤api妯″潡
+import { taskApi } from '@/api'
+
+// 鏇存柊浠诲姟鐘舵��
+await taskApi.updateTaskStatus('TASK001', { status: '宸插畬鎴�' })
+
+// 鑾峰彇浠诲姟璇︽儏
+const detail = await taskApi.getTaskDetail('TASK001')</code></pre>
+ </div>
+ </div>
+
+ <!-- 绀轰緥4: 瀹為檯涓氬姟鍦烘櫙 -->
+ <div class="example-section">
+ <div class="section-title">
+ <el-icon><Document /></el-icon>
+ <span>绀轰緥4: 瀹為檯涓氬姟鍦烘櫙 - 缁勪欢涓皟鐢ˋPI</span>
+ </div>
+ <div class="code-block">
+ <pre><code>// 鍦╒ue缁勪欢涓娇鐢�
+import { ref, onMounted } from 'vue'
+import { warehouseApi, inventoryApi } from '@/api'
+
+export default {
+ setup() {
+ const loading = ref(false)
+ const warehouseList = ref([])
+ const inventoryStats = ref({})
+
+ // 鑾峰彇浠撳簱鍒楄〃
+ const fetchWarehouseList = async () => {
+ loading.value = true
+ try {
+ const res = await warehouseApi.getAreas()
+ warehouseList.value = res.data
+ } catch (error) {
+ ElMessage.error('鑾峰彇浠撳簱鍒楄〃澶辫触')
+ } finally {
+ loading.value = false
+ }
+ }
+
+ // 鑾峰彇搴撳瓨缁熻
+ const fetchInventoryStats = async () => {
+ try {
+ const res = await inventoryApi.getInventoryOverview()
+ inventoryStats.value = res.data
+ } catch (error) {
+ console.error('鑾峰彇搴撳瓨缁熻澶辫触:', error)
+ }
+ }
+
+ // 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+ onMounted(() => {
+ fetchWarehouseList()
+ fetchInventoryStats()
+ })
+
+ return {
+ loading,
+ warehouseList,
+ inventoryStats,
+ fetchWarehouseList
+ }
+ }
+}</code></pre>
+ </div>
+ </div>
+
+ <!-- 绀轰緥5: 骞跺彂璇锋眰 -->
+ <div class="example-section">
+ <div class="section-title">
+ <el-icon><Document /></el-icon>
+ <span>绀轰緥5: 骞跺彂璇锋眰锛堜娇鐢≒romise.all锛�</span>
+ </div>
+ <div class="code-block">
+ <pre><code>// 鍚屾椂鍙戣捣澶氫釜璇锋眰
+import { http } from '@/utils/http'
+
+const fetchDashboardData = async () => {
+ try {
+ const [warehouseRes, inventoryRes, taskRes] = await Promise.all([
+ http.get('/api/warehouse/status'),
+ http.get('/api/inventory/overview'),
+ http.get('/api/task/list', { status: '杩涜涓�' })
+ ])
+
+ return {
+ warehouse: warehouseRes.data,
+ inventory: inventoryRes.data,
+ tasks: taskRes.data
+ }
+ } catch (error) {
+ console.error('鑾峰彇鐪嬫澘鏁版嵁澶辫触:', error)
+ }
+}
+
+// 浣跨敤api妯″潡
+import { warehouseApi, inventoryApi, taskApi } from '@/api'
+
+const fetchAllData = async () => {
+ const [warehouse, inventory, tasks] = await Promise.all([
+ warehouseApi.getWarehouseStatus(),
+ inventoryApi.getInventoryOverview(),
+ taskApi.getTaskList({ status: '杩涜涓�' })
+ ])
+
+ return { warehouse, inventory, tasks }
+}</code></pre>
+ </div>
+ <el-button type="warning" @click="example5" :loading="loading5">
+ 杩愯绀轰緥5锛堝苟鍙戣姹傦級
+ </el-button>
+ <div v-if="result5" class="result-box">
+ <div class="result-title">杩斿洖缁撴灉:</div>
+ <pre>{{ JSON.stringify(result5, null, 2) }}</pre>
+ </div>
+ </div>
+
+ <!-- 瀹為檯婕旂ず -->
+ <div class="example-section">
+ <div class="section-title">
+ <el-icon><Monitor /></el-icon>
+ <span>瀹為檯婕旂ず</span>
+ </div>
+ <div class="demo-buttons">
+ <el-button @click="fetchWarehouse" :loading="demoLoading.warehouse">
+ <el-icon><Box /></el-icon>
+ 鑾峰彇浠撳簱鐘舵��
+ </el-button>
+ <el-button @click="fetchInventory" :loading="demoLoading.inventory">
+ <el-icon><List /></el-icon>
+ 鑾峰彇搴撳瓨鍒楄〃
+ </el-button>
+ <el-button @click="fetchTasks" :loading="demoLoading.tasks">
+ <el-icon><Document /></el-icon>
+ 鑾峰彇浠诲姟鍒楄〃
+ </el-button>
+ <el-button @click="fetchDashboard" :loading="demoLoading.dashboard">
+ <el-icon><DataBoard /></el-icon>
+ 鑾峰彇鐪嬫澘鏁版嵁锛堝苟鍙戯級
+ </el-button>
+ </div>
+
+ <div v-if="demoResult" class="result-box large">
+ <div class="result-title">API杩斿洖鏁版嵁:</div>
+ <pre>{{ JSON.stringify(demoResult, null, 2) }}</pre>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import { http } from '@/utils/http'
+import { warehouseApi, inventoryApi, taskApi, reportApi } from '@/api'
+
+export default {
+ name: 'ApiExample',
+ setup() {
+ const loading1 = ref(false)
+ const loading2 = ref(false)
+ const loading5 = ref(false)
+ const result1 = ref(null)
+ const result2 = ref(null)
+ const result5 = ref(null)
+
+ const demoLoading = ref({
+ warehouse: false,
+ inventory: false,
+ tasks: false,
+ dashboard: false
+ })
+ const demoResult = ref(null)
+
+ // 绀轰緥1: GET璇锋眰
+ const example1 = async () => {
+ loading1.value = true
+ result1.value = null
+ try {
+ // 妯℃嫙API璋冪敤
+ // 瀹為檯浣跨敤鏃舵崲鎴愮湡瀹炵殑API
+ const res = await new Promise(resolve => {
+ setTimeout(() => {
+ resolve({
+ code: 200,
+ data: {
+ total: 100,
+ list: [
+ { id: 1, name: '浠撳簱A', capacity: 1000, used: 600 },
+ { id: 2, name: '浠撳簱B', capacity: 800, used: 400 }
+ ]
+ }
+ })
+ }, 1000)
+ })
+ result1.value = res.data
+ ElMessage.success('GET璇锋眰鎴愬姛')
+ } catch (error) {
+ ElMessage.error('璇锋眰澶辫触: ' + error.message)
+ } finally {
+ loading1.value = false
+ }
+ }
+
+ // 绀轰緥2: POST璇锋眰
+ const example2 = async () => {
+ loading2.value = true
+ result2.value = null
+ try {
+ const res = await new Promise(resolve => {
+ setTimeout(() => {
+ resolve({
+ code: 200,
+ data: {
+ id: 'TASK' + Date.now(),
+ status: 'success',
+ message: '鍒涘缓鎴愬姛'
+ }
+ })
+ }, 1000)
+ })
+ result2.value = res.data
+ ElMessage.success('POST璇锋眰鎴愬姛')
+ } catch (error) {
+ ElMessage.error('璇锋眰澶辫触: ' + error.message)
+ } finally {
+ loading2.value = false
+ }
+ }
+
+ // 绀轰緥5: 骞跺彂璇锋眰
+ const example5 = async () => {
+ loading5.value = true
+ result5.value = null
+ try {
+ // 妯℃嫙骞跺彂璇锋眰
+ const [res1, res2, res3] = await Promise.all([
+ new Promise(resolve => setTimeout(() => resolve({ code: 200, data: { warehouse: '姝e父' } }), 800)),
+ new Promise(resolve => setTimeout(() => resolve({ code: 200, data: { inventory: 12580 } }), 600)),
+ new Promise(resolve => setTimeout(() => resolve({ code: 200, data: { tasks: 48 } }), 1000))
+ ])
+
+ result5.value = {
+ warehouse: res1.data,
+ inventory: res2.data,
+ tasks: res3.data
+ }
+ ElMessage.success('骞跺彂璇锋眰鎴愬姛')
+ } catch (error) {
+ ElMessage.error('璇锋眰澶辫触: ' + error.message)
+ } finally {
+ loading5.value = false
+ }
+ }
+
+ // 瀹為檯婕旂ず - 鑾峰彇浠撳簱鐘舵��
+ const fetchWarehouse = async () => {
+ demoLoading.value.warehouse = true
+ demoResult.value = null
+ try {
+ // 瀹為檯浣跨敤鏃惰皟鐢ㄧ湡瀹炴帴鍙�
+ // const res = await warehouseApi.getWarehouseStatus()
+
+ // 妯℃嫙鏁版嵁
+ const res = {
+ code: 200,
+ data: {
+ totalAreas: 4,
+ totalPositions: 11000,
+ usedPositions: 7700,
+ utilization: 70
+ }
+ }
+ demoResult.value = res
+ ElMessage.success('鑾峰彇浠撳簱鐘舵�佹垚鍔�')
+ } catch (error) {
+ ElMessage.error('鑾峰彇浠撳簱鐘舵�佸け璐�')
+ } finally {
+ demoLoading.value.warehouse = false
+ }
+ }
+
+ // 鑾峰彇搴撳瓨鍒楄〃
+ const fetchInventory = async () => {
+ demoLoading.value.inventory = true
+ demoResult.value = null
+ try {
+ const res = {
+ code: 200,
+ data: {
+ total: 12580,
+ items: [
+ { code: 'M001', name: '閽㈡澘', quantity: 5000 },
+ { code: 'M002', name: '閾濇澘', quantity: 3000 },
+ { code: 'M003', name: '铻轰笣', quantity: 4580 }
+ ]
+ }
+ }
+ demoResult.value = res
+ ElMessage.success('鑾峰彇搴撳瓨鍒楄〃鎴愬姛')
+ } catch (error) {
+ ElMessage.error('鑾峰彇搴撳瓨鍒楄〃澶辫触')
+ } finally {
+ demoLoading.value.inventory = false
+ }
+ }
+
+ // 鑾峰彇浠诲姟鍒楄〃
+ const fetchTasks = async () => {
+ demoLoading.value.tasks = true
+ demoResult.value = null
+ try {
+ const res = {
+ code: 200,
+ data: {
+ total: 48,
+ list: [
+ { taskNo: 'RK001', type: '鍏ュ簱', status: '杩涜涓�' },
+ { taskNo: 'CK001', type: '鍑哄簱', status: '宸插畬鎴�' },
+ { taskNo: 'RK002', type: '鍏ュ簱', status: '寰呭鐞�' }
+ ]
+ }
+ }
+ demoResult.value = res
+ ElMessage.success('鑾峰彇浠诲姟鍒楄〃鎴愬姛')
+ } catch (error) {
+ ElMessage.error('鑾峰彇浠诲姟鍒楄〃澶辫触')
+ } finally {
+ demoLoading.value.tasks = false
+ }
+ }
+
+ // 骞跺彂鑾峰彇鐪嬫澘鏁版嵁
+ const fetchDashboard = async () => {
+ demoLoading.value.dashboard = true
+ demoResult.value = null
+ try {
+ // 瀹為檯浣跨敤鏃朵娇鐢ㄥ苟鍙戣姹�
+ // const [warehouse, inventory, tasks] = await Promise.all([
+ // warehouseApi.getWarehouseStatus(),
+ // inventoryApi.getInventoryOverview(),
+ // taskApi.getTaskList({ status: '杩涜涓�' })
+ // ])
+
+ // 妯℃嫙鏁版嵁
+ const res = {
+ code: 200,
+ data: {
+ warehouse: { totalAreas: 4, utilization: 70 },
+ inventory: { total: 12580, lowStock: 8 },
+ tasks: { total: 48, inProgress: 15 }
+ }
+ }
+ demoResult.value = res
+ ElMessage.success('鑾峰彇鐪嬫澘鏁版嵁鎴愬姛')
+ } catch (error) {
+ ElMessage.error('鑾峰彇鐪嬫澘鏁版嵁澶辫触')
+ } finally {
+ demoLoading.value.dashboard = false
+ }
+ }
+
+ return {
+ loading1,
+ loading2,
+ loading5,
+ result1,
+ result2,
+ result5,
+ demoLoading,
+ demoResult,
+ example1,
+ example2,
+ example5,
+ fetchWarehouse,
+ fetchInventory,
+ fetchTasks,
+ fetchDashboard
+ }
+ }
+}
+</script>
+
+<style scoped>
+.api-example-container {
+ width: 100%;
+ min-height: 100vh;
+ max-height: 100vh;
+ padding: 20px;
+ padding-bottom: 50px;
+ background: #0a0e27;
+ color: #fff;
+ overflow-y: auto;
+ box-sizing: border-box;
+}
+
+.header {
+ text-align: center;
+ margin-bottom: 30px;
+ padding: 30px;
+ background: linear-gradient(135deg, rgba(79, 172, 254, 0.1) 0%, rgba(0, 242, 254, 0.1) 100%);
+ border-radius: 10px;
+ border: 1px solid rgba(79, 172, 254, 0.2);
+}
+
+.title {
+ font-size: 32px;
+ font-weight: bold;
+ background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ margin-bottom: 10px;
+}
+
+.subtitle {
+ font-size: 16px;
+ color: rgba(255, 255, 255, 0.6);
+}
+
+.content {
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.example-section {
+ background: rgba(255, 255, 255, 0.03);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+ padding: 20px;
+ margin-bottom: 20px;
+}
+
+.section-title {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ font-size: 18px;
+ font-weight: bold;
+ color: #4facfe;
+ margin-bottom: 15px;
+}
+
+.code-block {
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 8px;
+ padding: 15px;
+ margin-bottom: 15px;
+ overflow-x: auto;
+}
+
+.code-block pre {
+ margin: 0;
+ font-size: 13px;
+ line-height: 1.6;
+}
+
+.code-block code {
+ color: #e6a23c;
+ font-family: 'Courier New', monospace;
+}
+
+.result-box {
+ margin-top: 15px;
+ padding: 15px;
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(103, 194, 58, 0.3);
+ border-radius: 8px;
+}
+
+.result-box.large {
+ max-height: 400px;
+ overflow-y: auto;
+}
+
+.result-title {
+ font-size: 14px;
+ font-weight: bold;
+ color: #67c23a;
+ margin-bottom: 10px;
+}
+
+.result-box pre {
+ margin: 0;
+ font-size: 12px;
+ line-height: 1.5;
+ color: #fff;
+ overflow-x: auto;
+}
+
+.demo-buttons {
+ display: flex;
+ gap: 10px;
+ flex-wrap: wrap;
+}
+
+:deep(.el-button) {
+ margin: 0;
+}
+</style>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/main.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/main.js"
new file mode 100644
index 0000000..e28ee26
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/main.js"
@@ -0,0 +1,17 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+
+const app = createApp(App)
+
+// 娉ㄥ唽鎵�鏈夊浘鏍�
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+ app.component(key, component)
+}
+
+app.use(ElementPlus)
+app.use(router)
+app.mount('#app')
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/router/index.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/router/index.js"
new file mode 100644
index 0000000..a9eeb2e
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/router/index.js"
@@ -0,0 +1,45 @@
+import { createRouter, createWebHistory } from 'vue-router'
+
+const routes = [
+ {
+ path: '/',
+ redirect: '/dashboard'
+ },
+ {
+ path: '/dashboard',
+ name: 'Dashboard',
+ component: () => import('@/views/Dashboard.vue'),
+ meta: { title: 'WMS缁煎悎鐪嬫澘' }
+ },
+ {
+ path: '/warehouse',
+ name: 'Warehouse',
+ component: () => import('@/views/Warehouse.vue'),
+ meta: { title: '浠撳簱鐩戞帶' }
+ },
+ {
+ path: '/production',
+ name: 'Production',
+ component: () => import('@/views/Production.vue'),
+ meta: { title: '鐢熶骇鐩戞帶' }
+ },
+ {
+ path: '/inventory',
+ name: 'Inventory',
+ component: () => import('@/views/Inventory.vue'),
+ meta: { title: '搴撳瓨棰勮' }
+ },
+ {
+ path: '/api-example',
+ name: 'ApiExample',
+ component: () => import('@/examples/ApiExample.vue'),
+ meta: { title: 'API璋冪敤绀轰緥' }
+ }
+]
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes
+})
+
+export default router
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/utils/http.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/utils/http.js"
new file mode 100644
index 0000000..c6118ff
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/utils/http.js"
@@ -0,0 +1,107 @@
+import axios from 'axios'
+import { ElMessage } from 'element-plus'
+
+// 鍒涘缓axios瀹炰緥
+const request = axios.create({
+ baseURL: '/api',
+ timeout: 30000,
+ headers: {
+ 'Content-Type': 'application/json;charset=UTF-8'
+ }
+})
+
+// 璇锋眰鎷︽埅鍣�
+request.interceptors.request.use(
+ config => {
+ // 鍙互鍦ㄨ繖閲屾坊鍔爐oken绛夎璇佷俊鎭�
+ // const token = localStorage.getItem('token')
+ // if (token) {
+ // config.headers['Authorization'] = `Bearer ${token}`
+ // }
+ return config
+ },
+ error => {
+ console.error('璇锋眰閿欒:', error)
+ return Promise.reject(error)
+ }
+)
+
+// 鍝嶅簲鎷︽埅鍣�
+request.interceptors.response.use(
+ response => {
+ const res = response.data
+
+ // 鏍规嵁瀹為檯鍚庣杩斿洖鏍煎紡璋冩暣
+ // 鍋囪鍚庣杩斿洖鏍煎紡涓� { code: 200, data: {}, message: '' }
+ if (res.code !== undefined && res.code !== 200) {
+ ElMessage.error(res.message || '璇锋眰澶辫触')
+ return Promise.reject(new Error(res.message || '璇锋眰澶辫触'))
+ }
+
+ return res
+ },
+ error => {
+ console.error('鍝嶅簲閿欒:', error)
+
+ let message = '缃戠粶閿欒'
+ if (error.response) {
+ switch (error.response.status) {
+ case 400:
+ message = '璇锋眰閿欒'
+ break
+ case 401:
+ message = '鏈巿鏉冿紝璇烽噸鏂扮櫥褰�'
+ break
+ case 403:
+ message = '鎷掔粷璁块棶'
+ break
+ case 404:
+ message = '璇锋眰鍦板潃涓嶅瓨鍦�'
+ break
+ case 500:
+ message = '鏈嶅姟鍣ㄥ唴閮ㄩ敊璇�'
+ break
+ default:
+ message = error.response.data?.message || '璇锋眰澶辫触'
+ }
+ } else if (error.request) {
+ message = '缃戠粶杩炴帴澶辫触'
+ }
+
+ ElMessage.error(message)
+ return Promise.reject(error)
+ }
+)
+
+// 瀵煎嚭甯哥敤鐨勮姹傛柟娉�
+export const http = {
+ get(url, params, config = {}) {
+ return request.get(url, { params, ...config })
+ },
+
+ post(url, data, config = {}) {
+ return request.post(url, data, config)
+ },
+
+ put(url, data, config = {}) {
+ return request.put(url, data, config)
+ },
+
+ delete(url, params, config = {}) {
+ return request.delete(url, { params, ...config })
+ },
+
+ // 鐢ㄤ簬鏂囦欢涓婁紶
+ upload(url, file, config = {}) {
+ const formData = new FormData()
+ formData.append('file', file)
+ return request.post(url, formData, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ },
+ ...config
+ })
+ }
+}
+
+export default request
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/utils/index.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/utils/index.js"
new file mode 100644
index 0000000..1b2b7e9
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/utils/index.js"
@@ -0,0 +1,111 @@
+// 閫氱敤宸ュ叿鍑芥暟
+import dayjs from 'dayjs'
+
+/**
+ * 鏍煎紡鍖栨棩鏈熸椂闂�
+ * @param {Date|string|number} date - 鏃ユ湡瀵硅薄銆佹棩鏈熷瓧绗︿覆鎴栨椂闂存埑
+ * @param {string} format - 鏍煎紡鍖栨ā鏉匡紝榛樿 'YYYY-MM-DD HH:mm:ss'
+ * @returns {string} 鏍煎紡鍖栧悗鐨勬棩鏈熷瓧绗︿覆
+ */
+export function formatDateTime(date, format = 'YYYY-MM-DD HH:mm:ss') {
+ return dayjs(date).format(format)
+}
+
+/**
+ * 鏍煎紡鍖栨棩鏈�
+ * @param {Date|string|number} date - 鏃ユ湡瀵硅薄銆佹棩鏈熷瓧绗︿覆鎴栨椂闂存埑
+ * @returns {string} 鏍煎紡鍖栧悗鐨勬棩鏈熷瓧绗︿覆 YYYY-MM-DD
+ */
+export function formatDate(date) {
+ return formatDateTime(date, 'YYYY-MM-DD')
+}
+
+/**
+ * 鏍煎紡鍖栨椂闂�
+ * @param {Date|string|number} date - 鏃ユ湡瀵硅薄銆佹棩鏈熷瓧绗︿覆鎴栨椂闂存埑
+ * @returns {string} 鏍煎紡鍖栧悗鐨勬椂闂村瓧绗︿覆 HH:mm:ss
+ */
+export function formatTime(date) {
+ return formatDateTime(date, 'HH:mm:ss')
+}
+
+/**
+ * 鏁板瓧鏍煎紡鍖栵紝娣诲姞鍗冨垎浣�
+ * @param {number} num - 鏁板瓧
+ * @param {number} decimals - 灏忔暟浣嶆暟锛岄粯璁�0
+ * @returns {string} 鏍煎紡鍖栧悗鐨勬暟瀛楀瓧绗︿覆
+ */
+export function formatNumber(num, decimals = 0) {
+ return Number(num).toLocaleString('zh-CN', {
+ minimumFractionDigits: decimals,
+ maximumFractionDigits: decimals
+ })
+}
+
+/**
+ * 鑾峰彇闅忔満棰滆壊
+ * @returns {string} 棰滆壊鍊�
+ */
+export function getRandomColor() {
+ const colors = [
+ '#409EFF', '#67C23A', '#E6A23C', '#F56C6C',
+ '#909399', '#5470c6', '#91cc75', '#fac858',
+ '#ee6666', '#73c0de', '#3ba272', '#fc8452'
+ ]
+ return colors[Math.floor(Math.random() * colors.length)]
+}
+
+/**
+ * 闃叉姈鍑芥暟
+ * @param {Function} func - 瑕侀槻鎶栫殑鍑芥暟
+ * @param {number} wait - 绛夊緟鏃堕棿锛堟绉掞級
+ * @returns {Function} 闃叉姈鍚庣殑鍑芥暟
+ */
+export function debounce(func, wait = 300) {
+ let timeout
+ return function executedFunction(...args) {
+ const later = () => {
+ clearTimeout(timeout)
+ func(...args)
+ }
+ clearTimeout(timeout)
+ timeout = setTimeout(later, wait)
+ }
+}
+
+/**
+ * 鑺傛祦鍑芥暟
+ * @param {Function} func - 瑕佽妭娴佺殑鍑芥暟
+ * @param {number} wait - 绛夊緟鏃堕棿锛堟绉掞級
+ * @returns {Function} 鑺傛祦鍚庣殑鍑芥暟
+ */
+export function throttle(func, wait = 300) {
+ let inThrottle
+ return function executedFunction(...args) {
+ if (!inThrottle) {
+ func(...args)
+ inThrottle = true
+ setTimeout(() => inThrottle = false, wait)
+ }
+ }
+}
+
+/**
+ * 娣辨嫹璐�
+ * @param {any} obj - 瑕佹嫹璐濈殑瀵硅薄
+ * @returns {any} 鎷疯礉鍚庣殑瀵硅薄
+ */
+export function deepClone(obj) {
+ if (obj === null || typeof obj !== 'object') return obj
+ if (obj instanceof Date) return new Date(obj)
+ if (obj instanceof Array) return obj.map(item => deepClone(item))
+ if (obj instanceof Object) {
+ const cloneObj = {}
+ for (const key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ cloneObj[key] = deepClone(obj[key])
+ }
+ }
+ return cloneObj
+ }
+}
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Dashboard.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Dashboard.vue"
new file mode 100644
index 0000000..e97fd1c
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Dashboard.vue"
@@ -0,0 +1,729 @@
+<template>
+ <div class="dashboard-container">
+ <!-- 椤堕儴鏍囬 -->
+ <div class="header">
+ <h1 class="title">WMS浠撳簱绠$悊绯荤粺鐩戞帶鐪嬫澘</h1>
+ <div class="datetime">{{ currentTime }}</div>
+ </div>
+
+ <!-- 瀵艰埅鑿滃崟 -->
+ <div class="nav-menu">
+ <router-link to="/dashboard" class="nav-item" active-class="active">
+ <el-icon><DataBoard /></el-icon>
+ <span>缁煎悎鐪嬫澘</span>
+ </router-link>
+ <router-link to="/warehouse" class="nav-item" active-class="active">
+ <el-icon><Box /></el-icon>
+ <span>浠撳簱鐩戞帶</span>
+ </router-link>
+ <router-link to="/production" class="nav-item" active-class="active">
+ <el-icon><Operation /></el-icon>
+ <span>鐢熶骇鐩戞帶</span>
+ </router-link>
+ <router-link to="/inventory" class="nav-item" active-class="active">
+ <el-icon><Warning /></el-icon>
+ <span>搴撳瓨棰勮</span>
+ </router-link>
+ </div>
+
+ <!-- 涓昏鍐呭鍖哄煙 -->
+ <div class="main-content">
+ <!-- 绗竴琛岋細鍏抽敭鎸囨爣鍗$墖 -->
+ <div class="metrics-row">
+ <div class="metric-card" v-for="(item, index) in metrics" :key="index">
+ <div class="metric-icon" :style="{ background: item.color }">
+ <el-icon :size="32">
+ <Box v-if="index === 0" />
+ <Download v-else-if="index === 1" />
+ <Upload v-else-if="index === 2" />
+ <List v-else />
+ </el-icon>
+ </div>
+ <div class="metric-content">
+ <div class="metric-value">{{ item.value }}</div>
+ <div class="metric-label">{{ item.label }}</div>
+ <div class="metric-trend" :class="item.trend > 0 ? 'up' : 'down'">
+ <el-icon>
+ <Top v-if="item.trend > 0" />
+ <Bottom v-else />
+ </el-icon>
+ <span>{{ Math.abs(item.trend) }}%</span>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 绗簩琛岋細鍥捐〃鍖哄煙 -->
+ <div class="charts-row">
+ <!-- 鍏ュ簱鍑哄簱瓒嬪娍 -->
+ <div class="chart-card">
+ <div class="card-title">
+ <span>鍑哄叆搴撹秼鍔�</span>
+ </div>
+ <div ref="trendChartRef" class="chart-container"></div>
+ </div>
+
+ <!-- 搴撳瓨鍒嗙被鍗犳瘮 -->
+ <div class="chart-card">
+ <div class="card-title">
+ <span>搴撳瓨鍒嗙被鍗犳瘮</span>
+ </div>
+ <div ref="categoryChartRef" class="chart-container"></div>
+ </div>
+
+ <!-- 浣滀笟鏁堢巼 -->
+ <div class="chart-card">
+ <div class="card-title">
+ <span>浣滀笟鏁堢巼缁熻</span>
+ </div>
+ <div ref="efficiencyChartRef" class="chart-container"></div>
+ </div>
+ </div>
+
+ <!-- 绗笁琛岋細鏁版嵁琛ㄦ牸 -->
+ <div class="table-row">
+ <div class="table-card">
+ <div class="card-title">
+ <span>瀹炴椂浣滀笟浠诲姟</span>
+ <el-button type="primary" size="small" @click="refreshData">
+ <el-icon><Refresh /></el-icon>
+ 鍒锋柊
+ </el-button>
+ </div>
+ <el-table :data="taskList" style="width: 100%" height="200">
+ <el-table-column prop="taskNo" label="浠诲姟缂栧彿" width="150" />
+ <el-table-column prop="type" label="浠诲姟绫诲瀷" width="100">
+ <template #default="{ row }">
+ <el-tag :type="row.type === '鍏ュ簱' ? 'success' : 'warning'">{{ row.type }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="material" label="鐗╂枡鍚嶇О" />
+ <el-table-column prop="quantity" label="鏁伴噺" width="100" />
+ <el-table-column prop="location" label="搴撲綅" width="120" />
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="{ row }">
+ <el-tag :type="getStatusType(row.status)">{{ row.status }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="operator" label="鎿嶄綔鍛�" width="100" />
+ <el-table-column prop="time" label="鏃堕棿" width="160" />
+ </el-table>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { ref, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { http } from '@/utils/http'
+import { formatDateTime } from '@/utils'
+
+export default {
+ name: 'Dashboard',
+ setup() {
+ const currentTime = ref('')
+ const trendChartRef = ref(null)
+ const categoryChartRef = ref(null)
+ const efficiencyChartRef = ref(null)
+
+ const metrics = ref([
+ { label: '鎬诲簱瀛橀噺', value: '12,580', icon: 'Box', color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', trend: 8.5 },
+ { label: '浠婃棩鍏ュ簱', value: '1,280', icon: 'Download', color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)', trend: 12.3 },
+ { label: '浠婃棩鍑哄簱', value: '965', icon: 'Upload', color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)', trend: -3.2 },
+ { label: '寰呭鐞嗕换鍔�', value: '48', icon: 'List', color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)', trend: 5.7 }
+ ])
+
+ const taskList = ref([])
+
+ // 鏇存柊鏃堕棿
+ let timer
+ const updateTime = () => {
+ currentTime.value = formatDateTime(new Date())
+ }
+
+ // 鑾峰彇鐘舵�佺被鍨�
+ const getStatusType = (status) => {
+ const map = {
+ '杩涜涓�': 'primary',
+ '宸插畬鎴�': 'success',
+ '寰呭鐞�': 'info',
+ '寮傚父': 'danger'
+ }
+ return map[status] || 'info'
+ }
+
+ // 鍒濆鍖栬秼鍔垮浘
+ const initTrendChart = () => {
+ const chart = echarts.init(trendChartRef.value)
+ const option = {
+ tooltip: { trigger: 'axis' },
+ legend: {
+ data: ['鍏ュ簱閲�', '鍑哄簱閲�'],
+ textStyle: { color: '#fff' }
+ },
+ grid: {
+ left: '3%', right: '4%', bottom: '3%', top: '15%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00', '24:00'],
+ axisLine: { lineStyle: { color: '#fff' } }
+ },
+ yAxis: {
+ type: 'value',
+ axisLine: { lineStyle: { color: '#fff' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }
+ },
+ series: [
+ {
+ name: '鍏ュ簱閲�',
+ type: 'line',
+ smooth: true,
+ data: [120, 200, 450, 680, 520, 780, 650],
+ itemStyle: { color: '#43e97b' },
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: 'rgba(67, 233, 123, 0.5)' },
+ { offset: 1, color: 'rgba(67, 233, 123, 0)' }
+ ])
+ }
+ },
+ {
+ name: '鍑哄簱閲�',
+ type: 'line',
+ smooth: true,
+ data: [80, 150, 380, 520, 420, 650, 580],
+ itemStyle: { color: '#4facfe' },
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: 'rgba(79, 172, 254, 0.5)' },
+ { offset: 1, color: 'rgba(79, 172, 254, 0)' }
+ ])
+ }
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ // 鍒濆鍖栧垎绫诲崰姣斿浘
+ const initCategoryChart = () => {
+ const chart = echarts.init(categoryChartRef.value)
+ const option = {
+ tooltip: { trigger: 'item' },
+ legend: {
+ orient: 'vertical',
+ right: '10%',
+ top: 'center',
+ textStyle: { color: '#fff' }
+ },
+ series: [
+ {
+ name: '搴撳瓨鍒嗙被',
+ type: 'pie',
+ radius: ['40%', '70%'],
+ center: ['35%', '50%'],
+ avoidLabelOverlap: false,
+ itemStyle: {
+ borderRadius: 10,
+ borderColor: '#0a0e27',
+ borderWidth: 2
+ },
+ label: { show: false },
+ emphasis: {
+ label: { show: true, fontSize: 16, fontWeight: 'bold' }
+ },
+ data: [
+ { value: 3580, name: '鍘熸潗鏂�', itemStyle: { color: '#5470c6' } },
+ { value: 2840, name: '鍗婃垚鍝�', itemStyle: { color: '#91cc75' } },
+ { value: 4120, name: '鎴愬搧', itemStyle: { color: '#fac858' } },
+ { value: 2040, name: '杈呮枡', itemStyle: { color: '#ee6666' } }
+ ]
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ // 鍒濆鍖栨晥鐜囩粺璁″浘
+ const initEfficiencyChart = () => {
+ const chart = echarts.init(efficiencyChartRef.value)
+ const option = {
+ tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
+ grid: {
+ left: '3%', right: '4%', bottom: '3%', top: '10%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: ['鍏ュ簱浣滀笟', '鍑哄簱浣滀笟', '鐩樼偣浣滀笟', '璋冩嫧浣滀笟', '琛ヨ揣浣滀笟'],
+ axisLine: { lineStyle: { color: '#fff' } },
+ axisLabel: { color: '#fff' }
+ },
+ yAxis: {
+ type: 'value',
+ name: '鏁堢巼(鍗曚綅/灏忔椂)',
+ axisLine: { lineStyle: { color: '#fff' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
+ axisLabel: { color: '#fff' }
+ },
+ series: [
+ {
+ data: [180, 156, 95, 78, 120],
+ type: 'bar',
+ barWidth: '40%',
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: '#83bff6' },
+ { offset: 1, color: '#188df0' }
+ ]),
+ borderRadius: [5, 5, 0, 0]
+ }
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ // 鑾峰彇浠诲姟鍒楄〃鏁版嵁
+ const fetchTaskList = async () => {
+ try {
+ // 妯℃嫙鏁版嵁锛屽疄闄呬娇鐢ㄦ椂璋冪敤鎺ュ彛
+ // const res = await http.get('/wms/task/list')
+
+ // 妯℃嫙鏁版嵁
+ taskList.value = [
+ { taskNo: 'RK20241224001', type: '鍏ュ簱', material: '閽㈡澘 A鍨�', quantity: 500, location: 'A-01-01', status: '杩涜涓�', operator: '寮犱笁', time: '2024-12-24 14:25:30' },
+ { taskNo: 'CK20241224002', type: '鍑哄簱', material: '铻轰笣 M8', quantity: 2000, location: 'B-03-05', status: '宸插畬鎴�', operator: '鏉庡洓', time: '2024-12-24 14:20:15' },
+ { taskNo: 'RK20241224003', type: '鍏ュ簱', material: '閾濇澘 B鍨�', quantity: 300, location: 'A-02-03', status: '寰呭鐞�', operator: '鐜嬩簲', time: '2024-12-24 14:15:00' },
+ { taskNo: 'CK20241224004', type: '鍑哄簱', material: '铻烘瘝 M8', quantity: 1500, location: 'B-02-01', status: '杩涜涓�', operator: '璧靛叚', time: '2024-12-24 14:10:45' },
+ { taskNo: 'PD20241224001', type: '鐩樼偣', material: '鍨墖', quantity: 5000, location: 'C-01-01', status: '杩涜涓�', operator: '瀛欎竷', time: '2024-12-24 14:05:20' }
+ ]
+ } catch (error) {
+ console.error('鑾峰彇浠诲姟鍒楄〃澶辫触:', error)
+ }
+ }
+
+ // 鍒锋柊鏁版嵁
+ const refreshData = () => {
+ fetchTaskList()
+ }
+
+ // 绐楀彛澶у皬鏀瑰彉鏃堕噸缁樺浘琛�
+ const handleResize = () => {
+ try {
+ const refs = [trendChartRef.value, categoryChartRef.value, efficiencyChartRef.value]
+ refs.forEach(dom => {
+ if (dom) {
+ const chart = echarts.getInstanceByDom(dom)
+ if (chart) {
+ chart.resize()
+ }
+ }
+ })
+ } catch (error) {
+ console.warn('鍥捐〃閲嶇粯鏃跺嚭閿�:', error)
+ }
+ }
+
+ onMounted(() => {
+ updateTime()
+ timer = setInterval(updateTime, 1000)
+
+ initTrendChart()
+ initCategoryChart()
+ initEfficiencyChart()
+ fetchTaskList()
+
+ window.addEventListener('resize', handleResize)
+ })
+
+ onUnmounted(() => {
+ clearInterval(timer)
+ window.removeEventListener('resize', handleResize)
+
+ // 閿�姣佸浘琛ㄥ疄渚�
+ try {
+ const refs = [trendChartRef.value, categoryChartRef.value, efficiencyChartRef.value]
+ refs.forEach(dom => {
+ if (dom) {
+ const chart = echarts.getInstanceByDom(dom)
+ if (chart) {
+ chart.dispose()
+ }
+ }
+ })
+ } catch (error) {
+ console.warn('鍥捐〃閿�姣佹椂鍑洪敊:', error)
+ }
+ })
+
+ return {
+ currentTime,
+ metrics,
+ taskList,
+ trendChartRef,
+ categoryChartRef,
+ efficiencyChartRef,
+ getStatusType,
+ refreshData
+ }
+ }
+}
+</script>
+
+<style scoped>
+.dashboard-container {
+ width: 100%;
+ height: 100%;
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+ overflow-y: auto;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 20px;
+ height: 60px;
+ background: linear-gradient(90deg, rgba(30, 58, 138, 0.5) 0%, rgba(30, 58, 138, 0.1) 100%);
+ border-radius: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.title {
+ font-size: 24px;
+ font-weight: bold;
+ background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.datetime {
+ font-size: 16px;
+ color: #4facfe;
+}
+
+.nav-menu {
+ display: flex;
+ gap: 15px;
+ padding: 0 20px;
+}
+
+.nav-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 10px 25px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 8px;
+ color: #fff;
+ text-decoration: none;
+ transition: all 0.3s;
+ cursor: pointer;
+}
+
+.nav-item:hover {
+ background: rgba(79, 172, 254, 0.2);
+ border-color: #4facfe;
+}
+
+.nav-item.active {
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+ border-color: transparent;
+}
+
+.main-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+}
+
+.metrics-row {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 15px;
+}
+
+.metric-card {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+ transition: all 0.3s;
+}
+
+.metric-card:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
+}
+
+.metric-icon {
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 12px;
+ color: #fff;
+}
+
+.metric-content {
+ flex: 1;
+}
+
+.metric-value {
+ font-size: 28px;
+ font-weight: bold;
+ margin-bottom: 5px;
+}
+
+.metric-label {
+ font-size: 14px;
+ color: rgba(255, 255, 255, 0.6);
+ margin-bottom: 5px;
+}
+
+.metric-trend {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ font-size: 12px;
+}
+
+.metric-trend.up {
+ color: #67c23a;
+}
+
+.metric-trend.down {
+ color: #f56c6c;
+}
+
+.charts-row {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 15px;
+}
+
+.chart-card {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.card-title {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+}
+
+.chart-container {
+ width: 100%;
+ height: 250px;
+}
+
+.table-row {
+ flex: 1;
+}
+
+.table-card {
+ height: 100%;
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+:deep(.el-table) {
+ background: transparent !important;
+}
+
+:deep(.el-table th) {
+ background: rgba(255, 255, 255, 0.1) !important;
+ color: #fff !important;
+ border-color: rgba(255, 255, 255, 0.1) !important;
+}
+
+:deep(.el-table td) {
+ border-color: rgba(255, 255, 255, 0.1) !important;
+}
+
+:deep(.el-table tr) {
+ background: transparent !important;
+}
+
+:deep(.el-table__row:hover td) {
+ background: rgba(255, 255, 255, 0.05) !important;
+}
+
+:deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
+ background: rgba(255, 255, 255, 0.05) !important;
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media screen and (max-width: 1920px) {
+ .metric-value {
+ font-size: 24px;
+ }
+
+ .chart-container {
+ height: 220px;
+ }
+}
+
+@media screen and (max-width: 1600px) {
+ .metrics-row {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .charts-row {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .title {
+ font-size: 20px;
+ }
+
+ .metric-value {
+ font-size: 20px;
+ }
+
+ .chart-container {
+ height: 200px;
+ }
+}
+
+@media screen and (max-width: 1366px) {
+ .dashboard-container {
+ padding: 15px;
+ }
+
+ .header {
+ height: 50px;
+ padding: 0 15px;
+ }
+
+ .title {
+ font-size: 18px;
+ }
+
+ .nav-item {
+ padding: 8px 20px;
+ font-size: 14px;
+ }
+
+ .metrics-row {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 10px;
+ }
+
+ .metric-card {
+ padding: 15px;
+ }
+
+ .metric-value {
+ font-size: 18px;
+ }
+
+ .charts-row {
+ grid-template-columns: 1fr;
+ gap: 10px;
+ }
+
+ .chart-card {
+ padding: 15px;
+ }
+
+ .chart-container {
+ height: 180px;
+ }
+}
+
+@media screen and (max-width: 1024px) {
+ .metrics-row {
+ grid-template-columns: 1fr 1fr;
+ }
+
+ .nav-menu {
+ flex-wrap: wrap;
+ }
+
+ .nav-item {
+ flex: 1;
+ min-width: 100px;
+ justify-content: center;
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .dashboard-container {
+ padding: 10px;
+ }
+
+ .header {
+ flex-direction: column;
+ height: auto;
+ padding: 10px;
+ gap: 10px;
+ }
+
+ .title {
+ font-size: 16px;
+ }
+
+ .datetime {
+ font-size: 14px;
+ }
+
+ .nav-menu {
+ gap: 8px;
+ padding: 0;
+ }
+
+ .nav-item {
+ padding: 6px 12px;
+ font-size: 12px;
+ flex-direction: column;
+ gap: 4px;
+ }
+
+ .metrics-row {
+ grid-template-columns: 1fr;
+ }
+
+ .metric-card {
+ padding: 12px;
+ flex-direction: column;
+ text-align: center;
+ }
+
+ .metric-icon {
+ width: 45px;
+ height: 45px;
+ }
+
+ .chart-container {
+ height: 150px;
+ }
+}
+</style>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Inventory.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Inventory.vue"
new file mode 100644
index 0000000..bf0cb6a
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Inventory.vue"
@@ -0,0 +1,831 @@
+<template>
+ <div class="inventory-container">
+ <div class="header">
+ <h1 class="title">搴撳瓨棰勮涓績</h1>
+ <div class="datetime">{{ currentTime }}</div>
+ </div>
+
+ <div class="nav-menu">
+ <router-link to="/dashboard" class="nav-item">缁煎悎鐪嬫澘</router-link>
+ <router-link to="/warehouse" class="nav-item">浠撳簱鐩戞帶</router-link>
+ <router-link to="/production" class="nav-item">鐢熶骇鐩戞帶</router-link>
+ <router-link to="/inventory" class="nav-item active">搴撳瓨棰勮</router-link>
+ </div>
+
+ <div class="main-content">
+ <!-- 棰勮缁熻 -->
+ <div class="alert-summary">
+ <div class="alert-card critical">
+ <div class="alert-icon">
+ <el-icon :size="36"><WarningFilled /></el-icon>
+ </div>
+ <div class="alert-content">
+ <div class="alert-count">{{ alertStats.critical }}</div>
+ <div class="alert-label">绱ф�ラ璀�</div>
+ </div>
+ </div>
+ <div class="alert-card warning">
+ <div class="alert-icon">
+ <el-icon :size="36"><Warning /></el-icon>
+ </div>
+ <div class="alert-content">
+ <div class="alert-count">{{ alertStats.warning }}</div>
+ <div class="alert-label">棰勮鎻愰啋</div>
+ </div>
+ </div>
+ <div class="alert-card info">
+ <div class="alert-icon">
+ <el-icon :size="36"><InfoFilled /></el-icon>
+ </div>
+ <div class="alert-content">
+ <div class="alert-count">{{ alertStats.info }}</div>
+ <div class="alert-label">淇℃伅鎻愰啋</div>
+ </div>
+ </div>
+ <div class="alert-card normal">
+ <div class="alert-icon">
+ <el-icon :size="36"><CircleCheckFilled /></el-icon>
+ </div>
+ <div class="alert-content">
+ <div class="alert-count">{{ alertStats.normal }}</div>
+ <div class="alert-label">搴撳瓨姝e父</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 搴撳瓨棰勮鍒楄〃 -->
+ <div class="alert-lists">
+ <div class="list-card">
+ <div class="list-header">
+ <span class="list-title">
+ <el-icon><WarningFilled /></el-icon>
+ 搴撳瓨涓嶈冻棰勮
+ </span>
+ <el-badge :value="lowStockAlerts.length" class="badge" />
+ </div>
+ <el-table :data="lowStockAlerts" style="width: 100%" max-height="250">
+ <el-table-column prop="materialCode" label="鐗╂枡缂栫爜" width="130" />
+ <el-table-column prop="materialName" label="鐗╂枡鍚嶇О" />
+ <el-table-column prop="currentStock" label="褰撳墠搴撳瓨" width="100">
+ <template #default="{ row }">
+ <span :class="getStockClass(row.currentStock, row.minStock)">{{ row.currentStock }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="minStock" label="鏈�灏忓簱瀛�" width="100" />
+ <el-table-column prop="maxStock" label="鏈�澶у簱瀛�" width="100" />
+ <el-table-column prop="unit" label="鍗曚綅" width="60" />
+ <el-table-column prop="suggestion" label="寤鸿琛ヨ揣" width="100" />
+ <el-table-column prop="warehouse" label="浠撳簱" width="100" />
+ <el-table-column label="鎿嶄綔" width="100" fixed="right">
+ <template #default="{ row }">
+ <el-button type="primary" size="small" link>琛ヨ揣</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
+ <div class="list-card">
+ <div class="list-header">
+ <span class="list-title">
+ <el-icon><Top /></el-icon>
+ 搴撳瓨绉帇棰勮
+ </span>
+ <el-badge :value="overStockAlerts.length" class="badge" />
+ </div>
+ <el-table :data="overStockAlerts" style="width: 100%" max-height="250">
+ <el-table-column prop="materialCode" label="鐗╂枡缂栫爜" width="130" />
+ <el-table-column prop="materialName" label="鐗╂枡鍚嶇О" />
+ <el-table-column prop="currentStock" label="褰撳墠搴撳瓨" width="100">
+ <template #default="{ row }">
+ <span class="over-stock">{{ row.currentStock }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="maxStock" label="鏈�澶у簱瀛�" width="100" />
+ <el-table-column prop="overRate" label="瓒呭偍鐜�" width="100">
+ <template #default="{ row }">
+ <el-progress type="circle" :percentage="row.overRate" :width="50" :color="'#f56c6c'" />
+ </template>
+ </el-table-column>
+ <el-table-column prop="unit" label="鍗曚綅" width="60" />
+ <el-table-column prop="daysInStock" label="搴撻緞(澶�)" width="90" />
+ <el-table-column prop="warehouse" label="浠撳簱" width="100" />
+ <el-table-column label="鎿嶄綔" width="100" fixed="right">
+ <template #default="{ row }">
+ <el-button type="warning" size="small" link>澶勭悊</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+
+ <!-- 搴撳瓨瓒嬪娍鍥捐〃 -->
+ <div class="charts-row">
+ <div class="chart-card">
+ <div class="card-title">搴撳瓨鍛ㄨ浆鐜囪秼鍔�</div>
+ <div ref="turnoverChartRef" class="chart-container"></div>
+ </div>
+
+ <div class="chart-card">
+ <div class="card-title">ABC鍒嗙被搴撳瓨鍗犳瘮</div>
+ <div ref="abcChartRef" class="chart-container"></div>
+ </div>
+
+ <div class="chart-card">
+ <div class="card-title">杩戞晥鏈熺墿鏂欓璀�</div>
+ <div ref="expiryChartRef" class="chart-container"></div>
+ </div>
+ </div>
+
+ <!-- 鍗冲皢杩囨湡鐗╂枡 -->
+ <div class="expiry-list">
+ <div class="list-title">鍗冲皢杩囨湡鐗╂枡娓呭崟</div>
+ <el-table :data="expiryItems" style="width: 100%" height="200">
+ <el-table-column prop="batchNo" label="鎵规鍙�" width="140" />
+ <el-table-column prop="materialName" label="鐗╂枡鍚嶇О" />
+ <el-table-column prop="quantity" label="鏁伴噺" width="100" />
+ <el-table-column prop="expiryDate" label="鏈夋晥鏈�" width="120" />
+ <el-table-column prop="daysLeft" label="鍓╀綑澶╂暟" width="100">
+ <template #default="{ row }">
+ <el-tag :type="getExpiryTagType(row.daysLeft)">{{ row.daysLeft }}澶�</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="location" label="搴撲綅" width="100" />
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="{ row }">
+ <el-tag :type="row.status === '宸查攣瀹�' ? 'danger' : 'warning'">{{ row.status }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="150" fixed="right">
+ <template #default="{ row }">
+ <el-button size="small" type="primary" link>浼樺厛鍑哄簱</el-button>
+ <el-button size="small" type="danger" link>鎶ュ簾</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { ref, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { http } from '@/utils/http'
+import { formatDateTime } from '@/utils'
+
+export default {
+ name: 'Inventory',
+ setup() {
+ const currentTime = ref('')
+ const turnoverChartRef = ref(null)
+ const abcChartRef = ref(null)
+ const expiryChartRef = ref(null)
+
+ const alertStats = ref({
+ critical: 8,
+ warning: 23,
+ info: 15,
+ normal: 1456
+ })
+
+ const lowStockAlerts = ref([
+ { materialCode: 'M001', materialName: '閽㈡澘 Q235', currentStock: 50, minStock: 200, maxStock: 1000, unit: '鍚�', suggestion: '150鍚�', warehouse: 'A鍖�' },
+ { materialCode: 'M002', materialName: '閾濇澘 6061', currentStock: 80, minStock: 150, maxStock: 800, unit: '鍚�', suggestion: '70鍚�', warehouse: 'A鍖�' },
+ { materialCode: 'M003', materialName: '铻轰笣 M8', currentStock: 500, minStock: 2000, maxStock: 10000, unit: '涓�', suggestion: '1500涓�', warehouse: 'B鍖�' },
+ { materialCode: 'M004', materialName: '铻烘瘝 M8', currentStock: 300, minStock: 1500, maxStock: 8000, unit: '涓�', suggestion: '1200涓�', warehouse: 'B鍖�' },
+ { materialCode: 'M005', materialName: '鍨墖 桅10', currentStock: 200, minStock: 1000, maxStock: 5000, unit: '涓�', suggestion: '800涓�', warehouse: 'B鍖�' }
+ ])
+
+ const overStockAlerts = ref([
+ { materialCode: 'M101', materialName: '杞存壙 6204', currentStock: 8000, maxStock: 5000, overRate: 160, unit: '涓�', daysInStock: 180, warehouse: 'C鍖�' },
+ { materialCode: 'M102', materialName: '瀵嗗皝鍦� O鍨�', currentStock: 15000, maxStock: 8000, overRate: 187, unit: '涓�', daysInStock: 240, warehouse: 'C鍖�' },
+ { materialCode: 'M103', materialName: '娑︽粦娌�', currentStock: 500, maxStock: 200, overRate: 250, unit: '鍗�', daysInStock: 300, warehouse: 'D鍖�' }
+ ])
+
+ const expiryItems = ref([
+ { batchNo: 'B20240601', materialName: '鍖栧伐鍘熸枡A', quantity: 100, expiryDate: '2025-01-15', daysLeft: 22, location: 'D-01-01', status: '棰勮' },
+ { batchNo: 'B20240701', materialName: '鑳剁矘鍓�', quantity: 50, expiryDate: '2025-01-20', daysLeft: 27, location: 'D-02-03', status: '棰勮' },
+ { batchNo: 'B20240515', materialName: '闃查攬娌�', quantity: 80, expiryDate: '2025-01-10', daysLeft: 17, location: 'D-01-05', status: '宸查攣瀹�' },
+ { batchNo: 'B20240801', materialName: '娓呮礂鍓�', quantity: 120, expiryDate: '2025-02-01', daysLeft: 39, location: 'D-03-02', status: '棰勮' },
+ { batchNo: 'B20240620', materialName: '娑傛枡', quantity: 200, expiryDate: '2025-01-25', daysLeft: 32, location: 'D-02-01', status: '棰勮' }
+ ])
+
+ let timer
+ const updateTime = () => {
+ currentTime.value = formatDateTime(new Date())
+ }
+
+ const getStockClass = (current, min) => {
+ if (current < min * 0.3) return 'critical'
+ if (current < min) return 'warning'
+ return 'normal'
+ }
+
+ const getExpiryTagType = (days) => {
+ if (days < 15) return 'danger'
+ if (days < 30) return 'warning'
+ return 'info'
+ }
+
+ // 鍒濆鍖栧懆杞巼鍥捐〃
+ const initTurnoverChart = () => {
+ const chart = echarts.init(turnoverChartRef.value)
+ const option = {
+ tooltip: { trigger: 'axis' },
+ grid: {
+ left: '3%', right: '4%', bottom: '3%', top: '10%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�'],
+ axisLine: { lineStyle: { color: '#fff' } }
+ },
+ yAxis: {
+ type: 'value',
+ name: '鍛ㄨ浆鐜�',
+ axisLine: { lineStyle: { color: '#fff' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }
+ },
+ series: [
+ {
+ name: '鍛ㄨ浆鐜�',
+ type: 'line',
+ smooth: true,
+ data: [4.2, 3.8, 4.5, 5.2, 4.8, 5.5],
+ itemStyle: { color: '#4facfe' },
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: 'rgba(79, 172, 254, 0.5)' },
+ { offset: 1, color: 'rgba(79, 172, 254, 0)' }
+ ])
+ }
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ // 鍒濆鍖朅BC鍒嗙被鍥捐〃
+ const initAbcChart = () => {
+ const chart = echarts.init(abcChartRef.value)
+ const option = {
+ tooltip: { trigger: 'item' },
+ legend: {
+ orient: 'vertical',
+ right: '5%',
+ top: 'center',
+ textStyle: { color: '#fff' }
+ },
+ series: [
+ {
+ name: 'ABC鍒嗙被',
+ type: 'pie',
+ radius: ['40%', '70%'],
+ center: ['40%', '50%'],
+ itemStyle: {
+ borderRadius: 10,
+ borderColor: '#0a0e27',
+ borderWidth: 2
+ },
+ label: { show: false },
+ data: [
+ { value: 4850, name: 'A绫�(楂樹环鍊�)', itemStyle: { color: '#f56c6c' } },
+ { value: 3280, name: 'B绫�(涓环鍊�)', itemStyle: { color: '#e6a23c' } },
+ { value: 4450, name: 'C绫�(浣庝环鍊�)', itemStyle: { color: '#67c23a' } }
+ ]
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ // 鍒濆鍖栬繎鏁堟湡鍥捐〃
+ const initExpiryChart = () => {
+ const chart = echarts.init(expiryChartRef.value)
+ const option = {
+ tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
+ grid: {
+ left: '3%', right: '4%', bottom: '3%', top: '10%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: ['15澶╁唴', '30澶╁唴', '60澶╁唴', '90澶╁唴', '90澶╀互涓�'],
+ axisLine: { lineStyle: { color: '#fff' } },
+ axisLabel: { color: '#fff', rotate: 30 }
+ },
+ yAxis: {
+ type: 'value',
+ axisLine: { lineStyle: { color: '#fff' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }
+ },
+ series: [
+ {
+ data: [5, 12, 28, 45, 18],
+ type: 'bar',
+ barWidth: '50%',
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: '#fa709a' },
+ { offset: 1, color: '#fee140' }
+ ]),
+ borderRadius: [5, 5, 0, 0]
+ }
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ const handleResize = () => {
+ try {
+ const refs = [turnoverChartRef.value, abcChartRef.value, expiryChartRef.value]
+ refs.forEach(dom => {
+ if (dom) {
+ const chart = echarts.getInstanceByDom(dom)
+ if (chart) {
+ chart.resize()
+ }
+ }
+ })
+ } catch (error) {
+ console.warn('鍥捐〃閲嶇粯鏃跺嚭閿�:', error)
+ }
+ }
+
+ onMounted(() => {
+ updateTime()
+ timer = setInterval(updateTime, 1000)
+ initTurnoverChart()
+ initAbcChart()
+ initExpiryChart()
+ window.addEventListener('resize', handleResize)
+ })
+
+ onUnmounted(() => {
+ clearInterval(timer)
+ window.removeEventListener('resize', handleResize)
+
+ // 閿�姣佸浘琛ㄥ疄渚�
+ try {
+ const refs = [turnoverChartRef.value, abcChartRef.value, expiryChartRef.value]
+ refs.forEach(dom => {
+ if (dom) {
+ const chart = echarts.getInstanceByDom(dom)
+ if (chart) {
+ chart.dispose()
+ }
+ }
+ })
+ } catch (error) {
+ console.warn('鍥捐〃閿�姣佹椂鍑洪敊:', error)
+ }
+ })
+
+ return {
+ currentTime,
+ alertStats,
+ lowStockAlerts,
+ overStockAlerts,
+ expiryItems,
+ turnoverChartRef,
+ abcChartRef,
+ expiryChartRef,
+ getStockClass,
+ getExpiryTagType
+ }
+ }
+}
+</script>
+
+<style scoped>
+.inventory-container {
+ width: 100%;
+ height: 100%;
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+ overflow-y: auto;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 20px;
+ height: 60px;
+ background: linear-gradient(90deg, rgba(30, 58, 138, 0.5) 0%, rgba(30, 58, 138, 0.1) 100%);
+ border-radius: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.title {
+ font-size: 24px;
+ font-weight: bold;
+ background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.datetime {
+ font-size: 16px;
+ color: #4facfe;
+}
+
+.nav-menu {
+ display: flex;
+ gap: 15px;
+ padding: 0 20px;
+}
+
+.nav-item {
+ padding: 10px 25px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 8px;
+ color: #fff;
+ text-decoration: none;
+ transition: all 0.3s;
+}
+
+.nav-item:hover {
+ background: rgba(79, 172, 254, 0.2);
+ border-color: #4facfe;
+}
+
+.nav-item.active {
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+ border-color: transparent;
+}
+
+.main-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+}
+
+.alert-summary {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 15px;
+}
+
+.alert-card {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ padding: 20px;
+ border-radius: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.alert-card.critical {
+ background: linear-gradient(135deg, rgba(245, 108, 108, 0.2) 0%, rgba(245, 108, 108, 0.05) 100%);
+ border-color: rgba(245, 108, 108, 0.3);
+}
+
+.alert-card.warning {
+ background: linear-gradient(135deg, rgba(230, 162, 60, 0.2) 0%, rgba(230, 162, 60, 0.05) 100%);
+ border-color: rgba(230, 162, 60, 0.3);
+}
+
+.alert-card.info {
+ background: linear-gradient(135deg, rgba(64, 158, 255, 0.2) 0%, rgba(64, 158, 255, 0.05) 100%);
+ border-color: rgba(64, 158, 255, 0.3);
+}
+
+.alert-card.normal {
+ background: linear-gradient(135deg, rgba(103, 194, 58, 0.2) 0%, rgba(103, 194, 58, 0.05) 100%);
+ border-color: rgba(103, 194, 58, 0.3);
+}
+
+.alert-icon {
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 12px;
+ background: rgba(255, 255, 255, 0.1);
+}
+
+.alert-card.critical .alert-icon {
+ color: #f56c6c;
+}
+
+.alert-card.warning .alert-icon {
+ color: #e6a23c;
+}
+
+.alert-card.info .alert-icon {
+ color: #409eff;
+}
+
+.alert-card.normal .alert-icon {
+ color: #67c23a;
+}
+
+.alert-content {
+ flex: 1;
+}
+
+.alert-count {
+ font-size: 32px;
+ font-weight: bold;
+ margin-bottom: 5px;
+}
+
+.alert-card.critical .alert-count {
+ color: #f56c6c;
+}
+
+.alert-card.warning .alert-count {
+ color: #e6a23c;
+}
+
+.alert-card.info .alert-count {
+ color: #409eff;
+}
+
+.alert-card.normal .alert-count {
+ color: #67c23a;
+}
+
+.alert-label {
+ font-size: 14px;
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.alert-lists {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 15px;
+}
+
+.list-card {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.list-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+}
+
+.list-title {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+}
+
+.critical {
+ color: #f56c6c !important;
+}
+
+.warning {
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.normal {
+ color: #67c23a;
+}
+
+.over-stock {
+ color: #e6a23c;
+ font-weight: bold;
+}
+
+.charts-row {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 15px;
+}
+
+.chart-card {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.card-title {
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+ margin-bottom: 15px;
+}
+
+.chart-container {
+ width: 100%;
+ height: 200px;
+}
+
+.expiry-list {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.expiry-list .list-title {
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+ margin-bottom: 15px;
+}
+
+:deep(.el-table) {
+ background: transparent !important;
+}
+
+:deep(.el-table th) {
+ background: rgba(255, 255, 255, 0.1) !important;
+ color: #fff !important;
+ border-color: rgba(255, 255, 255, 0.1) !important;
+}
+
+:deep(.el-table td) {
+ border-color: rgba(255, 255, 255, 0.1) !important;
+}
+
+:deep(.el-table tr) {
+ background: transparent !important;
+}
+
+:deep(.el-table__row:hover td) {
+ background: rgba(255, 255, 255, 0.05) !important;
+}
+
+:deep(.el-badge__content) {
+ background-color: #f56c6c;
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media screen and (max-width: 1600px) {
+ .alert-summary {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .charts-row {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (max-width: 1366px) {
+ .inventory-container {
+ padding: 15px;
+ }
+
+ .header {
+ height: 50px;
+ padding: 0 15px;
+ }
+
+ .title {
+ font-size: 18px;
+ }
+
+ .alert-summary {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 10px;
+ }
+
+ .alert-card {
+ padding: 15px;
+ }
+
+ .alert-count {
+ font-size: 24px;
+ }
+
+ .alert-lists {
+ grid-template-columns: 1fr;
+ }
+
+ .list-card {
+ padding: 15px;
+ }
+
+ .charts-row {
+ grid-template-columns: 1fr;
+ gap: 10px;
+ }
+
+ .chart-container {
+ height: 180px;
+ }
+}
+
+@media screen and (max-width: 1024px) {
+ .alert-summary {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .charts-row {
+ grid-template-columns: 1fr;
+ }
+
+ .list-card {
+ padding: 12px;
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .inventory-container {
+ padding: 10px;
+ }
+
+ .header {
+ flex-direction: column;
+ height: auto;
+ padding: 10px;
+ gap: 10px;
+ }
+
+ .title {
+ font-size: 16px;
+ }
+
+ .nav-menu {
+ gap: 8px;
+ padding: 0;
+ flex-wrap: wrap;
+ }
+
+ .nav-item {
+ padding: 6px 12px;
+ font-size: 12px;
+ }
+
+ .alert-summary {
+ grid-template-columns: 1fr 1fr;
+ gap: 8px;
+ }
+
+ .alert-card {
+ padding: 12px;
+ flex-direction: column;
+ text-align: center;
+ }
+
+ .alert-icon {
+ width: 45px;
+ height: 45px;
+ }
+
+ .alert-count {
+ font-size: 20px;
+ }
+
+ .alert-lists {
+ grid-template-columns: 1fr;
+ }
+
+ .list-card {
+ padding: 12px;
+ }
+
+ .list-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 10px;
+ }
+
+ .charts-row {
+ grid-template-columns: 1fr;
+ }
+
+ .chart-container {
+ height: 150px;
+ }
+
+ .expiry-list {
+ padding: 12px;
+ }
+
+ :deep(.el-table) {
+ font-size: 12px;
+ }
+
+ :deep(.el-table th) {
+ padding: 8px 0;
+ }
+
+ :deep(.el-table td) {
+ padding: 8px 0;
+ }
+}
+</style>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Production.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Production.vue"
new file mode 100644
index 0000000..233ad86
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Production.vue"
@@ -0,0 +1,837 @@
+<template>
+ <div class="production-container">
+ <div class="header">
+ <h1 class="title">鐢熶骇鐩戞帶涓績</h1>
+ <div class="datetime">{{ currentTime }}</div>
+ </div>
+
+ <div class="nav-menu">
+ <router-link to="/dashboard" class="nav-item">缁煎悎鐪嬫澘</router-link>
+ <router-link to="/warehouse" class="nav-item">浠撳簱鐩戞帶</router-link>
+ <router-link to="/production" class="nav-item active">鐢熶骇鐩戞帶</router-link>
+ <router-link to="/inventory" class="nav-item">搴撳瓨棰勮</router-link>
+ </div>
+
+ <div class="main-content">
+ <!-- 鐢熶骇鎸囨爣 -->
+ <div class="metrics-row">
+ <div class="metric-card" v-for="(metric, index) in metrics" :key="index">
+ <div class="metric-icon" :style="{ background: metric.color }">
+ <el-icon :size="28">
+ <Calendar v-if="index === 0" />
+ <SuccessFilled v-else-if="index === 1" />
+ <CircleCheckFilled v-else-if="index === 2" />
+ <Setting v-else />
+ </el-icon>
+ </div>
+ <div class="metric-info">
+ <div class="metric-value">{{ metric.value }}</div>
+ <div class="metric-label">{{ metric.label }}</div>
+ <div class="metric-target">鐩爣: {{ metric.target }}</div>
+ </div>
+ <div class="metric-progress" :style="{ width: metric.progress + '%', background: metric.color }"></div>
+ </div>
+ </div>
+
+ <!-- 鐢熶骇绾垮拰璁惧鐘舵�� -->
+ <div class="production-lines">
+ <div class="line-card" v-for="(line, index) in productionLines" :key="index">
+ <div class="line-header">
+ <div class="line-title">
+ <span class="line-name">{{ line.name }}</span>
+ <el-tag :type="line.status === '杩愯涓�' ? 'success' : 'warning'">{{ line.status }}</el-tag>
+ </div>
+ <div class="line-output">浠婃棩浜ч噺: {{ line.output }}</div>
+ </div>
+ <div class="line-devices">
+ <div class="device-item" v-for="(device, dIndex) in line.devices" :key="dIndex">
+ <div class="device-icon" :class="device.status === '杩愯' ? 'running' : 'stopped'">
+ <el-icon>
+ <Cpu v-if="device.name.includes('CNC')" />
+ <Operation v-else-if="device.name.includes('杈撻�佸甫')" />
+ <Connection v-else />
+ </el-icon>
+ </div>
+ <div class="device-info">
+ <div class="device-name">{{ device.name }}</div>
+ <div class="device-status">{{ device.status }}</div>
+ </div>
+ <div class="device-data">
+ <div class="data-item">
+ <span class="data-label">娓╁害</span>
+ <span class="data-value">{{ device.temperature }}掳C</span>
+ </div>
+ <div class="data-item">
+ <span class="data-label">杞��</span>
+ <span class="data-value">{{ device.speed }}</span>
+ </div>
+ <div class="data-item">
+ <span class="data-label">璐熻浇</span>
+ <span class="data-value">{{ device.load }}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 鐢熶骇缁熻鍥捐〃 -->
+ <div class="charts-row">
+ <div class="chart-card">
+ <div class="card-title">
+ <span>浜ч噺瓒嬪娍</span>
+ <el-radio-group v-model="trendPeriod" size="small">
+ <el-radio-button label="鏃�">鏃�</el-radio-button>
+ <el-radio-button label="鍛�">鍛�</el-radio-button>
+ <el-radio-button label="鏈�">鏈�</el-radio-button>
+ </el-radio-group>
+ </div>
+ <div ref="productionChartRef" class="chart-container"></div>
+ </div>
+
+ <div class="chart-card">
+ <div class="card-title">鑹搧鐜囩粺璁�</div>
+ <div ref="qualityChartRef" class="chart-container"></div>
+ </div>
+
+ <div class="chart-card">
+ <div class="card-title">璁惧OEE</div>
+ <div ref="oeeChartRef" class="chart-container"></div>
+ </div>
+ </div>
+
+ <!-- 瀹炴椂鐢熶骇浠诲姟 -->
+ <div class="tasks-panel">
+ <div class="panel-title">瀹炴椂鐢熶骇浠诲姟</div>
+ <el-table :data="tasks" style="width: 100%" height="200">
+ <el-table-column prop="orderNo" label="鐢熶骇璁㈠崟" width="140" />
+ <el-table-column prop="product" label="浜у搧鍚嶇О" />
+ <el-table-column prop="planQty" label="璁″垝鏁伴噺" width="100" />
+ <el-table-column prop="completedQty" label="瀹屾垚鏁伴噺" width="100" />
+ <el-table-column prop="progress" label="杩涘害" width="150">
+ <template #default="{ row }">
+ <el-progress :percentage="row.progress" :color="getProgressColor(row.progress)" />
+ </template>
+ </el-table-column>
+ <el-table-column prop="line" label="浜х嚎" width="100" />
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="{ row }">
+ <el-tag :type="getTaskStatusType(row.status)">{{ row.status }}</el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { ref, onMounted, onUnmounted, watch } from 'vue'
+import * as echarts from 'echarts'
+import { http } from '@/utils/http'
+import { formatDateTime } from '@/utils'
+
+export default {
+ name: 'Production',
+ setup() {
+ const currentTime = ref('')
+ const trendPeriod = ref('鏃�')
+ const productionChartRef = ref(null)
+ const qualityChartRef = ref(null)
+ const oeeChartRef = ref(null)
+
+ const metrics = ref([
+ { label: '璁″垝浜ч噺', value: '5,000', target: '5,000', progress: 100, icon: 'Calendar', color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
+ { label: '瀹為檯浜ч噺', value: '4,280', target: '5,000', progress: 85.6, icon: 'Check', color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' },
+ { label: '鑹搧鏁伴噺', value: '4,156', target: '4,280', progress: 97.1, icon: 'CircleCheck', color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' },
+ { label: '璁惧杩愯', value: '12/15', target: '15', progress: 80, icon: 'Setting', color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)' }
+ ])
+
+ const productionLines = ref([
+ {
+ name: '鐢熶骇绾� A',
+ status: '杩愯涓�',
+ output: '1,850',
+ devices: [
+ { name: 'CNC鏈哄簥-01', status: '杩愯', temperature: 45, speed: '2400rpm', load: '78%', icon: 'Cpu' },
+ { name: 'CNC鏈哄簥-02', status: '杩愯', temperature: 48, speed: '2200rpm', load: '82%', icon: 'Cpu' },
+ { name: '鏈哄櫒浜�-01', status: '杩愯', temperature: 38, speed: '1200rpm', load: '65%', icon: 'Robot' },
+ { name: '杈撻�佸甫-01', status: '杩愯', temperature: 35, speed: '800rpm', load: '55%', icon: 'Operation' }
+ ]
+ },
+ {
+ name: '鐢熶骇绾� B',
+ status: '杩愯涓�',
+ output: '1,620',
+ devices: [
+ { name: 'CNC鏈哄簥-03', status: '杩愯', temperature: 50, speed: '2500rpm', load: '85%', icon: 'Cpu' },
+ { name: 'CNC鏈哄簥-04', status: '鍋滄満', temperature: 25, speed: '0rpm', load: '0%', icon: 'Cpu' },
+ { name: '鏈哄櫒浜�-02', status: '杩愯', temperature: 40, speed: '1100rpm', load: '70%', icon: 'Robot' },
+ { name: '杈撻�佸甫-02', status: '杩愯', temperature: 36, speed: '750rpm', load: '60%', icon: 'Operation' }
+ ]
+ },
+ {
+ name: '鐢熶骇绾� C',
+ status: '缁存姢涓�',
+ output: '810',
+ devices: [
+ { name: 'CNC鏈哄簥-05', status: '鍋滄満', temperature: 28, speed: '0rpm', load: '0%', icon: 'Cpu' },
+ { name: 'CNC鏈哄簥-06', status: '杩愯', temperature: 42, speed: '2300rpm', load: '75%', icon: 'Cpu' },
+ { name: '鏈哄櫒浜�-03', status: '杩愯', temperature: 39, speed: '1150rpm', load: '68%', icon: 'Robot' },
+ { name: '杈撻�佸甫-03', status: '杩愯', temperature: 34, speed: '850rpm', load: '58%', icon: 'Operation' }
+ ]
+ }
+ ])
+
+ const tasks = ref([
+ { orderNo: 'PO20241224001', product: '绮惧瘑榻胯疆-A鍨�', planQty: 2000, completedQty: 1850, progress: 92.5, line: 'A绾�', status: '鐢熶骇涓�' },
+ { orderNo: 'PO20241224002', product: '浼犲姩杞�-B鍨�', planQty: 1500, completedQty: 1240, progress: 82.7, line: 'B绾�', status: '鐢熶骇涓�' },
+ { orderNo: 'PO20241224003', product: '杞存壙搴�-C鍨�', planQty: 1000, completedQty: 810, progress: 81, line: 'C绾�', status: '鐢熶骇涓�' },
+ { orderNo: 'PO20241224004', product: '杩炴帴鍣�-D鍨�', planQty: 500, completedQty: 380, progress: 76, line: 'A绾�', status: '鐢熶骇涓�' }
+ ])
+
+ let timer
+ const updateTime = () => {
+ currentTime.value = formatDateTime(new Date())
+ }
+
+ const getProgressColor = (progress) => {
+ if (progress >= 90) return '#67c23a'
+ if (progress >= 70) return '#409eff'
+ if (progress >= 50) return '#e6a23c'
+ return '#f56c6c'
+ }
+
+ const getTaskStatusType = (status) => {
+ const map = {
+ '鐢熶骇涓�': 'primary',
+ '宸插畬鎴�': 'success',
+ '寰呮帓浜�': 'info',
+ '鏆傚仠': 'warning'
+ }
+ return map[status] || 'info'
+ }
+
+ // 鍒濆鍖栦骇閲忚秼鍔垮浘
+ const initProductionChart = () => {
+ const chart = echarts.init(productionChartRef.value)
+ const option = {
+ tooltip: { trigger: 'axis' },
+ grid: {
+ left: '3%', right: '4%', bottom: '3%', top: '10%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: ['08:00', '10:00', '12:00', '14:00', '16:00', '18:00'],
+ axisLine: { lineStyle: { color: '#fff' } }
+ },
+ yAxis: {
+ type: 'value',
+ axisLine: { lineStyle: { color: '#fff' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }
+ },
+ series: [
+ {
+ name: '浜ч噺',
+ type: 'bar',
+ data: [420, 680, 850, 920, 780, 630],
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: '#83bff6' },
+ { offset: 1, color: '#188df0' }
+ ]),
+ borderRadius: [5, 5, 0, 0]
+ }
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ // 鍒濆鍖栬壇鍝佺巼鍥�
+ const initQualityChart = () => {
+ const chart = echarts.init(qualityChartRef.value)
+ const option = {
+ tooltip: { trigger: 'item' },
+ series: [
+ {
+ name: '鑹搧鐜�',
+ type: 'gauge',
+ progress: { show: true, width: 18 },
+ axisLine: { lineStyle: { width: 18, color: [[1, '#4facfe']] } },
+ axisTick: { show: false },
+ splitLine: { length: 15, lineStyle: { width: 2, color: '#fff' } },
+ axisLabel: { distance: 25, color: '#fff', fontSize: 20 },
+ anchor: { show: true, showAbove: true, size: 25, itemStyle: { borderWidth: 10 } },
+ detail: {
+ valueAnimation: true,
+ fontSize: 40,
+ offsetCenter: [0, '70%'],
+ color: '#fff',
+ formatter: '{value}%'
+ },
+ data: [{ value: 97.1 }]
+ }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ // 鍒濆鍖朞EE鍥�
+ const initOeeChart = () => {
+ const chart = echarts.init(oeeChartRef.value)
+ const option = {
+ tooltip: { trigger: 'axis' },
+ legend: {
+ data: ['鍙敤鐜�', '琛ㄧ幇鎸囨暟', '璐ㄩ噺鎸囨暟'],
+ textStyle: { color: '#fff' },
+ top: 5
+ },
+ grid: {
+ left: '3%', right: '4%', bottom: '3%', top: '20%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: ['A绾�', 'B绾�', 'C绾�'],
+ axisLine: { lineStyle: { color: '#fff' } }
+ },
+ yAxis: {
+ type: 'value',
+ max: 100,
+ axisLine: { lineStyle: { color: '#fff' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }
+ },
+ series: [
+ { name: '鍙敤鐜�', type: 'bar', data: [92, 88, 75], itemStyle: { color: '#5470c6' } },
+ { name: '琛ㄧ幇鎸囨暟', type: 'bar', data: [85, 82, 78], itemStyle: { color: '#91cc75' } },
+ { name: '璐ㄩ噺鎸囨暟', type: 'bar', data: [97, 96, 95], itemStyle: { color: '#fac858' } }
+ ]
+ }
+ chart.setOption(option)
+ return chart
+ }
+
+ const handleResize = () => {
+ try {
+ const refs = [productionChartRef.value, qualityChartRef.value, oeeChartRef.value]
+ refs.forEach(dom => {
+ if (dom) {
+ const chart = echarts.getInstanceByDom(dom)
+ if (chart) {
+ chart.resize()
+ }
+ }
+ })
+ } catch (error) {
+ console.warn('鍥捐〃閲嶇粯鏃跺嚭閿�:', error)
+ }
+ }
+
+ onMounted(() => {
+ updateTime()
+ timer = setInterval(updateTime, 1000)
+ initProductionChart()
+ initQualityChart()
+ initOeeChart()
+ window.addEventListener('resize', handleResize)
+ })
+
+ onUnmounted(() => {
+ clearInterval(timer)
+ window.removeEventListener('resize', handleResize)
+
+ // 閿�姣佸浘琛ㄥ疄渚�
+ try {
+ const refs = [productionChartRef.value, qualityChartRef.value, oeeChartRef.value]
+ refs.forEach(dom => {
+ if (dom) {
+ const chart = echarts.getInstanceByDom(dom)
+ if (chart) {
+ chart.dispose()
+ }
+ }
+ })
+ } catch (error) {
+ console.warn('鍥捐〃閿�姣佹椂鍑洪敊:', error)
+ }
+ })
+
+ return {
+ currentTime,
+ trendPeriod,
+ metrics,
+ productionLines,
+ tasks,
+ productionChartRef,
+ qualityChartRef,
+ oeeChartRef,
+ getProgressColor,
+ getTaskStatusType
+ }
+ }
+}
+</script>
+
+<style scoped>
+.production-container {
+ width: 100%;
+ height: 100%;
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+ overflow-y: auto;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 20px;
+ height: 60px;
+ background: linear-gradient(90deg, rgba(30, 58, 138, 0.5) 0%, rgba(30, 58, 138, 0.1) 100%);
+ border-radius: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.title {
+ font-size: 24px;
+ font-weight: bold;
+ background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.datetime {
+ font-size: 16px;
+ color: #4facfe;
+}
+
+.nav-menu {
+ display: flex;
+ gap: 15px;
+ padding: 0 20px;
+}
+
+.nav-item {
+ padding: 10px 25px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 8px;
+ color: #fff;
+ text-decoration: none;
+ transition: all 0.3s;
+}
+
+.nav-item:hover {
+ background: rgba(79, 172, 254, 0.2);
+ border-color: #4facfe;
+}
+
+.nav-item.active {
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+ border-color: transparent;
+}
+
+.main-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+}
+
+.metrics-row {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 15px;
+}
+
+.metric-card {
+ position: relative;
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+ overflow: hidden;
+}
+
+.metric-icon {
+ width: 50px;
+ height: 50px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 10px;
+ color: #fff;
+ flex-shrink: 0;
+}
+
+.metric-info {
+ flex: 1;
+}
+
+.metric-value {
+ font-size: 24px;
+ font-weight: bold;
+ margin-bottom: 3px;
+}
+
+.metric-label {
+ font-size: 13px;
+ color: rgba(255, 255, 255, 0.6);
+ margin-bottom: 3px;
+}
+
+.metric-target {
+ font-size: 12px;
+ color: rgba(255, 255, 255, 0.5);
+}
+
+.metric-progress {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ height: 3px;
+ transition: width 0.5s;
+}
+
+.production-lines {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 15px;
+}
+
+.line-card {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.line-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+ padding-bottom: 15px;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.line-title {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.line-name {
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+}
+
+.line-output {
+ font-size: 14px;
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.line-devices {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.device-item {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 12px;
+ background: rgba(0, 0, 0, 0.2);
+ border-radius: 8px;
+}
+
+.device-icon {
+ width: 40px;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 8px;
+ background: rgba(255, 255, 255, 0.05);
+ color: rgba(255, 255, 255, 0.5);
+}
+
+.device-icon.running {
+ background: rgba(103, 194, 58, 0.2);
+ color: #67c23a;
+}
+
+.device-icon.stopped {
+ background: rgba(245, 108, 108, 0.2);
+ color: #f56c6c;
+}
+
+.device-info {
+ flex: 1;
+}
+
+.device-name {
+ font-size: 14px;
+ font-weight: bold;
+ color: #fff;
+ margin-bottom: 3px;
+}
+
+.device-status {
+ font-size: 12px;
+ color: rgba(255, 255, 255, 0.5);
+}
+
+.device-data {
+ display: flex;
+ gap: 15px;
+}
+
+.data-item {
+ text-align: center;
+}
+
+.data-label {
+ font-size: 10px;
+ color: rgba(255, 255, 255, 0.5);
+ display: block;
+ margin-bottom: 2px;
+}
+
+.data-value {
+ font-size: 12px;
+ color: #4facfe;
+ font-weight: bold;
+}
+
+.charts-row {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 15px;
+}
+
+.chart-card {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.card-title {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+}
+
+.chart-container {
+ width: 100%;
+ height: 220px;
+}
+
+.tasks-panel {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.panel-title {
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+ margin-bottom: 15px;
+}
+
+:deep(.el-table) {
+ background: transparent !important;
+}
+
+:deep(.el-table th) {
+ background: rgba(255, 255, 255, 0.1) !important;
+ color: #fff !important;
+ border-color: rgba(255, 255, 255, 0.1) !important;
+}
+
+:deep(.el-table td) {
+ border-color: rgba(255, 255, 255, 0.1) !important;
+}
+
+:deep(.el-table tr) {
+ background: transparent !important;
+}
+
+:deep(.el-table__row:hover td) {
+ background: rgba(255, 255, 255, 0.05) !important;
+}
+
+:deep(.el-progress__text) {
+ color: #fff !important;
+}
+
+:deep(.el-progress-bar__outer) {
+ background: rgba(255, 255, 255, 0.1) !important;
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media screen and (max-width: 1600px) {
+ .metrics-row {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .production-lines {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (max-width: 1366px) {
+ .production-container {
+ padding: 15px;
+ }
+
+ .header {
+ height: 50px;
+ padding: 0 15px;
+ }
+
+ .title {
+ font-size: 18px;
+ }
+
+ .metrics-row {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 10px;
+ }
+
+ .metric-card {
+ padding: 15px;
+ }
+
+ .metric-value {
+ font-size: 20px;
+ }
+
+ .production-lines {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 10px;
+ }
+
+ .line-card {
+ padding: 15px;
+ }
+
+ .charts-row {
+ grid-template-columns: 1fr;
+ gap: 10px;
+ }
+
+ .chart-container {
+ height: 180px;
+ }
+}
+
+@media screen and (max-width: 1024px) {
+ .production-lines {
+ grid-template-columns: 1fr;
+ }
+
+ .device-item {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+ }
+
+ .device-data {
+ width: 100%;
+ justify-content: space-between;
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .production-container {
+ padding: 10px;
+ }
+
+ .header {
+ flex-direction: column;
+ height: auto;
+ padding: 10px;
+ }
+
+ .title {
+ font-size: 16px;
+ }
+
+ .nav-menu {
+ gap: 8px;
+ padding: 0;
+ flex-wrap: wrap;
+ }
+
+ .nav-item {
+ padding: 6px 12px;
+ font-size: 12px;
+ }
+
+ .metrics-row {
+ grid-template-columns: 1fr;
+ }
+
+ .metric-card {
+ padding: 12px;
+ }
+
+ .metric-icon {
+ width: 45px;
+ height: 45px;
+ }
+
+ .metric-value {
+ font-size: 18px;
+ }
+
+ .production-lines {
+ grid-template-columns: 1fr;
+ }
+
+ .line-card {
+ padding: 12px;
+ }
+
+ .device-item {
+ padding: 10px;
+ }
+
+ .device-icon {
+ width: 35px;
+ height: 35px;
+ }
+
+ .device-data {
+ flex-wrap: wrap;
+ gap: 10px;
+ }
+
+ .chart-container {
+ height: 150px;
+ }
+
+ .tasks-panel {
+ padding: 12px;
+ }
+}
+</style>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Warehouse.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Warehouse.vue"
new file mode 100644
index 0000000..d45f5cc
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Warehouse.vue"
@@ -0,0 +1,582 @@
+<template>
+ <div class="warehouse-container">
+ <div class="header">
+ <h1 class="title">浠撳簱鐩戞帶涓績</h1>
+ <div class="datetime">{{ currentTime }}</div>
+ </div>
+
+ <div class="nav-menu">
+ <router-link to="/dashboard" class="nav-item">缁煎悎鐪嬫澘</router-link>
+ <router-link to="/warehouse" class="nav-item active">浠撳簱鐩戞帶</router-link>
+ <router-link to="/production" class="nav-item">鐢熶骇鐩戞帶</router-link>
+ <router-link to="/inventory" class="nav-item">搴撳瓨棰勮</router-link>
+ </div>
+
+ <div class="main-content">
+ <!-- 浠撳簱鍖哄煙鐘舵�� -->
+ <div class="warehouse-areas">
+ <div class="area-card" v-for="area in areas" :key="area.name">
+ <div class="area-header">
+ <span class="area-name">{{ area.name }}</span>
+ <span class="area-capacity">瀹归噺: {{ area.used }}/{{ area.total }}</span>
+ </div>
+ <div class="area-progress">
+ <div class="progress-bar" :style="{ width: (area.used / area.total * 100) + '%', background: area.color }"></div>
+ </div>
+ <div class="area-stats">
+ <div class="stat-item">
+ <span class="stat-label">璐ф灦鏁�</span>
+ <span class="stat-value">{{ area.shelves }}</span>
+ </div>
+ <div class="stat-item">
+ <span class="stat-label">搴撲綅鏁�</span>
+ <span class="stat-value">{{ area.positions }}</span>
+ </div>
+ <div class="stat-item">
+ <span class="stat-label">鍒╃敤鐜�</span>
+ <span class="stat-value">{{ (area.used / area.total * 100).toFixed(1) }}%</span>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 浠撳簱甯冨眬鍥� -->
+ <div class="warehouse-layout">
+ <div class="card-title">浠撳簱瀹炴椂甯冨眬</div>
+ <div class="layout-grid">
+ <div v-for="zone in 8" :key="zone" class="warehouse-zone">
+ <div class="zone-label">{{ String.fromCharCode(64 + zone) }}鍖�</div>
+ <div class="zone-slots">
+ <div v-for="slot in 12" :key="slot"
+ class="slot"
+ :class="getSlotStatus(zone, slot)">
+ {{ String.fromCharCode(64 + zone) }}-{{ Math.ceil(slot / 4) }}-{{ slot % 4 || 4 }}
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="legend">
+ <div class="legend-item">
+ <span class="legend-color occupied"></span>
+ <span>宸插崰鐢�</span>
+ </div>
+ <div class="legend-item">
+ <span class="legend-color empty"></span>
+ <span>绌洪棽</span>
+ </div>
+ <div class="legend-item">
+ <span class="legend-color reserved"></span>
+ <span>棰勭暀</span>
+ </div>
+ <div class="legend-item">
+ <span class="legend-color locked"></span>
+ <span>閿佸畾</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- 娓╂箍搴︾洃鎺� -->
+ <div class="env-monitor">
+ <div class="env-card" v-for="(env, index) in envData" :key="index">
+ <div class="env-icon" :style="{ background: env.gradient }">
+ <el-icon :size="28">
+ <Monitor v-if="index < 3" />
+ <Warning v-else />
+ </el-icon>
+ </div>
+ <div class="env-content">
+ <div class="env-label">{{ env.location }}</div>
+ <div class="env-value">
+ <span class="temp">{{ env.temperature }}掳C</span>
+ <span class="humidity">{{ env.humidity }}%</span>
+ </div>
+ <div class="env-status" :class="env.status === '姝e父' ? 'normal' : 'warning'">
+ {{ env.status }}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { ref, onMounted, onUnmounted } from 'vue'
+import { http } from '@/utils/http'
+import { formatDateTime } from '@/utils'
+
+export default {
+ name: 'Warehouse',
+ setup() {
+ const currentTime = ref('')
+
+ const areas = ref([
+ { name: '鍘熸潗鏂欏尯', used: 2150, total: 3000, shelves: 50, positions: 3000, color: '#5470c6' },
+ { name: '鍗婃垚鍝佸尯', used: 1680, total: 2500, shelves: 42, positions: 2500, color: '#91cc75' },
+ { name: '鎴愬搧鍖�', used: 2890, total: 4000, shelves: 60, positions: 4000, color: '#fac858' },
+ { name: '杈呮枡鍖�', used: 980, total: 1500, shelves: 30, positions: 1500, color: '#ee6666' }
+ ])
+
+ const envData = ref([
+ { location: 'A鍖�-鍘熸枡浠�', temperature: 22.5, humidity: 55, status: '姝e父', icon: 'Thermometer', gradient: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' },
+ { location: 'B鍖�-鍗婃垚鍝佷粨', temperature: 23.8, humidity: 58, status: '姝e父', icon: 'Thermometer', gradient: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' },
+ { location: 'C鍖�-鎴愬搧浠�', temperature: 21.2, humidity: 52, status: '姝e父', icon: 'Thermometer', gradient: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)' },
+ { location: 'D鍖�-杈呮枡浠�', temperature: 26.5, humidity: 68, status: '棰勮', icon: 'Warning', gradient: 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)' }
+ ])
+
+ let timer
+ const updateTime = () => {
+ currentTime.value = formatDateTime(new Date())
+ }
+
+ // 妯℃嫙搴撲綅鐘舵��
+ const getSlotStatus = (zone, slot) => {
+ const random = (zone * slot) % 10
+ if (random < 6) return 'occupied'
+ if (random < 8) return 'empty'
+ if (random < 9) return 'reserved'
+ return 'locked'
+ }
+
+ // 鑾峰彇浠撳簱鏁版嵁
+ const fetchWarehouseData = async () => {
+ try {
+ // 瀹為檯浣跨敤鏃惰皟鐢ㄦ帴鍙�
+ // const res = await http.get('/wms/warehouse/status')
+ } catch (error) {
+ console.error('鑾峰彇浠撳簱鏁版嵁澶辫触:', error)
+ }
+ }
+
+ onMounted(() => {
+ updateTime()
+ timer = setInterval(updateTime, 1000)
+ fetchWarehouseData()
+ })
+
+ onUnmounted(() => {
+ clearInterval(timer)
+ })
+
+ return {
+ currentTime,
+ areas,
+ envData,
+ getSlotStatus
+ }
+ }
+}
+</script>
+
+<style scoped>
+.warehouse-container {
+ width: 100%;
+ height: 100%;
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+ overflow-y: auto;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 20px;
+ height: 60px;
+ background: linear-gradient(90deg, rgba(30, 58, 138, 0.5) 0%, rgba(30, 58, 138, 0.1) 100%);
+ border-radius: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+.title {
+ font-size: 24px;
+ font-weight: bold;
+ background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.datetime {
+ font-size: 16px;
+ color: #4facfe;
+}
+
+.nav-menu {
+ display: flex;
+ gap: 15px;
+ padding: 0 20px;
+}
+
+.nav-item {
+ padding: 10px 25px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 8px;
+ color: #fff;
+ text-decoration: none;
+ transition: all 0.3s;
+}
+
+.nav-item:hover {
+ background: rgba(79, 172, 254, 0.2);
+ border-color: #4facfe;
+}
+
+.nav-item.active {
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+ border-color: transparent;
+}
+
+.main-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+}
+
+.warehouse-areas {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 15px;
+}
+
+.area-card {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.area-header {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 15px;
+}
+
+.area-name {
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+}
+
+.area-capacity {
+ font-size: 14px;
+ color: rgba(255, 255, 255, 0.6);
+}
+
+.area-progress {
+ height: 8px;
+ background: rgba(255, 255, 255, 0.1);
+ border-radius: 4px;
+ margin-bottom: 15px;
+ overflow: hidden;
+}
+
+.progress-bar {
+ height: 100%;
+ border-radius: 4px;
+ transition: width 0.5s;
+}
+
+.area-stats {
+ display: flex;
+ justify-content: space-between;
+}
+
+.stat-item {
+ text-align: center;
+}
+
+.stat-label {
+ font-size: 12px;
+ color: rgba(255, 255, 255, 0.5);
+ display: block;
+ margin-bottom: 5px;
+}
+
+.stat-value {
+ font-size: 16px;
+ font-weight: bold;
+ color: #fff;
+}
+
+.warehouse-layout {
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.card-title {
+ font-size: 16px;
+ font-weight: bold;
+ color: #4facfe;
+ margin-bottom: 15px;
+}
+
+.layout-grid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 15px;
+ margin-bottom: 20px;
+}
+
+.warehouse-zone {
+ background: rgba(0, 0, 0, 0.2);
+ border-radius: 8px;
+ padding: 15px;
+}
+
+.zone-label {
+ text-align: center;
+ font-size: 14px;
+ font-weight: bold;
+ color: #4facfe;
+ margin-bottom: 10px;
+}
+
+.zone-slots {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 8px;
+}
+
+.slot {
+ padding: 8px 4px;
+ font-size: 10px;
+ text-align: center;
+ border-radius: 4px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ color: rgba(255, 255, 255, 0.7);
+ transition: all 0.3s;
+ cursor: pointer;
+}
+
+.slot:hover {
+ transform: scale(1.05);
+}
+
+.slot.occupied {
+ background: rgba(84, 112, 198, 0.5);
+ border-color: #5470c6;
+}
+
+.slot.empty {
+ background: rgba(67, 233, 123, 0.2);
+ border-color: #43e97b;
+}
+
+.slot.reserved {
+ background: rgba(250, 200, 88, 0.3);
+ border-color: #fac858;
+}
+
+.slot.locked {
+ background: rgba(238, 102, 102, 0.3);
+ border-color: #ee6666;
+}
+
+.legend {
+ display: flex;
+ justify-content: center;
+ gap: 30px;
+}
+
+.legend-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 14px;
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.legend-color {
+ width: 20px;
+ height: 20px;
+ border-radius: 4px;
+}
+
+.legend-color.occupied {
+ background: rgba(84, 112, 198, 0.5);
+ border: 1px solid #5470c6;
+}
+
+.legend-color.empty {
+ background: rgba(67, 233, 123, 0.2);
+ border: 1px solid #43e97b;
+}
+
+.legend-color.reserved {
+ background: rgba(250, 200, 88, 0.3);
+ border: 1px solid #fac858;
+}
+
+.legend-color.locked {
+ background: rgba(238, 102, 102, 0.3);
+ border: 1px solid #ee6666;
+}
+
+.env-monitor {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 15px;
+}
+
+.env-card {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ padding: 20px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 10px;
+}
+
+.env-icon {
+ width: 50px;
+ height: 50px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 10px;
+ color: #fff;
+}
+
+.env-content {
+ flex: 1;
+}
+
+.env-label {
+ font-size: 14px;
+ color: rgba(255, 255, 255, 0.6);
+ margin-bottom: 5px;
+}
+
+.env-value {
+ display: flex;
+ gap: 15px;
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 5px;
+}
+
+.env-value .temp {
+ color: #f5576c;
+}
+
+.env-value .humidity {
+ color: #4facfe;
+}
+
+.env-status {
+ font-size: 12px;
+}
+
+.env-status.normal {
+ color: #67c23a;
+}
+
+.env-status.warning {
+ color: #e6a23c;
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media screen and (max-width: 1600px) {
+ .warehouse-areas {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .layout-grid {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (max-width: 1366px) {
+ .warehouse-areas {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 10px;
+ }
+
+ .layout-grid {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 10px;
+ }
+
+ .env-monitor {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (max-width: 1024px) {
+ .warehouse-areas {
+ grid-template-columns: 1fr 1fr;
+ }
+
+ .layout-grid {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .warehouse-zone {
+ padding: 10px;
+ }
+
+ .zone-slots {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .warehouse-container {
+ padding: 10px;
+ }
+
+ .header {
+ flex-direction: column;
+ height: auto;
+ padding: 10px;
+ gap: 10px;
+ }
+
+ .title {
+ font-size: 16px;
+ }
+
+ .warehouse-areas {
+ grid-template-columns: 1fr;
+ }
+
+ .area-card {
+ padding: 12px;
+ }
+
+ .layout-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .zone-slots {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 5px;
+ }
+
+ .slot {
+ font-size: 9px;
+ padding: 6px 2px;
+ }
+
+ .legend {
+ flex-wrap: wrap;
+ gap: 15px;
+ }
+
+ .env-monitor {
+ grid-template-columns: 1fr;
+ }
+
+ .env-card {
+ padding: 12px;
+ }
+}
+</style>
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/vite.config.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/vite.config.js"
new file mode 100644
index 0000000..e92f479
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/vite.config.js"
@@ -0,0 +1,23 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import { resolve } from 'path'
+
+export default defineConfig({
+ plugins: [vue()],
+ resolve: {
+ alias: {
+ '@': resolve(__dirname, 'src')
+ }
+ },
+ server: {
+ port: 3000,
+ open: true,
+ proxy: {
+ '^/api/': {
+ target: 'http://localhost:8080',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, '')
+ }
+ }
+ }
+})
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue"
index 5f1f0be..aa90c8e 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/inbound/extend/OrderStockTake.vue"
@@ -185,7 +185,6 @@
<script setup>
import { ref, reactive, onMounted, nextTick, watch, defineEmits, computed } from "vue";
import { ElMessage, ElTag, ElMessageBox } from "element-plus";
-import { Search, Check, Return } from "@element-plus/icons-vue";
import VolBox from "@/components/basic/VolBox.vue";
import http from "@/api/http";
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/printView.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/printView.vue"
index d5e94f0..4c584fb 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/printView.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/outbound/extend/printView.vue"
@@ -19,6 +19,10 @@
<span class="label">渚涘簲鍟嗙紪鐮�</span>
<span class="value full-width">{{ item.suplierCode }}</span>
</div>
+ <div class="column">
+ <span class="label">鏁伴噺/鎬绘暟</span>
+ <span class="value full-width">{{ item.quantity }}</span>
+ </div>
</div>
<div class="row dual-column">
@@ -37,10 +41,7 @@
<span class="label">瑙勬牸</span>
<span class="value full-width">{{ item.materialSpec }}</span>
</div>
- <div class="column">
- <span class="label">鏁伴噺/鎬绘暟</span>
- <span class="value full-width">{{ item.quantity }}</span>
- </div>
+
</div>
<div class="row dual-column">
@@ -89,6 +90,10 @@
<span class="label-preview">渚涘簲鍟嗙紪鐮�</span>
<span class="value-preview full-width">{{ item.suplierCode }}</span>
</div>
+ <div class="column-preview">
+ <span class="label-preview">鏁伴噺/鎬绘暟</span>
+ <span class="value-preview full-width">{{ item.quantity }}</span>
+ </div>
</div>
<div class="row-preview dual-column">
@@ -107,10 +112,7 @@
<span class="label-preview">瑙勬牸</span>
<span class="value-preview full-width">{{ item.materialSpec }}</span>
</div>
- <div class="column-preview">
- <span class="label-preview">鏁伴噺/鎬绘暟</span>
- <span class="value-preview full-width">{{ item.quantity }}</span>
- </div>
+
</div>
<div class="row-preview dual-column">
@@ -305,7 +307,7 @@
.row {
display: flex !important;
margin-bottom: 1.2mm !important;
- min-height: 6.5mm !important;
+ min-height: 5.5mm !important;
align-items: stretch !important;
}
@@ -318,15 +320,11 @@
flex: 1 !important;
display: flex !important;
align-items: center !important;
- min-height: 5mm !important;
+ min-height: 4mm !important;
}
- .column:first-child {
- margin-right: 2.5mm !important;
- }
.label {
- flex: 0 0 8mm !important;
white-space: nowrap !important;
font-size: 2.5mm !important;
line-height: 1.3 !important;
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
index 62c338f..f786268 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
@@ -281,15 +281,11 @@
return;
}
- // 鏋勯�犺姹傚弬鏁帮細
- // 1. 璇锋眰浣擄細鐩存帴浼犻�抯tockViews鏁扮粍锛堝搴斿悗绔疞ist<StockViewDTO>锛�
- // 2. outStation锛氶�氳繃鏌ヨ鍙傛暟浼犻�掞紙鍥犲悗绔湭鎸囧畾[FromBody]鎺ユ敹璇ュ弬鏁帮級
- const requestBody = stockViews; // 鐩存帴浼犻�掗�変腑鏁扮粍锛堢‘淇濇暟缁勫唴瀵硅薄缁撴瀯涓嶴tockViewDTO涓�鑷达級
+ const requestBody = stockViews;
const outStation = formData.outStation;
- // 鎺ュ彛璇锋眰锛歅ost鏂瑰紡锛岃姹備綋浼爏tockViews鏁扮粍锛宱utStation鎷煎埌URL鏌ヨ鍙傛暟
try {
- // 鎷兼帴鏌ヨ鍙傛暟锛堝鏋渙utStation鏈夌壒娈婂瓧绗︼紝鍙娇鐢╡ncodeURIComponent澶勭悊锛�
+
const url = `api/Task/TakeOutbound?outStation=${encodeURIComponent(outStation)}`;
const x = await this.http.post(
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/printForm.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/printForm.vue"
index 540435a..9490e6a 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/printForm.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/printForm.vue"
@@ -32,25 +32,25 @@
/>
</el-form-item>
- <el-form-item label="瑙勬牸" prop="specification">
+ <el-form-item label="瑙勬牸" prop="materialSpec">
<el-input
- v-model="printForm.specification"
+ v-model="printForm.materialSpec"
placeholder="璇疯緭鍏ョ墿鏂欒鏍�"
clearable
/>
</el-form-item>
- <el-form-item label="鎵瑰彿" prop="batchNumber">
+ <el-form-item label="鎵瑰彿" prop="barcode">
<el-input
- v-model="printForm.batchNumber"
+ v-model="printForm.barcode"
placeholder="璇疯緭鍏ユ壒鍙凤紙鐢熸垚浜岀淮鐮佺敤锛�"
clearable
/>
</el-form-item>
- <el-form-item label="鍘傚尯" prop="factory">
+ <el-form-item label="鍘傚尯" prop="factoryArea">
<el-input
- v-model="printForm.factory"
+ v-model="printForm.factoryArea"
placeholder="璇疯緭鍏ュ巶鍖哄悕绉�"
clearable
/>
@@ -59,33 +59,33 @@
<!-- 绗簩鍒� -->
<el-col :span="12">
- <el-form-item label="渚涘簲鍟嗙紪鐮�" prop="supplierCode">
+ <el-form-item label="渚涘簲鍟嗙紪鐮�" prop="suplierCode">
<el-input
- v-model="printForm.supplierCode"
+ v-model="printForm.suplierCode"
placeholder="璇疯緭鍏ヤ緵搴斿晢缂栫爜"
clearable
/>
</el-form-item>
- <el-form-item label="閲囪喘鍗曞彿" prop="purchaseOrderNo">
+ <el-form-item label="閲囪喘鍗曞彿" prop="pruchaseOrderNo">
<el-input
- v-model="printForm.purchaseOrderNo"
+ v-model="printForm.pruchaseOrderNo"
placeholder="璇疯緭鍏ラ噰璐崟鍙�"
clearable
/>
</el-form-item>
- <el-form-item label="鏁伴噺/鎬绘暟" prop="quantityTotal">
+ <el-form-item label="鏁伴噺/鎬绘暟" prop="quantity">
<el-input
- v-model="printForm.quantityTotal"
+ v-model="printForm.quantity"
placeholder="渚嬶細100/5000"
clearable
/>
</el-form-item>
- <el-form-item label="鎵规" prop="batch">
+ <el-form-item label="鎵规" prop="batchNo">
<el-input
- v-model="printForm.batch"
+ v-model="printForm.batchNo"
placeholder="璇疯緭鍏ユ壒娆″彿"
clearable
/>
@@ -141,14 +141,14 @@
// 琛ㄥ崟鏁版嵁锛堝搴攑rintView鎵�闇�鐨勫弬鏁帮級
printForm: {
materialCode: "", // 鏂欏彿
- supplierCode: "", // 渚涘簲鍟嗙紪鐮�
+ suplierCode: "", // 渚涘簲鍟嗙紪鐮�
materialName: "", // 鍝佸悕
- purchaseOrderNo: "", // 閲囪喘鍗曞彿
- specification: "", // 瑙勬牸
- quantityTotal: "", // 鏁伴噺/鎬绘暟
- batchNumber: "", // 鎵瑰彿锛堜簩缁寸爜鍐呭锛�
- batch: "", // 鎵规
- factory: "", // 鍘傚尯
+ pruchaseOrderNo: "", // 閲囪喘鍗曞彿
+ materialSpec: "", // 瑙勬牸
+ quantity: "", // 鏁伴噺/鎬绘暟
+ barcode: "", // 鎵瑰彿锛堜簩缁寸爜鍐呭锛�
+ batchNo: "", // 鎵规
+ factoryArea: "", // 鍘傚尯
date: "", // 鏃ユ湡锛堥粯璁ゅ綋鍓嶆棩鏈燂級
},
// 鎵撳嵃浠芥暟锛堟敮鎸佹壒閲忕敓鎴愬鏉$浉鍚屾暟鎹級
@@ -157,7 +157,7 @@
formRules: {
materialCode: [{ required: true, message: "璇疯緭鍏ユ枡鍙�", trigger: "blur" }],
materialName: [{ required: true, message: "璇疯緭鍏ュ搧鍚�", trigger: "blur" }],
- batchNumber: [{ required: true, message: "璇疯緭鍏ユ壒鍙�", trigger: "blur" }],
+ barcode: [{ required: true, message: "璇疯緭鍏ユ壒鍙�", trigger: "blur" }],
date: [{ required: true, message: "璇烽�夋嫨鏃ユ湡", trigger: "change" }],
},
};
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db"
index 7daab4d..330b4ee 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/CodeChunks.db"
Binary files differ
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db"
index 2644848..088d42a 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.1204.46620/SemanticSymbols.db"
Binary files differ
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/StockStatusEmun.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/StockStatusEmun.cs"
index 8450c53..8b9f256 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/StockStatusEmun.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_Common/StockEnum/StockStatusEmun.cs"
@@ -107,6 +107,9 @@
[Description("宸叉竻鐞�")]
宸叉竻鐞� = 33,
+ [Description("鎵嬪姩瑙i攣")]
+ 鎵嬪姩瑙i攣 = 66,
+
[Description("杩囨湡")]
杩囨湡 =98,
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs"
index f621cae..051e334 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs"
@@ -134,7 +134,6 @@
OrderNo = inboundOrder.InboundOrderNo,
BusinessType = inboundOrder.BusinessType,
ValidDate = inboundOrder.BusinessType == BusinessTypeEnum.澶栭儴浠撳簱璋冩櫤浠�.ToString() ? item.ValidDate : datevaliDate == null ? null : Convert.ToDateTime(DateTime.Now).AddDays(Convert.ToDouble(datevaliDate.ValidityDays)),
- //ValidDate = datevaliDate == null ? null : DateTime.Now.AddDays(datevaliDate.ValidityDays),
});
item.ReceiptQuantity = item.BarcodeQty;
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
index 19550fb..d244dd5 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
@@ -2483,7 +2483,7 @@
Operator = App.User.UserName,
lineNo = outboundOrderDetail.lineNo,
WarehouseCode = outboundOrderDetail.WarehouseCode ?? "鏃�",
- BarcodeQty = outboundOrderDetail.NoStockOutQty,
+ BarcodeQty = outboundOrderDetail.BarcodeQty,
BarcodeUnit = outboundOrderDetail.BarcodeUnit,
BatchNo = outboundOrderDetail.BatchNo
};
@@ -2618,6 +2618,8 @@
}).ToList()
}).ToList();
outfeedmodel.details.AddRange(groupdata);
+
+ _outStockLockInfoService.DeleteData(detailLocks);
}
//瀛樺偍鍥炰紶鍙傛暟锛屼繚璇佸紓甯告墜鍔ㄥ洖浼�
Dt_InterfaceLog interfaceLog = new Dt_InterfaceLog
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs"
index c7cd1e8..4d53ab6 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs"
@@ -549,7 +549,7 @@
private List<Dt_StockInfo> BuildStockQueryWithInfo(MaterielOutboundCalculationDTO materielCalc, string factoryArea)
{
// 鍩虹鏌ヨ鏉′欢锛氱墿鏂欑紪鍙枫�佹壒娆″彿锛堝鏋滄彁渚涳級銆佸簱瀛樻暟閲�>0
- ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0);
+ ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0 && (x.Status == (int)StockStatusEmun.鍏ュ簱瀹屾垚 || x.Status == (int)StockStatusEmun.鎵嬪姩瑙i攣));
// 鏍规嵁鏉′欢娣诲姞渚涘簲鍟嗙紪鍙峰尮閰嶏紙涓嶄负绌烘椂鎵嶉渶瑕佸尮閰嶏級
if (!string.IsNullOrEmpty(materielCalc.SupplyCode))
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs"
index ec6e218..240cea6 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/InventoryLockJob.cs"
@@ -4,37 +4,25 @@
using WIDESEA_Common.StockEnum;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Basic;
+using WIDESEA_WMSServer.Jobs;
-namespace WIDESEA_WMSServer.Jobs
+namespace WIDESEA_WMSServer
{
[DisallowConcurrentExecution]
public class InventoryLockJob : IJob
{
- private readonly ILogger<ErpJob> _logger;
private readonly ISqlSugarClient _db;
- public InventoryLockJob(ILogger<ErpJob> logger, ISqlSugarClient db )
+ public InventoryLockJob(ISqlSugarClient db)
{
- _logger = logger;
_db = db;
-
}
public Task Execute(IJobExecutionContext context)
{
-
- // 绗竴姝ワ細鏇存柊ValidDate鐨勫師鐢烻QL锛圫QL Server锛�
- // string updateSql = @"
- //UPDATE s
- //SET s.ValidDate = DATEADD(DAY, m.ValidityDays, s.CreateDate)
- //FROM Dt_StockInfoDetail s
- //INNER JOIN Dt_MaterialExpirationDate m ON SUBSTRING(s.MaterielCode, 1, 6) = m.MaterialCode
- //WHERE s.ValidDate IS NULL";
- // int updateValidDateResult = _db.Ado.ExecuteCommand(updateSql);
-
- // 绗簩姝ワ細鏇存柊杩囨湡鐘舵�佺殑鍘熺敓SQL
string updateStatusSql = @"
- UPDATE Dt_StockInfoDetail
- SET Status = 98
- WHERE ValidDate IS NOT NULL AND ValidDate < GETDATE()";
+ UPDATE Dt_StockInfoDetail
+ SET Status = 98
+ WHERE ValidDate IS NOT NULL AND ValidDate < GETDATE()
+ AND Status = 6";
int updateStatusResult = _db.Ado.ExecuteCommand(updateStatusSql);
return Task.CompletedTask;
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/QuartzJobMildd.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/QuartzJobMildd.cs"
index 2c7e0ee..f1099bd 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/QuartzJobMildd.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Jobs/QuartzJobMildd.cs"
@@ -35,6 +35,19 @@
Name = "AgvTaskJob",
TriggerType = 0
},
+ new TasksQz()
+ {
+ Id = 2,
+ AssemblyName = "WIDESEA_WMSServer",
+ ClassName = "InventoryLockJob",
+ CreateTime = DateTime.Now,
+ IntervalSecond = 3,
+ IsDeleted = false,
+ IsStart = false,
+ JobGroup = "WIDESEA_WMSServer",
+ Name = "InventoryLockJob",
+ TriggerType = 0
+ },
};
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs"
index 8152876..d9dfa17 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs"
@@ -188,6 +188,7 @@
});
builder.Services.AddSingleton<IJobFactory, JobFactory>();
builder.Services.AddTransient<AgvTaskJob>();//Job使用瞬时依赖注入
+builder.Services.AddTransient<InventoryLockJob>();//Job使用瞬时依赖注入
builder.Services.AddSingleton<ISchedulerCenter, SchedulerCenterServer>();
builder.Services.AddQuartz(q =>
@@ -202,13 +203,13 @@
.WithIdentity("ErpJob-trigger")
.WithCronSchedule("0 0 10,14,20 * * ?"));
- var inventoryLockJobKey = new JobKey("InventoryLockJob");
- q.AddJob<InventoryLockJob>(opts => opts.WithIdentity(inventoryLockJobKey));
+ //var inventoryLockJobKey = new JobKey("InventoryLockJob");
+ //q.AddJob<InventoryLockJob>(opts => opts.WithIdentity(inventoryLockJobKey));
- q.AddTrigger(opts => opts
- .ForJob(inventoryLockJobKey)
- .WithIdentity("InventoryLockJob-trigger")
- .WithCronSchedule("0 0/10 * * * ?")); // 每10分钟执行一次
+ //q.AddTrigger(opts => opts
+ // .ForJob(inventoryLockJobKey)
+ // .WithIdentity("InventoryLockJob-trigger")
+ // .WithCronSchedule("0 0/10 * * * ?")); // 每10分钟执行一次
});
builder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
--
Gitblit v1.9.3