Merge branch 'htq20251215' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu into htq20251215
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 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? |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 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 模å |
| | | |
| | | æææ¥å£å·²ç»ä¸å°è£
å¨ `/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 |
| | | ``` |
| | | |
| | | ## 代çé
ç½® |
| | | |
| | | å¨ `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 æ¥ç宿´çAPIè°ç¨ç¤ºä¾åäº¤äºæ¼ç¤ºã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # WMSçæ¿ç³»ç» |
| | | |
| | | å¶é ä¸WMSä»åºç®¡çç³»ç»çæ§çæ¿ï¼ä½¿ç¨Vue3+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` ä¸å·²ç»å®ä¹å¥½ææä¸å¡æ¥å£ï¼ |
| | | |
| | | ```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: 'è¿è¡ä¸' }) |
| | | } |
| | | ``` |
| | | |
| | | ## 代çé
ç½® |
| | | |
| | | å¨ `vite.config.js` ä¸å·²é
ç½®API代çï¼ |
| | | |
| | | ```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. ææé¡µé¢é½å¯ç´æ¥è®¿é®ï¼æ éç»å½è®¤è¯ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "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" |
| | | } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "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" |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * API æ¥å£ç»ä¸ç®¡ç |
| | | * æææ¥å£é½å¨è¿éå®ä¹ï¼æ¹ä¾¿ç»´æ¤ |
| | | */ |
| | | 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) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="api-example-container"> |
| | | <div class="header"> |
| | | <h1 class="title">APIè°ç¨ç¤ºä¾</h1> |
| | | <p class="subtitle">å±ç¤ºå¦ä½ä½¿ç¨å°è£
好çhttpå·¥å
·åapi模åè°ç¨å端æ¥å£</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 å·¥å
·åéPOSTè¯·æ± |
| | | 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) |
| | | } |
| | | } |
| | | |
| | | // 使ç¨å°è£
çapi |
| | | 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: å®é
ä¸å¡åºæ¯ - ç»ä»¶ä¸è°ç¨API</span> |
| | | </div> |
| | | <div class="code-block"> |
| | | <pre><code>// å¨Vueç»ä»¶ä¸ä½¿ç¨ |
| | | 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: å¹¶å请æ±ï¼ä½¿ç¨Promise.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: 'æ£å¸¸' } }), 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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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') |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 => { |
| | | // å¯ä»¥å¨è¿éæ·»å tokenç认è¯ä¿¡æ¯ |
| | | // 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 |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // éç¨å·¥å
·å½æ° |
| | | 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 |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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">åºåæ£å¸¸</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 |
| | | } |
| | | |
| | | // åå§åABCåç±»å¾è¡¨ |
| | | 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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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 |
| | | } |
| | | |
| | | // åå§åOEEå¾ |
| | | 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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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 === 'æ£å¸¸' ? '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: 'æ£å¸¸', icon: 'Thermometer', gradient: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' }, |
| | | { location: 'Båº-åæåä»', temperature: 23.8, humidity: 58, status: 'æ£å¸¸', icon: 'Thermometer', gradient: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' }, |
| | | { location: 'Cåº-æåä»', temperature: 21.2, humidity: 52, status: 'æ£å¸¸', 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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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/, '') |
| | | } |
| | | } |
| | | } |
| | | }) |
| | |
| | | <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"; |
| | |
| | | <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"> |
| | |
| | | <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"> |
| | |
| | | <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"> |
| | |
| | | <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"> |
| | |
| | | .row { |
| | | display: flex !important; |
| | | margin-bottom: 1.2mm !important; |
| | | min-height: 6.5mm !important; |
| | | min-height: 5.5mm !important; |
| | | align-items: stretch !important; |
| | | } |
| | | |
| | |
| | | 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; |
| | |
| | | return; |
| | | } |
| | | |
| | | // æé 请æ±åæ°ï¼ |
| | | // 1. 请æ±ä½ï¼ç´æ¥ä¼ éstockViewsæ°ç»ï¼å¯¹åºå端List<StockViewDTO>ï¼ |
| | | // 2. outStationï¼éè¿æ¥è¯¢åæ°ä¼ éï¼å åç«¯æªæå®[FromBody]æ¥æ¶è¯¥åæ°ï¼ |
| | | const requestBody = stockViews; // ç´æ¥ä¼ éé䏿°ç»ï¼ç¡®ä¿æ°ç»å
å¯¹è±¡ç»æä¸StockViewDTOä¸è´ï¼ |
| | | const requestBody = stockViews; |
| | | const outStation = formData.outStation; |
| | | |
| | | // æ¥å£è¯·æ±ï¼Postæ¹å¼ï¼è¯·æ±ä½ä¼ stockViewsæ°ç»ï¼outStationæ¼å°URLæ¥è¯¢åæ° |
| | | try { |
| | | // æ¼æ¥æ¥è¯¢åæ°ï¼å¦æoutStationæç¹æ®å符ï¼å¯ä½¿ç¨encodeURIComponentå¤çï¼ |
| | | |
| | | const url = `api/Task/TakeOutbound?outStation=${encodeURIComponent(outStation)}`; |
| | | |
| | | const x = await this.http.post( |
| | |
| | | /> |
| | | </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 |
| | | /> |
| | |
| | | |
| | | <!-- 第äºå --> |
| | | <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 |
| | | /> |
| | |
| | | // è¡¨åæ°æ®ï¼å¯¹åºprintViewæéçåæ°ï¼ |
| | | printForm: { |
| | | materialCode: "", // æå· |
| | | supplierCode: "", // ä¾åºåç¼ç |
| | | suplierCode: "", // ä¾åºåç¼ç |
| | | materialName: "", // åå |
| | | purchaseOrderNo: "", // éè´åå· |
| | | specification: "", // è§æ ¼ |
| | | quantityTotal: "", // æ°é/æ»æ° |
| | | batchNumber: "", // æ¹å·ï¼äºç»´ç å
å®¹ï¼ |
| | | batch: "", // æ¹æ¬¡ |
| | | factory: "", // ååº |
| | | pruchaseOrderNo: "", // éè´åå· |
| | | materialSpec: "", // è§æ ¼ |
| | | quantity: "", // æ°é/æ»æ° |
| | | barcode: "", // æ¹å·ï¼äºç»´ç å
å®¹ï¼ |
| | | batchNo: "", // æ¹æ¬¡ |
| | | factoryArea: "", // ååº |
| | | date: "", // æ¥æï¼é»è®¤å½åæ¥æï¼ |
| | | }, |
| | | // æå°ä»½æ°ï¼æ¯ææ¹éçæå¤æ¡ç¸åæ°æ®ï¼ |
| | |
| | | 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" }], |
| | | }, |
| | | }; |
| | |
| | | [Description("å·²æ¸
ç")] |
| | | å·²æ¸
ç = 33, |
| | | |
| | | [Description("æå¨è§£é")] |
| | | æå¨è§£é = 66, |
| | | |
| | | [Description("è¿æ")] |
| | | è¿æ =98, |
| | | |
| | |
| | | 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; |
| | |
| | | Operator = App.User.UserName, |
| | | lineNo = outboundOrderDetail.lineNo, |
| | | WarehouseCode = outboundOrderDetail.WarehouseCode ?? "æ ", |
| | | BarcodeQty = outboundOrderDetail.NoStockOutQty, |
| | | BarcodeQty = outboundOrderDetail.BarcodeQty, |
| | | BarcodeUnit = outboundOrderDetail.BarcodeUnit, |
| | | BatchNo = outboundOrderDetail.BatchNo |
| | | }; |
| | |
| | | }).ToList() |
| | | }).ToList(); |
| | | outfeedmodel.details.AddRange(groupdata); |
| | | |
| | | _outStockLockInfoService.DeleteData(detailLocks); |
| | | } |
| | | //åå¨åä¼ åæ°ï¼ä¿è¯å¼å¸¸æå¨åä¼ |
| | | Dt_InterfaceLog interfaceLog = new Dt_InterfaceLog |
| | |
| | | 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.æå¨è§£é)); |
| | | |
| | | // æ ¹æ®æ¡ä»¶æ·»å ä¾åºåç¼å·å¹é
ï¼ä¸ä¸ºç©ºæ¶æéè¦å¹é
ï¼ |
| | | if (!string.IsNullOrEmpty(materielCalc.SupplyCode)) |
| | |
| | | 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çåçSQLï¼SQL 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; |
| | |
| | | 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 |
| | | }, |
| | | |
| | | }; |
| | | |
| | |
| | | }); |
| | | builder.Services.AddSingleton<IJobFactory, JobFactory>(); |
| | | builder.Services.AddTransient<AgvTaskJob>();//Job使ç¨ç¬æ¶ä¾èµæ³¨å
¥ |
| | | builder.Services.AddTransient<InventoryLockJob>();//Job使ç¨ç¬æ¶ä¾èµæ³¨å
¥ |
| | | builder.Services.AddSingleton<ISchedulerCenter, SchedulerCenterServer>(); |
| | | |
| | | builder.Services.AddQuartz(q => |
| | |
| | | .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); |