Merge branch 'htq20251215' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu into htq20251215
| | |
| | | |
| | | // å建axioså®ä¾ |
| | | const request = axios.create({ |
| | | baseURL: '/api', |
| | | baseURL: 'http://localhost:9291', |
| | | timeout: 30000, |
| | | headers: { |
| | | 'Content-Type': 'application/json;charset=UTF-8' |
| | |
| | | // æ ¹æ®å®é
å端è¿åæ ¼å¼è°æ´ |
| | | // å设å端è¿åæ ¼å¼ä¸º { code: 200, data: {}, message: '' } |
| | | if (res.code !== undefined && res.code !== 200) { |
| | | ElMessage.error(res.message || '请æ±å¤±è´¥') |
| | | return Promise.reject(new Error(res.message || '请æ±å¤±è´¥')) |
| | | |
| | | } |
| | | |
| | | return res |
| | |
| | | <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"> |
| | | <el-table :data="showTaskList" style="width: 100%" :height="tableHeight"> |
| | | <el-table-column prop="taskNum" label="ä»»å¡å·" /> |
| | | <el-table-column prop="taskStatus" label="ä»»å¡ç¶æ" width="120"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="row.type === 'å
¥åº' ? 'success' : 'warning'">{{ row.type }}</el-tag> |
| | | <div class="status-container" :class="getStatusClass(row.taskStatus)"> |
| | | <div class="status-dot"></div> |
| | | <span class="status-text">{{ getTaskStatusText(row.taskStatus) }}</span> |
| | | </div> |
| | | </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"> |
| | | <el-table-column prop="taskType" label="ä»»å¡ç±»å" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getStatusType(row.status)">{{ row.status }}</el-tag> |
| | | <div class="type-container" :class="getTypeClass(row.taskType)"> |
| | | <el-icon class="type-icon"> |
| | | <Box v-if="getTypeClass(row.taskType) === 'type-inbound'" /> |
| | | <Upload v-else-if="getTypeClass(row.taskType) === 'type-outbound'" /> |
| | | <Refresh v-else-if="getTypeClass(row.taskType) === 'type-transfer'" /> |
| | | <Operation v-else /> |
| | | </el-icon> |
| | | <span class="type-text">{{ getTaskTypeText(row.taskType) }}</span> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="operator" label="æä½å" width="100" /> |
| | | <el-table-column prop="time" label="æ¶é´" width="160" /> |
| | | <el-table-column prop="palletCode" label="æçç¼å·" /> |
| | | <el-table-column prop="sourceAddress" label="èµ·ç¹ä½ç½®"/> |
| | | <el-table-column prop="targetAddress" label="ç»ç¹ä½ç½®"/> |
| | | <el-table-column prop="createDate" label="å建æ¶é´"/> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { ref, onMounted, onUnmounted } from 'vue' |
| | | import { ref, onMounted, onUnmounted, nextTick } from 'vue' |
| | | import * as echarts from 'echarts' |
| | | import { http } from '@/utils/http' |
| | | import { formatDateTime } from '@/utils' |
| | | import { ElMessage } from 'element-plus' |
| | | // 导å
¥Element Plus徿 |
| | | import { |
| | | DataBoard, Box, Operation, Warning, Download, Upload, List, |
| | | Top, Bottom, Refresh, ArrowRight, Clock |
| | | } from '@element-plus/icons-vue' |
| | | |
| | | export default { |
| | | name: 'Dashboard', |
| | | components: { |
| | | DataBoard, Box, Operation, Warning, Download, Upload, List, |
| | | Top, Bottom, Refresh, ArrowRight, Clock |
| | | }, |
| | | setup() { |
| | | const currentTime = ref('') |
| | | const trendChartRef = ref(null) |
| | | const categoryChartRef = ref(null) |
| | | const efficiencyChartRef = ref(null) |
| | | const tableHeight = ref(200) |
| | | |
| | | // å¾è¡¨å®ä¾å¼ç¨ |
| | | const trendChart = ref(null) |
| | | const categoryChart = ref(null) |
| | | const efficiencyChart = ref(null) |
| | | |
| | | // å端è¿åæ°æ®ï¼ååºå¼ï¼ |
| | | const bigscreendata = ref({ |
| | | totalStockQuantity: 0, |
| | | unOutBoundOrderCount: 0, |
| | | dailyCompletionRate: 0, |
| | | unhandledExceptionCount: 0, |
| | | locationUtilizationRate: 0, |
| | | inStockPallet: 0, |
| | | freeStockPallet: 0, |
| | | dailyInOutBoundList: [], |
| | | taskList: [], |
| | | inboundCount: 0, |
| | | outboundCount: 0, |
| | | inventoryLocationDist: [], |
| | | completeTask: [] |
| | | }) |
| | | |
| | | // ä»»å¡ç¶ææ å° |
| | | const taskStatusMap = { |
| | | 100: "æ°å»º", |
| | | 105: "å·²åé", |
| | | 200: "å åæºå¾
æ§è¡", |
| | | 210: "å åæºæ§è¡ä¸", |
| | | 220: "å åæºå®æ", |
| | | 400: "è¾é线å¾
æ§è¡", |
| | | 410: "è¾é线æ§è¡ä¸", |
| | | 420: "è¾éçº¿å®æ", |
| | | 300: "AGVå¾
æ§è¡", |
| | | 310: "AGVæ§è¡ä¸", |
| | | 315: "AGVåè´§ä¸", |
| | | 320: "AGVå¾
ç»§ç»æ§è¡", |
| | | 325: "AGVæ¾è´§ä¸", |
| | | 330: "AGV宿", |
| | | 900: "ä»»å¡å®æ", |
| | | 970: "ä»»å¡æèµ·", |
| | | 980: "ä»»å¡åæ¶", |
| | | 990: "ä»»å¡å¼å¸¸", |
| | | 110: "æåæºæ§è¡ä¸" |
| | | } |
| | | |
| | | // å
³é®ææ ï¼ååºå¼ï¼ |
| | | 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 } |
| | | { |
| | | label: 'æ»åºåé', |
| | | value: 0, |
| | | icon: 'Box', |
| | | color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', |
| | | trend: 8.5 |
| | | }, |
| | | { |
| | | label: '仿¥å
¥åº', |
| | | value: 0, |
| | | icon: 'Download', |
| | | color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)', |
| | | trend: 12.3 |
| | | }, |
| | | { |
| | | label: '仿¥åºåº', |
| | | value: 0, |
| | | icon: 'Upload', |
| | | color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)', |
| | | trend: -3.2 |
| | | }, |
| | | { |
| | | label: 'å¾
å¤çä»»å¡', |
| | | value: 0, |
| | | icon: 'List', |
| | | color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)', |
| | | trend: 5.7 |
| | | } |
| | | ]) |
| | | |
| | | // ä»»å¡å表ç¸å
³ |
| | | const taskList = ref([]) |
| | | const showTaskList = ref([]) |
| | | const currentTaskIndex = ref(7) // åå§ä»ç¬¬8æ¡å¼å§ï¼å7æ¡é»è®¤æ¾ç¤ºï¼ |
| | | let taskCarouselTimer = null |
| | | |
| | | // èªå¨å·æ°ç¸å
³é
ç½® |
| | | const lastInboundToday = ref(0) // ä¸ä¸æ¬¡å½å¤©å
¥åºé |
| | | const lastOutboundToday = ref(0) // ä¸ä¸æ¬¡å½å¤©åºåºé |
| | | const refreshInterval = ref(5 * 60 * 1000) // 宿¶å·æ°é´éï¼5åéï¼ |
| | | const minRefreshGap = ref(30 * 1000) // æå°å·æ°é´éï¼é²æï¼30ç§ï¼ |
| | | let lastRefreshTime = ref(0) // ä¸ä¸æ¬¡å·æ°æ¶é´ |
| | | let autoRefreshTimer = null // èªå¨å·æ°å®æ¶å¨ |
| | | |
| | | // è·åä»»å¡ç¶æææ¬ |
| | | const getTaskStatusText = (statusNum) => { |
| | | if (statusNum === undefined || statusNum === null || isNaN(statusNum)) { |
| | | return "æªç¥ç¶æ"; |
| | | } |
| | | return taskStatusMap[statusNum] || "æªç¥ç¶æ"; |
| | | } |
| | | |
| | | // å¯å¨ä»»å¡è½®æ |
| | | const startTaskCarousel = () => { |
| | | if (taskCarouselTimer) clearInterval(taskCarouselTimer); |
| | | |
| | | const totalTask = bigscreendata.value.taskList.length; |
| | | if (totalTask <= 7) { // 任塿°<=7æ¶ä¸è½®æ |
| | | showTaskList.value = [...bigscreendata.value.taskList]; |
| | | return; |
| | | } |
| | | |
| | | taskCarouselTimer = setInterval(() => { |
| | | const tableElement = document.querySelector('.el-table'); |
| | | if (tableElement) { |
| | | tableElement.classList.add('flash-effect'); |
| | | setTimeout(() => { |
| | | tableElement.classList.remove('flash-effect'); |
| | | }, 600); |
| | | } |
| | | |
| | | // æ°å¢ä¸1æ¡ï¼å 餿å1æ¡ï¼ä¿æ7æ¡æ¾ç¤ºï¼ |
| | | showTaskList.value.push(bigscreendata.value.taskList[currentTaskIndex.value]); |
| | | showTaskList.value.shift(); |
| | | |
| | | // 循ç¯ç´¢å¼ |
| | | currentTaskIndex.value++; |
| | | if (currentTaskIndex.value >= totalTask) { |
| | | currentTaskIndex.value = 0; |
| | | } |
| | | }, 5000); // 5ç§è½®æä¸æ¬¡ |
| | | } |
| | | |
| | | // è·åä»»å¡ç±»åææ¬ |
| | | const getTaskTypeText = (taskTypeNum) => { |
| | | if (!taskTypeNum || isNaN(taskTypeNum)) return "æªç¥ç±»å"; |
| | | |
| | | if (taskTypeNum >= 500 && taskTypeNum < 900) return "å
¥åº"; |
| | | if (taskTypeNum >= 100 && taskTypeNum < 500) return "åºåº"; |
| | | if (taskTypeNum >= 900 && taskTypeNum < 1000) return "ç§»åº"; |
| | | return "å
¶ä»ä½ä¸"; |
| | | } |
| | | |
| | | // è·åä»»å¡ç¶ææ ·å¼ç±» |
| | | const getStatusClass = (statusNum) => { |
| | | if (statusNum === undefined || statusNum === null || isNaN(statusNum)) { |
| | | return "status-unknown"; |
| | | } |
| | | |
| | | if (statusNum >= 900) return "status-completed"; // 宿 |
| | | if (statusNum >= 400) return "status-processing"; // è¾é线æ§è¡ä¸ |
| | | if (statusNum >= 300) return "status-processing"; // AGVæ§è¡ä¸ |
| | | if (statusNum >= 200) return "status-processing"; // å åæºæ§è¡ä¸ |
| | | if (statusNum >= 100) return "status-pending"; // æ°å»ºãå·²åé |
| | | if (statusNum === 970) return "status-suspended"; // æèµ· |
| | | if (statusNum === 980) return "status-canceled"; // åæ¶ |
| | | if (statusNum === 990) return "status-error"; // å¼å¸¸ |
| | | |
| | | return "status-unknown"; |
| | | } |
| | | |
| | | // è·åä»»å¡ç±»åæ ·å¼ç±» |
| | | const getTypeClass = (taskTypeNum) => { |
| | | if (!taskTypeNum || isNaN(taskTypeNum)) return "type-unknown"; |
| | | |
| | | if (taskTypeNum >= 500 && taskTypeNum < 900) return "type-inbound"; // å
¥åº |
| | | if (taskTypeNum >= 100 && taskTypeNum < 500) return "type-outbound"; // åºåº |
| | | if (taskTypeNum >= 900 && taskTypeNum < 1000) return "type-transfer"; // ç§»åº |
| | | |
| | | return "type-other"; // å
¶ä»ä½ä¸ |
| | | } |
| | | |
| | | // ä»å端è·åæ°æ® |
| | | const fetchBigGreenData = async () => { |
| | | try { |
| | | const res = await http.get('/api/BigScreen/GetBigGreenData'); |
| | | console.log('大屿°æ®', res); |
| | | bigscreendata.value = res.data || res; |
| | | |
| | | updateMetrics(); |
| | | |
| | | taskList.value = bigscreendata.value.taskList || []; |
| | | showTaskList.value = taskList.value.slice(0, 7); |
| | | startTaskCarousel(); |
| | | |
| | | // æ°æ®å è½½å®æååå§åå¾è¡¨ |
| | | nextTick(() => { |
| | | initEfficiencyChart(); |
| | | initTrendChart(); |
| | | initCategoryChart(); |
| | | }); |
| | | } catch (error) { |
| | | console.error('è·å大屿°æ®å¤±è´¥:', error); |
| | | ElMessage.error('è·åæ°æ®å¤±è´¥ï¼è¯·ç¨åéè¯'); |
| | | } |
| | | }; |
| | | |
| | | // æ´æ°å
³é®ææ |
| | | const updateMetrics = () => { |
| | | metrics.value[0].value = bigscreendata.value.totalStockQuantity || 0 |
| | | metrics.value[1].value = bigscreendata.value.inboundCount || 0 |
| | | metrics.value[2].value = bigscreendata.value.outboundCount || 0 |
| | | metrics.value[3].value = bigscreendata.value.unOutBoundOrderCount || 0 |
| | | } |
| | | |
| | | // æ´æ°æ¶é´ |
| | | let timer |
| | |
| | | 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) |
| | | if (!trendChartRef.value) return |
| | | |
| | | trendChart.value = echarts.init(trendChartRef.value) |
| | | |
| | | // ç´æ¥ä»å端è·åæ¥æåæ°æ® |
| | | const dates = [] |
| | | const inboundData = [] |
| | | const outboundData = [] |
| | | |
| | | if (bigscreendata.value.dailyInOutBoundList && bigscreendata.value.dailyInOutBoundList.length > 0) { |
| | | bigscreendata.value.dailyInOutBoundList.forEach(item => { |
| | | dates.push(item.date) // ç´æ¥ä½¿ç¨å端è¿åçæ¥æ |
| | | inboundData.push(item.dailyInboundQuantity || 0) |
| | | outboundData.push(item.dailyOutboundQuantity || 0) |
| | | }) |
| | | } |
| | | |
| | | const hasData = dates.length > 0 |
| | | |
| | | const option = { |
| | | tooltip: { trigger: 'axis' }, |
| | | |
| | | legend: { |
| | | data: ['å
¥åºé', 'åºåºé'], |
| | | textStyle: { color: '#fff' } |
| | | }, |
| | | grid: { |
| | | left: '3%', right: '4%', bottom: '3%', top: '15%', |
| | | 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' } } |
| | | data: dates, |
| | | axisLine: { lineStyle: { color: '#fff' } }, |
| | | axisLabel: { color: '#fff' } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { lineStyle: { color: '#fff' } }, |
| | | splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } } |
| | | splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }, |
| | | axisLabel: { color: '#fff' }, |
| | | min: 0 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'å
¥åºé', |
| | | type: 'line', |
| | | smooth: true, |
| | | data: [120, 200, 450, 680, 520, 780, 650], |
| | | itemStyle: { color: '#43e97b' }, |
| | | data: inboundData, |
| | | itemStyle: { color: '#5470c6' }, |
| | | lineStyle: { color: '#5470c6' }, |
| | | 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)' } |
| | | { offset: 0, color: 'rgba(84, 112, 198, 0.5)' }, |
| | | { offset: 1, color: 'rgba(84, 112, 198, 0)' } |
| | | ]) |
| | | } |
| | | }, |
| | | showSymbol: hasData, |
| | | symbol: 'circle', |
| | | symbolSize: 6 |
| | | }, |
| | | { |
| | | name: 'åºåºé', |
| | | type: 'line', |
| | | smooth: true, |
| | | data: [80, 150, 380, 520, 420, 650, 580], |
| | | itemStyle: { color: '#4facfe' }, |
| | | data: outboundData, |
| | | itemStyle: { color: '#91cc75' }, |
| | | lineStyle: { color: '#91cc75' }, |
| | | 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)' } |
| | | { offset: 0, color: 'rgba(145, 204, 117, 0.5)' }, |
| | | { offset: 1, color: 'rgba(145, 204, 117, 0)' } |
| | | ]) |
| | | } |
| | | }, |
| | | showSymbol: hasData, |
| | | symbol: 'circle', |
| | | symbolSize: 6 |
| | | } |
| | | ] |
| | | ], |
| | | |
| | | } |
| | | chart.setOption(option) |
| | | return chart |
| | | |
| | | trendChart.value.setOption(option) |
| | | return trendChart.value |
| | | } |
| | | |
| | | // åå§ååç±»å æ¯å¾ |
| | | const initCategoryChart = () => { |
| | | const chart = echarts.init(categoryChartRef.value) |
| | | if (!categoryChartRef.value) return |
| | | |
| | | categoryChart.value = echarts.init(categoryChartRef.value) |
| | | |
| | | const option = { |
| | | tooltip: { trigger: 'item' }, |
| | | legend: { |
| | |
| | | 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' } } |
| | | ] |
| | | data: bigscreendata.value.inventoryLocationDist.length > 0 |
| | | ? bigscreendata.value.inventoryLocationDist |
| | | : [ |
| | | { 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 |
| | | |
| | | categoryChart.value.setOption(option) |
| | | return categoryChart.value |
| | | } |
| | | |
| | | // åå§åæçç»è®¡å¾ |
| | | 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 |
| | | // åå§åæçç»è®¡å¾ |
| | | // åå§åæçç»è®¡å¾ï¼ä¿®å¤çï¼ |
| | | const initEfficiencyChart = () => { |
| | | if (!efficiencyChartRef.value) { |
| | | console.warn('æçå¾è¡¨å®¹å¨ä¸åå¨ï¼'); |
| | | return; |
| | | } |
| | | |
| | | // ç¡®ä¿å®¹å¨æé«åº¦ |
| | | efficiencyChartRef.value.style.height = '250px'; |
| | | efficiencyChartRef.value.style.width = '100%'; |
| | | |
| | | // 鿝æ§å®ä¾ |
| | | if (efficiencyChart.value) { |
| | | efficiencyChart.value.dispose(); |
| | | } |
| | | |
| | | // åå§å ECharts |
| | | efficiencyChart.value = echarts.init(efficiencyChartRef.value); |
| | | |
| | | // æ°æ®å¤ç |
| | | const taskData = { |
| | | 'å
¥åº': 0, |
| | | 'åºåº': 0 |
| | | }; |
| | | bigscreendata.value.completeTask.forEach(item => { |
| | | if (item.taskType && typeof item.count === 'number') { |
| | | taskData[item.taskType] = item.count; |
| | | } |
| | | }); |
| | | |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { type: 'shadow' }, |
| | | formatter: params => { |
| | | return params.map(p => `${p.seriesName}: ${p.value || 0} å`).join('<br/>'); |
| | | } |
| | | }, |
| | | grid: { |
| | | left: '5%', |
| | | right: '5%', |
| | | bottom: '10%', |
| | | top: '15%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['å
¥åºä½ä¸', 'åºåºä½ä¸'], |
| | | axisLine: { lineStyle: { color: '#fff' } }, |
| | | axisLabel: { color: '#fff' } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: '宿æ°é(å)', |
| | | nameTextStyle: { color: '#fff' }, |
| | | axisLine: { lineStyle: { color: '#fff' } }, |
| | | splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }, |
| | | axisLabel: { color: '#fff' }, |
| | | min: 0 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'ä½ä¸æ°é', |
| | | data: [taskData['å
¥åº'], taskData['åºåº']], |
| | | 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] |
| | | }, |
| | | 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] |
| | | } |
| | | label: { |
| | | show: true, |
| | | position: 'top', |
| | | color: '#fff', |
| | | fontSize: 12 |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | efficiencyChart.value.setOption(option, true); |
| | | console.log('æçå¾è¡¨æ¸²æå®æï¼æ°æ®ï¼', taskData); |
| | | }; |
| | | |
| | | // å·æ°å¾è¡¨æ°æ®ï¼isDataChangeï¼æ¯å¦æ¯æ°æ®åå导è´çå·æ°ï¼ |
| | | const refreshCharts = (isDataChange = false) => { |
| | | // æ°æ®ååæ¶æ·»å éªçææ |
| | | if (isDataChange) { |
| | | const chartElements = [trendChartRef.value, categoryChartRef.value, efficiencyChartRef.value] |
| | | chartElements.forEach(el => { |
| | | if (el) { |
| | | el.classList.add('flash-effect'); |
| | | setTimeout(() => el.classList.remove('flash-effect'), 600); |
| | | } |
| | | ] |
| | | }) |
| | | } |
| | | chart.setOption(option) |
| | | return chart |
| | | |
| | | // 鿝æ§å¾è¡¨å®ä¾ |
| | | if (trendChart.value) trendChart.value.dispose() |
| | | if (categoryChart.value) categoryChart.value.dispose() |
| | | if (efficiencyChart.value) efficiencyChart.value.dispose() |
| | | |
| | | // éæ°åå§åå¾è¡¨ |
| | | initTrendChart() |
| | | initCategoryChart() |
| | | initEfficiencyChart() |
| | | } |
| | | |
| | | // è·åä»»å¡åè¡¨æ°æ® |
| | | 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() |
| | | fetchBigGreenData() |
| | | } |
| | | |
| | | // çªå£å¤§å°æ¹åæ¶éç»å¾è¡¨ |
| | | // å¯å¨èªå¨å·æ° |
| | | const startAutoRefresh = () => { |
| | | if (autoRefreshTimer) clearInterval(autoRefreshTimer) |
| | | autoRefreshTimer = setInterval(() => { |
| | | console.log('宿¶å·æ°æ°æ®:', new Date().toLocaleString()) |
| | | fetchBigGreenData() |
| | | }, refreshInterval.value) |
| | | } |
| | | |
| | | // çªå£å¤§å°æ¹åæ¶éç»å¾è¡¨åè°æ´è¡¨æ ¼é«åº¦ |
| | | 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() |
| | | } |
| | | } |
| | | const windowHeight = window.innerHeight |
| | | const headerHeight = 60 |
| | | const navHeight = 50 |
| | | const metricsHeight = 120 |
| | | const chartsHeight = 300 |
| | | const padding = 80 |
| | | |
| | | const availableHeight = windowHeight - headerHeight - navHeight - metricsHeight - chartsHeight - padding |
| | | tableHeight.value = Math.max(200, Math.min(availableHeight, 400)) |
| | | |
| | | // éç»å¾è¡¨ |
| | | const charts = [trendChart.value, categoryChart.value, efficiencyChart.value] |
| | | charts.forEach(chart => { |
| | | if (chart) chart.resize() |
| | | }) |
| | | } catch (error) { |
| | | console.warn('å¾è¡¨éç»æ¶åºé:', error) |
| | |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // åå§åæ¶é´ |
| | | updateTime() |
| | | timer = setInterval(updateTime, 1000) |
| | | |
| | | initTrendChart() |
| | | initCategoryChart() |
| | | initEfficiencyChart() |
| | | fetchTaskList() |
| | | |
| | | // åå§åæ°æ®åå¾è¡¨ |
| | | fetchBigGreenData() |
| | | |
| | | nextTick(() => { |
| | | initTrendChart() |
| | | initCategoryChart() |
| | | initEfficiencyChart() |
| | | handleResize() |
| | | startAutoRefresh() // å¯å¨èªå¨å·æ° |
| | | }) |
| | | |
| | | // çå¬çªå£å¤§å°åå |
| | | window.addEventListener('resize', handleResize) |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | // æ¸
餿æå®æ¶å¨ |
| | | clearInterval(timer) |
| | | if (taskCarouselTimer) clearInterval(taskCarouselTimer) |
| | | if (autoRefreshTimer) clearInterval(autoRefreshTimer) |
| | | |
| | | // ç§»é¤çªå£çå¬ |
| | | 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() |
| | | } |
| | | } |
| | | }) |
| | | if (trendChart.value) trendChart.value.dispose() |
| | | if (categoryChart.value) categoryChart.value.dispose() |
| | | if (efficiencyChart.value) efficiencyChart.value.dispose() |
| | | } catch (error) { |
| | | console.warn('å¾è¡¨éæ¯æ¶åºé:', error) |
| | | } |
| | |
| | | currentTime, |
| | | metrics, |
| | | taskList, |
| | | showTaskList, |
| | | trendChartRef, |
| | | categoryChartRef, |
| | | efficiencyChartRef, |
| | | getStatusType, |
| | | tableHeight, |
| | | getTaskTypeText, |
| | | getTaskStatusText, |
| | | getStatusClass, |
| | | getTypeClass, |
| | | refreshData |
| | | } |
| | | } |
| | |
| | | <style scoped> |
| | | .dashboard-container { |
| | | width: 100%; |
| | | height: 100%; |
| | | height: 100vh; |
| | | padding: 20px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | overflow-y: auto; |
| | | background-color: #0a0e27; |
| | | } |
| | | |
| | | .header { |
| | |
| | | .metric-value { |
| | | font-size: 28px; |
| | | font-weight: bold; |
| | | color: #fff; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | |
| | | border-radius: 10px; |
| | | } |
| | | |
| | | /* Element Plus Table æ ·å¼è¦ç */ |
| | | :deep(.el-table) { |
| | | background: transparent !important; |
| | | } |
| | |
| | | |
| | | :deep(.el-table td) { |
| | | border-color: rgba(255, 255, 255, 0.1) !important; |
| | | color: rgba(255, 255, 255, 0.9) !important; |
| | | } |
| | | |
| | | :deep(.el-table tr) { |
| | |
| | | |
| | | :deep(.el-table--enable-row-hover .el-table__body tr:hover > td) { |
| | | background: rgba(255, 255, 255, 0.05) !important; |
| | | } |
| | | |
| | | /* ä»»å¡ç¶ææ ·å¼ */ |
| | | .status-container { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 4px 10px; |
| | | border-radius: 20px; |
| | | position: relative; |
| | | overflow: hidden; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .status-dot { |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | margin-right: 6px; |
| | | position: relative; |
| | | } |
| | | |
| | | .status-dot::after { |
| | | content: ''; |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 100%; |
| | | border-radius: 50%; |
| | | animation: pulse 2s infinite; |
| | | } |
| | | |
| | | .status-text { |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | /* ä¸åç¶æçé¢è² */ |
| | | .status-completed { |
| | | background: rgba(103, 194, 58, 0.15); |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .status-completed .status-dot { |
| | | background: #67c23a; |
| | | } |
| | | |
| | | .status-completed .status-dot::after { |
| | | background: rgba(103, 194, 58, 0.5); |
| | | } |
| | | |
| | | .status-processing { |
| | | background: rgba(64, 158, 255, 0.15); |
| | | color: #409eff; |
| | | } |
| | | |
| | | .status-processing .status-dot { |
| | | background: #409eff; |
| | | } |
| | | |
| | | .status-processing .status-dot::after { |
| | | background: rgba(64, 158, 255, 0.5); |
| | | } |
| | | |
| | | .status-pending { |
| | | background: rgba(144, 147, 153, 0.15); |
| | | color: #909399; |
| | | } |
| | | |
| | | .status-pending .status-dot { |
| | | background: #909399; |
| | | } |
| | | |
| | | .status-pending .status-dot::after { |
| | | background: rgba(144, 147, 153, 0.5); |
| | | } |
| | | |
| | | .status-suspended { |
| | | background: rgba(230, 162, 60, 0.15); |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | .status-suspended .status-dot { |
| | | background: #e6a23c; |
| | | } |
| | | |
| | | .status-suspended .status-dot::after { |
| | | background: rgba(230, 162, 60, 0.5); |
| | | } |
| | | |
| | | .status-canceled { |
| | | background: rgba(144, 147, 153, 0.15); |
| | | color: #909399; |
| | | } |
| | | |
| | | .status-canceled .status-dot { |
| | | background: #909399; |
| | | } |
| | | |
| | | .status-canceled .status-dot::after { |
| | | background: rgba(144, 147, 153, 0.5); |
| | | } |
| | | |
| | | .status-error { |
| | | background: rgba(245, 108, 108, 0.15); |
| | | color: #f56c6c; |
| | | } |
| | | |
| | | .status-error .status-dot { |
| | | background: #f56c6c; |
| | | } |
| | | |
| | | .status-error .status-dot::after { |
| | | background: rgba(245, 108, 108, 0.5); |
| | | } |
| | | |
| | | /* ä»»å¡ç±»åæ ·å¼ */ |
| | | .type-container { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 4px 10px; |
| | | border-radius: 20px; |
| | | position: relative; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .type-icon { |
| | | margin-right: 6px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .type-text { |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | /* ä¸åç±»åçé¢è² */ |
| | | .type-inbound { |
| | | background: rgba(103, 194, 58, 0.15); |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .type-outbound { |
| | | background: rgba(230, 162, 60, 0.15); |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | .type-transfer { |
| | | background: rgba(64, 158, 255, 0.15); |
| | | color: #409eff; |
| | | } |
| | | |
| | | .type-other { |
| | | background: rgba(144, 147, 153, 0.15); |
| | | color: #909399; |
| | | } |
| | | |
| | | /* å¨ç»ææ */ |
| | | @keyframes pulse { |
| | | 0% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | } |
| | | 50% { |
| | | transform: scale(1.5); |
| | | opacity: 0.3; |
| | | } |
| | | 100% { |
| | | transform: scale(1); |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | /* éªçææï¼è¡¨æ ¼åå¾è¡¨å·æ°æ¶ï¼ */ |
| | | .flash-effect { |
| | | animation: flash 0.6s ease-in-out; |
| | | } |
| | | |
| | | @keyframes flash { |
| | | 0% { |
| | | box-shadow: 0 0 0 rgba(79, 172, 254, 0); |
| | | } |
| | | 20% { |
| | | box-shadow: 0 0 15px rgba(79, 172, 254, 0.7); |
| | | } |
| | | 40% { |
| | | box-shadow: 0 0 0 rgba(79, 172, 254, 0); |
| | | } |
| | | 60% { |
| | | box-shadow: 0 0 15px rgba(79, 172, 254, 0.7); |
| | | } |
| | | 80% { |
| | | box-shadow: 0 0 0 rgba(79, 172, 254, 0); |
| | | } |
| | | 100% { |
| | | box-shadow: 0 0 0 rgba(79, 172, 254, 0); |
| | | } |
| | | } |
| | | |
| | | /* ååºå¼éé
*/ |
| | |
| | | @media screen and (max-width: 1024px) { |
| | | .metrics-row { |
| | | grid-template-columns: 1fr 1fr; |
| | | } |
| | | } |
| | | |
| | | .nav-menu { |
| | | flex-wrap: wrap; |
| | |
| | | height: 150px; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | |
| | | // åå§åè¿7æ¥åºå
¥åºè¶å¿å¾ï¼å
³èåç«¯æ°æ®ï¼ |
| | | const initStockTrend = () => { |
| | | debugger |
| | | if (!stockTrendRef.value) return; |
| | | |
| | | if (stockTrendChart) { |
| | |
| | | // ä¼å
使ç¨åç«¯æ°æ® |
| | | const trendData = bigscreendata.value.dailyInOutBoundList; |
| | | console.log('åºå
¥åºè¶å¿æ°æ®', trendData); |
| | | |
| | | // è®¡ç®æ°æ®ä¸çæå¤§å¼ï¼ç¨äºè®¾ç½®Yè½´èå´ |
| | | const maxInbound = Math.max(...trendData.map(item => item.dailyInboundQuantity || 0)); |
| | | const maxOutbound = Math.max(...trendData.map(item => item.dailyOutboundQuantity || 0)); |
| | | const maxValue = Math.max(maxInbound, maxOutbound); |
| | | console.log('æå¤§å¼è®¡ç®ç»æ:', { maxInbound, maxOutbound, maxValue }); |
| | | |
| | | const option = { |
| | | tooltip: { |
| | |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: 'æ°éï¼åä»¶ï¼', |
| | | max: 25 |
| | | name: 'æ°é', |
| | | min: 0, |
| | | // æ ¹æ®æ°æ®å¨æè®¾ç½®æå¤§å¼ï¼çåºä¸äºç©ºé´ |
| | | max: maxValue > 0 ? Math.ceil(maxValue * 1.2) : 10 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'å
¥åºé', |
| | | type: 'bar', |
| | | barWidth: '30%', |
| | | data: trendData.map(item => item.inNum), |
| | | itemStyle: { color: '#52c41a' } |
| | | data: trendData.map(item => item.dailyInboundQuantity), |
| | | itemStyle: { |
| | | color: '#52c41a', |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | }, |
| | | { |
| | | name: 'åºåºé', |
| | | type: 'bar', |
| | | barWidth: '30%', |
| | | data: trendData.map(item => item.outNum), |
| | | itemStyle: { color: '#1890ff' } |
| | | data: trendData.map(item => item.dailyOutboundQuantity), |
| | | itemStyle: { |
| | | color: '#1890ff', |
| | | borderRadius: [4, 4, 0, 0] |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | |
| | | // è·ååç«¯å¤§å±æ°æ® |
| | | const fetchBigGreenData = async () => { |
| | | try { |
| | | debugger |
| | | const res = await http.get('/api/BigScreen/GetBigGreenData'); |
| | | console.log('大屿°æ®', res); |
| | | |
| | |
| | | ? [...bigscreendata.value.taskList.slice(0,5)] |
| | | : [...bigscreendata.value.taskList]; |
| | | startTaskCarousel(); // å¯å¨ä»»å¡è½®æ |
| | | refreshCharts(); |
| | | // refreshCharts(); // ç§»é¤è¿éçè°ç¨ï¼æ¹ä¸ºå¨æ°æ®è·ååç»ä¸åå§å |
| | | }); |
| | | // è¿åPromiseï¼ä»¥ä¾¿å¨æ°æ®è·åæåååå§åå¾è¡¨ |
| | | return Promise.resolve(); |
| | | } catch (error) { |
| | | ElMessage.error('æ°æ®è·å失败ï¼è¯·æ£æ¥å端æ¥å£æ¯å¦æ£å¸¸'); |
| | | return Promise.reject(error); |
| | | } |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // åå§åè¿7æ¥åºå
¥åºè¶å¿å¾ï¼å
³èåç«¯æ°æ®ï¼ |
| | | const initStockTrend = () => { |
| | | debugger |
| | | if (!stockTrendRef.value) return; |
| | | |
| | | if (stockTrendChart) { |
| | | stockTrendChart.dispose(); |
| | | } |
| | | |
| | | stockTrendChart = echarts.init(stockTrendRef.value); |
| | | // ä¼å
使ç¨åç«¯æ°æ® |
| | | const trendData = bigscreendata.value.dailyInOutBoundList; |
| | | console.log('åºå
¥åºè¶å¿æ°æ®', trendData); |
| | | |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross' |
| | | } |
| | | }, |
| | | legend: { |
| | | data: ['å
¥åºé', 'åºåºé'], |
| | | top: 10 |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | top: '15%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: true, |
| | | data: trendData.map(item => item.date) |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | name: 'æ°éï¼åä»¶ï¼', |
| | | max: 25 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: 'å
¥åºé', |
| | | type: 'bar', |
| | | barWidth: '30%', |
| | | data: trendData.map(item => item.inNum), |
| | | itemStyle: { color: '#52c41a' } |
| | | }, |
| | | { |
| | | name: 'åºåºé', |
| | | type: 'bar', |
| | | barWidth: '30%', |
| | | data: trendData.map(item => item.outNum), |
| | | itemStyle: { color: '#1890ff' } |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | stockTrendChart.setOption(option); |
| | | return stockTrendChart; |
| | | }; |
| | | // const initStockTrend = () => { |
| | | // 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 initLocationRate = () => { |
| | |
| | | return exceptionTrendChart; |
| | | }; |
| | | |
| | | // å·æ°ææå¾è¡¨ï¼ç§»é¤æ æé·è¾¾å¾é»è¾ï¼ |
| | | // å·æ°ææå¾è¡¨ |
| | | const refreshCharts = () => { |
| | | const charts = [ |
| | | initInventoryPie, |
| | | initStockTrend, |
| | | initLocationRate, |
| | | initExceptionTrend, |
| | | ]; |
| | | |
| | | charts.forEach(initFunc => { |
| | |
| | | |
| | | // ç»ä»¶æè½½æ¶ï¼å
è¯·æ±æ°æ®ï¼ååå§åå¾è¡¨ |
| | | onMounted(() => { |
| | | console.log('ç»ä»¶å·²æè½½ï¼å¼å§åå§å'); |
| | | |
| | | // å
è·ååç«¯æ°æ® |
| | | fetchBigGreenData(); |
| | | // åå§åå¾è¡¨ï¼ç¡®ä¿DOM已渲æï¼ |
| | | nextTick(() => { |
| | | initInventoryPie(); |
| | | initStockTrend(); |
| | | initLocationRate(); |
| | | initExceptionTrend(); |
| | | window.addEventListener('resize', handleResize); |
| | | fetchBigGreenData().then(() => { |
| | | console.log('æ°æ®è·åæåï¼å¼å§åå§åå¾è¡¨'); |
| | | |
| | | // æ°æ®è·åæååååå§åå¾è¡¨ |
| | | nextTick(() => { |
| | | console.log('DOMå·²æ´æ°ï¼å¼å§åå§åå¾è¡¨'); |
| | | |
| | | try { |
| | | // ç«å³åå§åå¾è¡¨ |
| | | initInventoryPie(); |
| | | console.log('åºååå¸é¥¼å¾åå§å宿'); |
| | | |
| | | // ç¹å«å¤çåºå
¥åºè¶å¿å¾ |
| | | if (stockTrendRef.value) { |
| | | console.log('åºå
¥åºè¶å¿å¾å®¹å¨åå¨ï¼å¼å§åå§å'); |
| | | initStockTrend(); |
| | | console.log('åºå
¥åºè¶å¿å¾åå§å宿'); |
| | | } else { |
| | | console.error('åºå
¥åºè¶å¿å¾å®¹å¨ä¸åå¨'); |
| | | } |
| | | |
| | | initLocationRate(); |
| | | console.log('åºä½å©ç¨çå¾åå§å宿'); |
| | | |
| | | initExceptionTrend(); |
| | | console.log('å¼å¸¸è¶å¿å¾åå§å宿'); |
| | | |
| | | window.addEventListener('resize', handleResize); |
| | | console.log('ææå¾è¡¨åå§å宿'); |
| | | } catch (error) { |
| | | console.error('å¾è¡¨åå§åè¿ç¨ä¸åºé:', error); |
| | | } |
| | | }); |
| | | }).catch(error => { |
| | | console.error('è·åæ°æ®å¤±è´¥:', error); |
| | | }); |
| | | }); |
| | | |
| | |
| | | transition: all 0.3s ease; |
| | | overflow: hidden; |
| | | position: relative; |
| | | min-height: 400px; |
| | | } |
| | | |
| | | .chart-card:hover { |
| | |
| | | flex: 1; |
| | | position: relative; |
| | | border-radius: 8px; |
| | | background: rgba(255, 255, 255, 0.7); |
| | | backdrop-filter: blur(5px); |
| | | background: rgba(255, 255, 255, 0.9); |
| | | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.03); |
| | | overflow: hidden; |
| | | z-index: 1; |
| | | display: block; |
| | | } |
| | | |
| | | |
| | |
| | | // 4. è·åè¿7æ¥æ¯æ¥åºå
¥åºæç»ï¼æ ¸å¿ä¿®æ¹ï¼è°ç¨ä¸é¢çæ¹æ³ï¼ |
| | | var dailyInOutBoundList = Get7DaysDailyInOutBound(); |
| | | |
| | | //è·åä½ä¸ç»è®¡ |
| | | var completeTask = SimpleStatistics(); |
| | | //ä»»å¡ |
| | | List<Dt_Task> tasks = _taskRepository.QueryData(); |
| | | |
| | |
| | | InboundCount = inboundCount, |
| | | OutboundCount = outboundCount, |
| | | InStockPallet = inStockPallet, |
| | | FreeStockPallet = freeStockPallet |
| | | FreeStockPallet = freeStockPallet, |
| | | CompleteTask = completeTask |
| | | }; |
| | | return WebResponseContent.Instance.OK(data: bigGreenData); |
| | | } |
| | |
| | | .Queryable<Dt_OutboundOrderDetail>() |
| | | .Where(x => x.CreateDate >= startDate |
| | | && x.CreateDate < endDate.AddDays(1)) |
| | | .GroupBy(x => x.CreateDate) // ææ¥ææ ¼å¼ååç» |
| | | |
| | | .Select(x => new |
| | | { |
| | | Date = x.CreateDate.ToString( "MM-dd"), |
| | | DailyOutbound = SqlFunc.AggregateSum((decimal?)x.OverOutQuantity) ?? 0 |
| | | Date = x.CreateDate.ToString("MM-dd"), |
| | | x.OverOutQuantity |
| | | }) |
| | | .ToList() |
| | | .ToDictionary(k => k.Date, v => v.DailyOutbound); // 转为åå
¸æ¹ä¾¿å¹é
|
| | | .GroupBy(x => x.Date) |
| | | .ToDictionary(k => k.Key , g => g.Sum(x => (decimal?)x.OverOutQuantity) ?? 0); // 转为åå
¸æ¹ä¾¿å¹é
|
| | | |
| | | // 3. æ¥è¯¢æ¯æ¥å
¥åºæç»ï¼ææ¥æåç»ï¼ |
| | | var dailyInboundList = _inboundOrderDetailRepository.Db |
| | |
| | | .Where(x => x.CreateDate != null // è¿æ»¤ç©ºæ¥æ |
| | | && x.CreateDate >= startDate |
| | | && x.CreateDate < endDate.AddDays(1)) |
| | | .GroupBy(x => x.CreateDate).Distinct() // ææ¥ææ ¼å¼ååç» |
| | | .Select(x => new |
| | | { |
| | | Date = x.CreateDate.ToString("MM-dd"), |
| | | DailyInbound = SqlFunc.AggregateSum((decimal?)x.OverInQuantity) ?? 0 |
| | | x.OverInQuantity |
| | | }) |
| | | .ToList() |
| | | .ToDictionary(k => k.Date, v => v.DailyInbound); // 转为åå
¸æ¹ä¾¿å¹é
|
| | | .GroupBy(x=>x.Date) |
| | | .ToDictionary(k => k.Key, g => g.Sum(x => (decimal?)x.OverInQuantity) ?? 0); // 转为åå
¸æ¹ä¾¿å¹é
|
| | | |
| | | // 4. åå¹¶æ¯æ¥æ°æ®ï¼ç¡®ä¿7å¤©æ¥æå®æ´ï¼æ æ°æ®è¡¥0ï¼ |
| | | var dailyInOutBoundList = all7Days.Select(date => new DailyInOutBoundDto |
| | |
| | | return dailyInOutBoundList; |
| | | } |
| | | |
| | | |
| | | public List<SimpleStatisticsDTO> SimpleStatistics() |
| | | { |
| | | DateTime sevenDaysAgo = DateTime.Now.AddDays(-7); |
| | | |
| | | var stats = _taskHtyRepository |
| | | .QueryData(x => x.TaskStatus == (int)TaskStatusEnum.Finish && x.CreateDate >= sevenDaysAgo) |
| | | .GroupBy(t => |
| | | (int)t.TaskType >= 100 && (int)t.TaskType <= 299 ? "åºåº" : |
| | | (int)t.TaskType >= 500 && (int)t.TaskType <= 699 ? "å
¥åº" : "å
¶ä»" |
| | | ) |
| | | .Where(g => g.Key == "åºåº" || g.Key == "å
¥åº") |
| | | .Select(g => new SimpleStatisticsDTO |
| | | { |
| | | TaskType = g.Key, |
| | | Count = g.Count() |
| | | }) |
| | | .ToList(); |
| | | |
| | | return stats; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 大å±/æ±æ»æ°æ®è¿åDTOï¼å¤§ç»¿æ°æ®æ±æ»ï¼ |
| | |
| | | /// <summary> |
| | | /// è¿7æ¥åå
¥åºéï¼å
¥åº-åºåºï¼ |
| | | /// </summary> |
| | | public decimal totalStockChangeRate { get; set; } |
| | | public decimal TotalStockChangeRate { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä»»å¡å表 |
| | |
| | | public int InStockPallet { get; set; } |
| | | |
| | | public int FreeStockPallet { get; set; } |
| | | |
| | | public List<SimpleStatisticsDTO> CompleteTask { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | public class SimpleStatisticsDTO |
| | | { |
| | | public string TaskType { get; set; } |
| | | public int Count { get; set; } |
| | | } |
| | | |
| | | |
| | | } |
| | | } |