From 5dfd83bd540c2e43af2e0449c246c79a22cb1296 Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期二, 20 一月 2026 16:22:56 +0800
Subject: [PATCH] 1
---
项目代码/Dashboard/src/views/Dashboard.vue | 836 +++++++++++++++++++++++++++++++++++++----------------------
1 files changed, 525 insertions(+), 311 deletions(-)
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Dashboard.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Dashboard.vue"
index d322a88..3f99dbb 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Dashboard.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/Dashboard/src/views/Dashboard.vue"
@@ -36,11 +36,13 @@
<Box v-if="index === 0" />
<Download v-else-if="index === 1" />
<Upload v-else-if="index === 2" />
- <List v-else />
+ <List v-else-if="index === 3" />
+ <Box v-else-if="index === 4" />
+ <Box v-else />
</el-icon>
</div>
<div class="metric-content">
- <div class="metric-value">{{ item.value }}</div>
+ <div class="metric-value">{{ formatNumber(item.value) }}</div>
<div class="metric-label">{{ item.label }}</div>
<div class="metric-trend" :class="item.trend > 0 ? 'up' : 'down'">
<el-icon>
@@ -71,12 +73,32 @@
<div ref="categoryChartRef" class="chart-container"></div>
</div>
- <!-- 浣滀笟鏁堢巼 -->
+ <!-- 鐗╂枡涓存湡鏁版嵁 -->
<div class="chart-card">
<div class="card-title">
- <span>浣滀笟鏁堢巼缁熻</span>
+ <span>鐗╂枡涓存湡鏁版嵁</span>
+ <span class="task-count">鍏� {{ nearExpirationList.length }} 鏉¤褰�</span>
</div>
- <div ref="efficiencyChartRef" class="chart-container"></div>
+ <el-table
+ :data="showNearExpirationList"
+ style="width: 100%"
+ :height="250"
+ :empty-text="nearExpirationList.length === 0 ? '鏆傛棤涓存湡鏁版嵁' : ''"
+ >
+ <el-table-column prop="materielCode" label="鐗╂枡缂栫爜" min-width="120" />
+ <el-table-column prop="batchNo" label="鎵规鍙�" min-width="100" />
+ <el-table-column prop="palletCode" label="鎵樼洏缂栧彿" min-width="100" />
+ <el-table-column prop="locationCode" label="搴撲綅" min-width="100" />
+ <el-table-column prop="stockQuantity" label="搴撳瓨鏁伴噺" width="100" />
+ <el-table-column prop="daysToExpiration" label="涓存湡澶╂暟" width="100">
+ <template #default="{ row }">
+ <div :class="getExpirationClass(row.daysToExpiration)">
+ {{ row.daysToExpiration }}澶�
+ </div>
+ </template>
+ </el-table-column>
+ <el-table-column prop="validDate" label="鏈夋晥鏈熻嚦" width="160" />
+ </el-table>
</div>
</div>
@@ -85,10 +107,16 @@
<div class="table-card">
<div class="card-title">
<span>瀹炴椂浣滀笟浠诲姟</span>
+ <span class="task-count">鍏� {{ taskList.length }} 鏉′换鍔�</span>
</div>
- <el-table :data="showTaskList" style="width: 100%" :height="tableHeight">
- <el-table-column prop="taskNum" label="浠诲姟鍙�" />
- <el-table-column prop="taskStatus" label="浠诲姟鐘舵��" width="120">
+ <el-table
+ :data="showTaskList"
+ style="width: 100%"
+ :height="tableHeight"
+ :empty-text="taskList.length === 0 ? '鏆傛棤浣滀笟浠诲姟鏁版嵁' : ''"
+ >
+ <el-table-column prop="taskNum" label="浠诲姟鍙�" min-width="120" />
+ <el-table-column prop="taskStatus" label="浠诲姟鐘舵��" width="140">
<template #default="{ row }">
<div class="status-container" :class="getStatusClass(row.taskStatus)">
<div class="status-dot"></div>
@@ -96,7 +124,7 @@
</div>
</template>
</el-table-column>
- <el-table-column prop="taskType" label="浠诲姟绫诲瀷" width="100">
+ <el-table-column prop="taskType" label="浠诲姟绫诲瀷" width="120">
<template #default="{ row }">
<div class="type-container" :class="getTypeClass(row.taskType)">
<el-icon class="type-icon">
@@ -109,10 +137,10 @@
</div>
</template>
</el-table-column>
- <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-column prop="palletCode" label="鎵樼洏缂栧彿" min-width="100" />
+ <el-table-column prop="sourceAddress" label="璧风偣浣嶇疆" min-width="100"/>
+ <el-table-column prop="targetAddress" label="缁堢偣浣嶇疆" min-width="100"/>
+ <el-table-column prop="createDate" label="鍒涘缓鏃堕棿" width="180"/>
</el-table>
</div>
</div>
@@ -121,7 +149,7 @@
</template>
<script>
-import { ref, onMounted, onUnmounted, nextTick } from 'vue'
+import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
import * as echarts from 'echarts'
import { http } from '@/utils/http'
import { formatDateTime } from '@/utils'
@@ -190,35 +218,49 @@
110: "鎻愬崌鏈烘墽琛屼腑"
}
- // 鍏抽敭鎸囨爣锛堝搷搴斿紡锛�
+ // 鍏抽敭鎸囨爣锛堝搷搴斿紡锛�- 淇鏄犲皠鍏崇郴
const metrics = ref([
{
- label: '鎬诲簱瀛橀噺',
+ label: '寰呭叆搴撹鍗�',
value: 0,
icon: 'Box',
color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
trend: 8.5
},
{
- label: '浠婃棩鍏ュ簱',
+ label: '寰呭嚭搴撹鍗�',
value: 0,
icon: 'Download',
color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
trend: 12.3
},
{
- label: '浠婃棩鍑哄簱',
+ label: '浠婃棩鍏ュ簱瀹屾垚鏁�',
value: 0,
icon: 'Upload',
color: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
trend: -3.2
},
{
- label: '寰呭鐞嗕换鍔�',
+ label: '浠婃棩鍑哄簱瀹屾垚鏁�',
value: 0,
icon: 'List',
color: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
trend: 5.7
+ },
+ {
+ label: '鏈夎揣鏂欑',
+ value: 0,
+ icon: 'List',
+ color: 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)',
+ trend: 2.1
+ },
+ {
+ label: '绌虹鏁伴噺',
+ value: 0,
+ icon: 'List',
+ color: 'linear-gradient(135deg, #8176af 0%, #c0b7e8 100%)',
+ trend: -1.8
}
])
@@ -228,6 +270,12 @@
const currentTaskIndex = ref(7) // 鍒濆浠庣8鏉″紑濮嬶紙鍓�7鏉¢粯璁ゆ樉绀猴級
let taskCarouselTimer = null
+ // 涓存湡鐗╂枡鍒楄〃鐩稿叧
+ const nearExpirationList = ref([])
+ const showNearExpirationList = ref([])
+ const currentExpirationIndex = ref(7) // 鍒濆浠庣8鏉″紑濮嬶紙鍓�7鏉¢粯璁ゆ樉绀猴級
+ let expirationCarouselTimer = null
+
// 鑷姩鍒锋柊鐩稿叧閰嶇疆
const lastInboundToday = ref(0) // 涓婁竴娆″綋澶╁叆搴撻噺
const lastOutboundToday = ref(0) // 涓婁竴娆″綋澶╁嚭搴撻噺
@@ -236,24 +284,38 @@
let lastRefreshTime = ref(0) // 涓婁竴娆″埛鏂版椂闂�
let autoRefreshTimer = null // 鑷姩鍒锋柊瀹氭椂鍣�
+ // 鏁板瓧鏍煎紡鍖�
+ const formatNumber = (num) => {
+ if (num === undefined || num === null || isNaN(num)) return '0';
+ return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+ }
+
// 鑾峰彇浠诲姟鐘舵�佹枃鏈�
const getTaskStatusText = (statusNum) => {
if (statusNum === undefined || statusNum === null || isNaN(statusNum)) {
return "鏈煡鐘舵��";
}
- return taskStatusMap[statusNum] || "鏈煡鐘舵��";
+ return taskStatusMap[statusNum] || `鏈煡鐘舵��(${statusNum})`;
}
// 鍚姩浠诲姟杞挱
const startTaskCarousel = () => {
+ // 娓呴櫎鏃у畾鏃跺櫒
if (taskCarouselTimer) clearInterval(taskCarouselTimer);
- const totalTask = bigscreendata.value.taskList.length;
- if (totalTask <= 7) { // 浠诲姟鏁�<=7鏃朵笉杞挱
- showTaskList.value = [...bigscreendata.value.taskList];
+ const totalTask = taskList.value.length;
+ // 浠诲姟鏁�<=7鏃朵笉杞挱
+ if (totalTask <= 7) {
+ showTaskList.value = [...taskList.value];
return;
}
+ // 閲嶇疆绱㈠紩
+ currentTaskIndex.value = 7;
+ // 鍒濆鏄剧ず鍓�7鏉�
+ showTaskList.value = taskList.value.slice(0, 7);
+
+ // 鍚姩杞挱
taskCarouselTimer = setInterval(() => {
const tableElement = document.querySelector('.el-table');
if (tableElement) {
@@ -264,7 +326,7 @@
}
// 鏂板涓�1鏉★紝鍒犻櫎鏈�鍓�1鏉★紙淇濇寔7鏉℃樉绀猴級
- showTaskList.value.push(bigscreendata.value.taskList[currentTaskIndex.value]);
+ showTaskList.value.push(taskList.value[currentTaskIndex.value]);
showTaskList.value.shift();
// 寰幆绱㈠紩
@@ -273,6 +335,62 @@
currentTaskIndex.value = 0;
}
}, 5000); // 5绉掕疆鎾竴娆�
+ }
+
+ // 鍋滄浠诲姟杞挱
+ const stopTaskCarousel = () => {
+ if (taskCarouselTimer) {
+ clearInterval(taskCarouselTimer);
+ taskCarouselTimer = null;
+ }
+ }
+
+ // 鍚姩涓存湡鐗╂枡杞挱
+ const startExpirationCarousel = () => {
+ // 娓呴櫎鏃у畾鏃跺櫒
+ if (expirationCarouselTimer) clearInterval(expirationCarouselTimer);
+
+ const totalExpiration = nearExpirationList.value.length;
+ // 璁板綍鏁�<=7鏃朵笉杞挱
+ if (totalExpiration <= 7) {
+ showNearExpirationList.value = [...nearExpirationList.value];
+ return;
+ }
+
+ // 閲嶇疆绱㈠紩
+ currentExpirationIndex.value = 7;
+ // 鍒濆鏄剧ず鍓�7鏉�
+ showNearExpirationList.value = nearExpirationList.value.slice(0, 7);
+
+ // 鍚姩杞挱
+ expirationCarouselTimer = setInterval(() => {
+ // 鏂板涓�1鏉★紝鍒犻櫎鏈�鍓�1鏉★紙淇濇寔7鏉℃樉绀猴級
+ showNearExpirationList.value.push(nearExpirationList.value[currentExpirationIndex.value]);
+ showNearExpirationList.value.shift();
+
+ // 寰幆绱㈠紩
+ currentExpirationIndex.value++;
+ if (currentExpirationIndex.value >= totalExpiration) {
+ currentExpirationIndex.value = 0;
+ }
+ }, 5000); // 5绉掕疆鎾竴娆�
+ }
+
+ // 鍋滄涓存湡鐗╂枡杞挱
+ const stopExpirationCarousel = () => {
+ if (expirationCarouselTimer) {
+ clearInterval(expirationCarouselTimer);
+ expirationCarouselTimer = null;
+ }
+ }
+
+ // 鑾峰彇涓存湡澶╂暟鏍峰紡绫�
+ const getExpirationClass = (days) => {
+ if (days === undefined || days === null || isNaN(days)) return "exp-unknown";
+ if (days <= 0) return "exp-expired"; // 宸茶繃鏈�
+ if (days <= 7) return "exp-critical"; // 7澶╁唴涓存湡
+ if (days <= 30) return "exp-warning"; // 30澶╁唴涓存湡
+ return "exp-normal"; // 姝e父
}
// 鑾峰彇浠诲姟绫诲瀷鏂囨湰
@@ -291,14 +409,12 @@
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 === 900) return "status-completed"; // 瀹屾垚
if (statusNum === 970) return "status-suspended"; // 鎸傝捣
if (statusNum === 980) return "status-canceled"; // 鍙栨秷
if (statusNum === 990) return "status-error"; // 寮傚父
+ if (statusNum >= 200 && statusNum < 900) return "status-processing"; // 鎵ц涓�
+ if (statusNum >= 100 && statusNum < 200) return "status-pending"; // 鏂板缓銆佸凡鍙戦��
return "status-unknown";
}
@@ -316,35 +432,50 @@
// 浠庡悗绔幏鍙栨暟鎹�
const fetchBigGreenData = async () => {
- try {
- const res = await http.get('/api/BigScreen/GetBigGreenData');
- console.log('澶у睆鏁版嵁', res);
- bigscreendata.value = res.data || res;
+ try {
+ // 闃叉姈澶勭悊锛氶伩鍏嶇煭鏃堕棿鍐呭娆¤姹�
+ const now = Date.now();
+ if (now - lastRefreshTime.value < minRefreshGap.value) {
+ return;
+ }
+ lastRefreshTime.value = now;
- updateMetrics();
+ const res = await http.get('/api/BigScreen/GetBigGreenData');
+ console.log('澶у睆鏁版嵁', res);
+ bigscreendata.value = res.data || res;
- taskList.value = bigscreendata.value.taskList || [];
- showTaskList.value = taskList.value.slice(0, 7);
- startTaskCarousel();
+ updateMetrics();
- // 鏁版嵁鍔犺浇瀹屾垚鍚庡垵濮嬪寲鍥捐〃
- nextTick(() => {
- initEfficiencyChart();
- initTrendChart();
- initCategoryChart();
- });
- } catch (error) {
- console.error('鑾峰彇澶у睆鏁版嵁澶辫触:', error);
- ElMessage.error('鑾峰彇鏁版嵁澶辫触锛岃绋嶅悗閲嶈瘯');
- }
-};
+ // 鏇存柊浠诲姟鍒楄〃
+ taskList.value = Array.isArray(bigscreendata.value.taskList) ? bigscreendata.value.taskList : [];
+ // 閲嶅惎杞挱
+ stopTaskCarousel();
+ startTaskCarousel();
- // 鏇存柊鍏抽敭鎸囨爣
+ // 鏇存柊涓存湡鐗╂枡鍒楄〃
+ nearExpirationList.value = Array.isArray(bigscreendata.value.nearExpirationList) ? bigscreendata.value.nearExpirationList : [];
+ // 閲嶅惎涓存湡鐗╂枡杞挱
+ stopExpirationCarousel();
+ startExpirationCarousel();
+
+ // 鏁版嵁鍔犺浇瀹屾垚鍚庡埛鏂板浘琛�
+ nextTick(() => {
+ refreshCharts(true);
+ });
+ } 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
+ metrics.value[0].value = bigscreendata.value.unInBoundOrderCount || 0; // 寰呭叆搴撹鍗�
+ metrics.value[1].value = bigscreendata.value.unOutBoundOrderCount || 0; // 寰呭嚭搴撹鍗�
+ metrics.value[2].value = bigscreendata.value.inboundCount || 0; // 浠婃棩鍏ュ簱瀹屾垚鏁�
+ metrics.value[3].value = bigscreendata.value.outboundCount || 0; // 浠婃棩鍑哄簱瀹屾垚鏁�
+ metrics.value[4].value = bigscreendata.value.inStockPallet || 0; // 鏈夎揣鏂欑
+ metrics.value[5].value = bigscreendata.value.freeStockPallet || 0; // 绌虹鏁伴噺
}
// 鏇存柊鏃堕棿
@@ -353,32 +484,42 @@
currentTime.value = formatDateTime(new Date())
}
- // 鍒濆鍖栬秼鍔垮浘锛堢洿鎺ヤ娇鐢ㄥ悗绔棩鏈燂級
+ // 鍒濆鍖栬秼鍔垮浘
const initTrendChart = () => {
- if (!trendChartRef.value) return
+ 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)
- })
+ // 閿�姣佹棫瀹炰緥
+ if (trendChart.value) {
+ trendChart.value.dispose();
}
- const hasData = dates.length > 0
+ trendChart.value = echarts.init(trendChartRef.value);
+
+ // 鐩存帴浠庡悗绔幏鍙栨棩鏈熷拰鏁版嵁
+ const dates = [];
+ const inboundData = [];
+ const outboundData = [];
+
+ if (Array.isArray(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 = {
-
+ backgroundColor: 'transparent',
+ tooltip: {
+ trigger: 'axis',
+ textStyle: { color: '#fff', fontSize: 12 },
+ backgroundColor: 'rgba(0,0,0,0.7)'
+ },
legend: {
data: ['鍏ュ簱閲�', '鍑哄簱閲�'],
- textStyle: { color: '#fff' }
+ textStyle: { color: '#e0e0e0', fontSize: 12 }
},
grid: {
left: '3%',
@@ -390,15 +531,15 @@
xAxis: {
type: 'category',
boundaryGap: false,
- data: dates,
- axisLine: { lineStyle: { color: '#fff' } },
- axisLabel: { color: '#fff' }
+ data: hasData ? dates : ['鏆傛棤鏁版嵁'],
+ axisLine: { lineStyle: { color: '#666' } },
+ axisLabel: { color: '#e0e0e0', fontSize: 11 }
},
yAxis: {
type: 'value',
- axisLine: { lineStyle: { color: '#fff' } },
+ axisLine: { lineStyle: { color: '#666' } },
splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
- axisLabel: { color: '#fff' },
+ axisLabel: { color: '#e0e0e0', fontSize: 11 },
min: 0
},
series: [
@@ -406,7 +547,7 @@
name: '鍏ュ簱閲�',
type: 'line',
smooth: true,
- data: inboundData,
+ data: hasData ? inboundData : [0],
itemStyle: { color: '#5470c6' },
lineStyle: { color: '#5470c6' },
areaStyle: {
@@ -423,7 +564,7 @@
name: '鍑哄簱閲�',
type: 'line',
smooth: true,
- data: outboundData,
+ data: hasData ? outboundData : [0],
itemStyle: { color: '#91cc75' },
lineStyle: { color: '#91cc75' },
areaStyle: {
@@ -436,27 +577,46 @@
symbol: 'circle',
symbolSize: 6
}
- ],
-
- }
+ ]
+ };
- trendChart.value.setOption(option)
- return trendChart.value
+ trendChart.value.setOption(option);
+ return trendChart.value;
}
// 鍒濆鍖栧垎绫诲崰姣斿浘
const initCategoryChart = () => {
- if (!categoryChartRef.value) return
+ if (!categoryChartRef.value) return;
- categoryChart.value = echarts.init(categoryChartRef.value)
+ // 閿�姣佹棫瀹炰緥
+ if (categoryChart.value) {
+ categoryChart.value.dispose();
+ }
+
+ categoryChart.value = echarts.init(categoryChartRef.value);
+
+ const chartData = Array.isArray(bigscreendata.value.inventoryLocationDist) && 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' } }
+ ];
const option = {
- tooltip: { trigger: 'item' },
+ backgroundColor: 'transparent',
+ tooltip: {
+ trigger: 'item',
+ textStyle: { color: '#fff', fontSize: 12 },
+ backgroundColor: 'rgba(0,0,0,0.7)',
+ formatter: '{b}: {c} ({d}%)'
+ },
legend: {
orient: 'vertical',
right: '10%',
top: 'center',
- textStyle: { color: '#fff' }
+ textStyle: { color: '#e0e0e0', fontSize: 12 }
},
series: [
{
@@ -472,230 +632,241 @@
},
label: { show: false },
emphasis: {
- label: { show: true, fontSize: 16, fontWeight: 'bold' }
+ label: { show: true, fontSize: 14, fontWeight: 'bold', color: '#fff' }
},
- 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' } }
- ]
+ data: chartData
}
]
- }
+ };
- categoryChart.value.setOption(option)
- return categoryChart.value
+ categoryChart.value.setOption(option);
+ return categoryChart.value;
}
// 鍒濆鍖栨晥鐜囩粺璁″浘
- // 鍒濆鍖栨晥鐜囩粺璁″浘
-// 鍒濆鍖栨晥鐜囩粺璁″浘锛堜慨澶嶇増锛�
-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/>');
+ const initEfficiencyChart = () => {
+ if (!efficiencyChartRef.value) {
+ console.warn('鏁堢巼鍥捐〃瀹瑰櫒涓嶅瓨鍦紒');
+ return;
}
- },
- 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]
+
+ // 纭繚瀹瑰櫒鏈夐珮搴�
+ 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
+ };
+
+ if (Array.isArray(bigscreendata.value.completeTask)) {
+ bigscreendata.value.completeTask.forEach(item => {
+ if (item.taskType && typeof item.count === 'number') {
+ taskData[item.taskType] = item.count;
+ }
+ });
+ }
+
+ const hasData = taskData.鍏ュ簱 > 0 || taskData.鍑哄簱 > 0;
+
+ const option = {
+ backgroundColor: 'transparent',
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: { type: 'shadow' },
+ textStyle: { color: '#fff', fontSize: 12 },
+ backgroundColor: 'rgba(0,0,0,0.7)',
+ formatter: params => {
+ return params.map(p => `${p.seriesName}: ${p.value || 0} 鍗昤).join('<br/>');
+ }
},
- label: {
- show: true,
- position: 'top',
- color: '#fff',
- fontSize: 12
- }
- }
- ]
- };
+ grid: {
+ left: '5%',
+ right: '5%',
+ bottom: '10%',
+ top: '15%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: hasData ? ['鍏ュ簱浣滀笟', '鍑哄簱浣滀笟'] : ['鏆傛棤鏁版嵁'],
+ axisLine: { lineStyle: { color: '#666' } },
+ axisLabel: { color: '#e0e0e0', fontSize: 11 }
+ },
+ yAxis: {
+ type: 'value',
+ name: '瀹屾垚鏁伴噺(鍗�)',
+ nameTextStyle: { color: '#e0e0e0', fontSize: 12 },
+ axisLine: { lineStyle: { color: '#666' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
+ axisLabel: { color: '#e0e0e0', fontSize: 11 },
+ min: 0
+ },
+ series: [
+ {
+ name: '浣滀笟鏁伴噺',
+ data: hasData ? [taskData['鍏ュ簱'], taskData['鍑哄簱']] : [0],
+ 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: hasData,
+ position: 'top',
+ color: '#ffffff',
+ fontSize: 12,
+ fontWeight: 600
+ }
+ }
+ ]
+ };
- efficiencyChart.value.setOption(option, true);
- console.log('鏁堢巼鍥捐〃娓叉煋瀹屾垚锛屾暟鎹細', taskData);
-};
+ efficiencyChart.value.setOption(option, true);
+ console.log('鏁堢巼鍥捐〃娓叉煋瀹屾垚锛屾暟鎹細', taskData);
+ };
- // 鍒锋柊鍥捐〃鏁版嵁锛坕sDataChange锛氭槸鍚︽槸鏁版嵁鍙樺寲瀵艰嚧鐨勫埛鏂帮級
+ // 鍒锋柊鍥捐〃鏁版嵁
const refreshCharts = (isDataChange = false) => {
// 鏁版嵁鍙樺寲鏃舵坊鍔犻棯鐑佹晥鏋�
if (isDataChange) {
- const chartElements = [trendChartRef.value, categoryChartRef.value, efficiencyChartRef.value]
+ 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);
}
- })
+ });
}
- // 閿�姣佹棫鍥捐〃瀹炰緥
- if (trendChart.value) trendChart.value.dispose()
- if (categoryChart.value) categoryChart.value.dispose()
- if (efficiencyChart.value) efficiencyChart.value.dispose()
-
// 閲嶆柊鍒濆鍖栧浘琛�
- initTrendChart()
- initCategoryChart()
- initEfficiencyChart()
+ initTrendChart();
+ initCategoryChart();
+ initEfficiencyChart();
}
// 鎵嬪姩鍒锋柊鏁版嵁
const refreshData = () => {
- fetchBigGreenData()
+ fetchBigGreenData();
}
// 鍚姩鑷姩鍒锋柊
const startAutoRefresh = () => {
- if (autoRefreshTimer) clearInterval(autoRefreshTimer)
+ if (autoRefreshTimer) clearInterval(autoRefreshTimer);
autoRefreshTimer = setInterval(() => {
- console.log('瀹氭椂鍒锋柊鏁版嵁:', new Date().toLocaleString())
- fetchBigGreenData()
- }, refreshInterval.value)
+ console.log('瀹氭椂鍒锋柊鏁版嵁:', new Date().toLocaleString());
+ fetchBigGreenData();
+ }, refreshInterval.value);
+ }
+
+ // 鍋滄鑷姩鍒锋柊
+ const stopAutoRefresh = () => {
+ if (autoRefreshTimer) {
+ clearInterval(autoRefreshTimer);
+ autoRefreshTimer = null;
+ }
}
// 绐楀彛澶у皬鏀瑰彉鏃堕噸缁樺浘琛ㄥ拰璋冩暣琛ㄦ牸楂樺害
const handleResize = () => {
try {
- const windowHeight = window.innerHeight
- const headerHeight = 60
- const navHeight = 50
- const metricsHeight = 120
- const chartsHeight = 300
- const padding = 80
+ 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 availableHeight = windowHeight - headerHeight - navHeight - metricsHeight - chartsHeight - padding;
+ tableHeight.value = Math.max(200, Math.min(availableHeight, 400));
// 閲嶇粯鍥捐〃
- const charts = [trendChart.value, categoryChart.value, efficiencyChart.value]
+ const charts = [trendChart.value, categoryChart.value, efficiencyChart.value];
charts.forEach(chart => {
- if (chart) chart.resize()
- })
+ if (chart) chart.resize();
+ });
} catch (error) {
- console.warn('鍥捐〃閲嶇粯鏃跺嚭閿�:', error)
+ console.warn('鍥捐〃閲嶇粯鏃跺嚭閿�:', error);
}
}
onMounted(() => {
// 鍒濆鍖栨椂闂�
- updateTime()
- timer = setInterval(updateTime, 1000)
+ updateTime();
+ timer = setInterval(updateTime, 1000);
- // 鍒濆鍖栨暟鎹拰鍥捐〃
- fetchBigGreenData()
+ // 鍒濆鍖栨暟鎹�
+ fetchBigGreenData();
nextTick(() => {
- initTrendChart()
- initCategoryChart()
- initEfficiencyChart()
- handleResize()
- startAutoRefresh() // 鍚姩鑷姩鍒锋柊
- })
+ handleResize();
+ startAutoRefresh(); // 鍚姩鑷姩鍒锋柊
+ });
// 鐩戝惉绐楀彛澶у皬鍙樺寲
- window.addEventListener('resize', handleResize)
- })
+ window.addEventListener('resize', handleResize);
+ });
onUnmounted(() => {
// 娓呴櫎鎵�鏈夊畾鏃跺櫒
- clearInterval(timer)
- if (taskCarouselTimer) clearInterval(taskCarouselTimer)
- if (autoRefreshTimer) clearInterval(autoRefreshTimer)
+ clearInterval(timer);
+ stopTaskCarousel();
+ stopExpirationCarousel();
+ stopAutoRefresh();
// 绉婚櫎绐楀彛鐩戝惉
- window.removeEventListener('resize', handleResize)
+ window.removeEventListener('resize', handleResize);
// 閿�姣佸浘琛ㄥ疄渚�
try {
- if (trendChart.value) trendChart.value.dispose()
- if (categoryChart.value) categoryChart.value.dispose()
- if (efficiencyChart.value) efficiencyChart.value.dispose()
+ if (trendChart.value) trendChart.value.dispose();
+ if (categoryChart.value) categoryChart.value.dispose();
+ if (efficiencyChart.value) efficiencyChart.value.dispose();
} catch (error) {
- console.warn('鍥捐〃閿�姣佹椂鍑洪敊:', error)
+ console.warn('鍥捐〃閿�姣佹椂鍑洪敊:', error);
}
- })
+ });
+
+ // 鐩戝惉浠诲姟鍒楄〃鍙樺寲锛岃嚜鍔ㄩ噸鍚疆鎾�
+ watch(taskList, () => {
+ stopTaskCarousel();
+ startTaskCarousel();
+ }, { deep: true });
return {
currentTime,
metrics,
taskList,
showTaskList,
+ nearExpirationList,
+ showNearExpirationList,
trendChartRef,
categoryChartRef,
efficiencyChartRef,
tableHeight,
+ formatNumber,
getTaskTypeText,
getTaskStatusText,
getStatusClass,
getTypeClass,
+ getExpirationClass,
refreshData
- }
+ };
}
-}
+};
</script>
<style scoped>
@@ -718,7 +889,7 @@
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);
+ border: 1px solid rgba(255, 255, 255, 0.15);
}
.title {
@@ -727,11 +898,14 @@
background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
+ margin: 0;
}
.datetime {
font-size: 16px;
color: #4facfe;
+ font-weight: 600;
+ font-family: 'Consolas', monospace;
}
.nav-menu {
@@ -746,9 +920,9 @@
gap: 8px;
padding: 10px 25px;
background: rgba(255, 255, 255, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 8px;
- color: #fff;
+ color: #e0e0e0;
text-decoration: none;
transition: all 0.3s;
cursor: pointer;
@@ -757,11 +931,14 @@
.nav-item:hover {
background: rgba(79, 172, 254, 0.2);
border-color: #4facfe;
+ transform: translateY(-1px);
}
.nav-item.active {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
border-color: transparent;
+ color: #fff;
+ box-shadow: 0 4px 12px rgba(79, 172, 254, 0.3);
}
.main-content {
@@ -771,9 +948,10 @@
gap: 15px;
}
+/* 鍏抽敭鎸囨爣鍗$墖 - 浼樺寲缃戞牸甯冨眬鍜屾牱寮忓姣斿害 */
.metrics-row {
display: grid;
- grid-template-columns: repeat(4, 1fr);
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 15px;
}
@@ -783,7 +961,7 @@
gap: 20px;
padding: 20px;
background: rgba(255, 255, 255, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 10px;
transition: all 0.3s;
}
@@ -791,6 +969,7 @@
.metric-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
+ border-color: rgba(79, 172, 254, 0.5);
}
.metric-icon {
@@ -808,23 +987,26 @@
}
.metric-value {
- font-size: 28px;
- font-weight: bold;
- color: #fff;
+ font-size: 32px;
+ font-weight: 700;
+ color: #ffffff;
margin-bottom: 5px;
+ text-shadow: 0 0 8px rgba(255,255,255,0.2);
}
.metric-label {
font-size: 14px;
- color: rgba(255, 255, 255, 0.6);
+ color: #cccccc;
margin-bottom: 5px;
+ font-weight: 500;
}
.metric-trend {
display: flex;
align-items: center;
gap: 5px;
- font-size: 12px;
+ font-size: 13px;
+ font-weight: 600;
}
.metric-trend.up {
@@ -835,17 +1017,20 @@
color: #f56c6c;
}
+/* 鍥捐〃鍖哄煙 - 浼樺寲甯冨眬鍜屾牱寮� */
.charts-row {
display: grid;
- grid-template-columns: repeat(3, 1fr);
+ grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 15px;
}
.chart-card {
padding: 20px;
background: rgba(255, 255, 255, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 10px;
+ display: flex;
+ flex-direction: column;
}
.card-title {
@@ -854,15 +1039,23 @@
align-items: center;
margin-bottom: 15px;
font-size: 16px;
- font-weight: bold;
+ font-weight: 600;
color: #4facfe;
}
-.chart-container {
- width: 100%;
- height: 250px;
+.task-count {
+ font-size: 12px;
+ color: #cccccc;
+ font-weight: normal;
}
+.chart-container {
+ flex: 1;
+ width: 100%;
+ min-height: 250px;
+}
+
+/* 琛ㄦ牸鍖哄煙 */
.table-row {
flex: 1;
}
@@ -871,24 +1064,31 @@
height: 100%;
padding: 20px;
background: rgba(255, 255, 255, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 10px;
+ display: flex;
+ flex-direction: column;
}
-/* Element Plus Table 鏍峰紡瑕嗙洊 */
+/* Element Plus Table 鏍峰紡娣卞害浼樺寲 */
:deep(.el-table) {
background: transparent !important;
+ color: #e0e0e0;
+ font-size: 13px;
}
:deep(.el-table th) {
- background: rgba(255, 255, 255, 0.1) !important;
- color: #fff !important;
- border-color: rgba(255, 255, 255, 0.1) !important;
+ background: rgba(255, 255, 255, 0.15) !important;
+ color: #ffffff !important;
+ border-color: rgba(255, 255, 255, 0.2) !important;
+ font-weight: 600;
+ padding: 10px 0;
}
:deep(.el-table td) {
border-color: rgba(255, 255, 255, 0.1) !important;
- color: rgba(255, 255, 255, 0.9) !important;
+ color: #e0e0e0 !important;
+ padding: 12px 0;
}
:deep(.el-table tr) {
@@ -896,14 +1096,18 @@
}
:deep(.el-table__row:hover td) {
- background: rgba(255, 255, 255, 0.05) !important;
+ background: rgba(255, 255, 255, 0.08) !important;
}
-:deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
- background: rgba(255, 255, 255, 0.05) !important;
+:deep(.el-table--border) {
+ border: 1px solid rgba(255,255,255,0.15) !important;
}
-/* 浠诲姟鐘舵�佹牱寮� */
+:deep(.el-table__empty-text) {
+ color: #cccccc !important;
+}
+
+/* 浠诲姟鐘舵�佹牱寮� - 楂樺姣斿害浼樺寲 */
.status-container {
display: flex;
align-items: center;
@@ -912,7 +1116,7 @@
position: relative;
overflow: hidden;
font-size: 12px;
- font-weight: 500;
+ font-weight: 600;
}
.status-dot {
@@ -936,7 +1140,7 @@
white-space: nowrap;
}
-/* 涓嶅悓鐘舵�佺殑棰滆壊 */
+/* 涓嶅悓鐘舵�佺殑棰滆壊 - 娣辫壊涓婚楂樺姣斿害 */
.status-completed {
background: rgba(103, 194, 58, 0.15);
color: #67c23a;
@@ -1015,7 +1219,20 @@
background: rgba(245, 108, 108, 0.5);
}
-/* 浠诲姟绫诲瀷鏍峰紡 */
+.status-unknown {
+ background: rgba(75, 85, 99, 0.15);
+ color: #9ca3af;
+}
+
+.status-unknown .status-dot {
+ background: #9ca3af;
+}
+
+.status-unknown .status-dot::after {
+ background: rgba(156, 163, 175, 0.5);
+}
+
+/* 浠诲姟绫诲瀷鏍峰紡 - 楂樺姣斿害浼樺寲 */
.type-container {
display: flex;
align-items: center;
@@ -1023,7 +1240,7 @@
border-radius: 20px;
position: relative;
font-size: 12px;
- font-weight: 500;
+ font-weight: 600;
}
.type-icon {
@@ -1054,6 +1271,37 @@
.type-other {
background: rgba(144, 147, 153, 0.15);
color: #909399;
+}
+
+.type-unknown {
+ background: rgba(75, 85, 99, 0.15);
+ color: #9ca3af;
+}
+
+/* 涓存湡澶╂暟鏍峰紡 */
+.exp-expired {
+ color: #f56c6c;
+ font-weight: 600;
+}
+
+.exp-critical {
+ color: #e6a23c;
+ font-weight: 600;
+}
+
+.exp-warning {
+ color: #f0ad4e;
+ font-weight: 500;
+}
+
+.exp-normal {
+ color: #67c23a;
+ font-weight: 500;
+}
+
+.exp-unknown {
+ color: #909399;
+ font-weight: 400;
}
/* 鍔ㄧ敾鏁堟灉 */
@@ -1098,36 +1346,28 @@
}
}
-/* 鍝嶅簲寮忛�傞厤 */
+/* 鍝嶅簲寮忛�傞厤澧炲己 */
@media screen and (max-width: 1920px) {
.metric-value {
- font-size: 24px;
+ font-size: 28px;
}
.chart-container {
- height: 220px;
+ min-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;
+ font-size: 24px;
}
.chart-container {
- height: 200px;
+ min-height: 200px;
}
}
@@ -1150,22 +1390,12 @@
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;
+ font-size: 22px;
}
.chart-card {
@@ -1173,23 +1403,7 @@
}
.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;
+ min-height: 180px;
}
}
@@ -1216,17 +1430,17 @@
.nav-menu {
gap: 8px;
padding: 0;
+ flex-wrap: wrap;
}
.nav-item {
padding: 6px 12px;
font-size: 12px;
+ flex: 1;
+ min-width: 80px;
+ justify-content: center;
flex-direction: column;
gap: 4px;
- }
-
- .metrics-row {
- grid-template-columns: 1fr;
}
.metric-card {
@@ -1240,8 +1454,8 @@
height: 45px;
}
- .chart-container {
- height: 150px;
+ .metric-trend {
+ justify-content: center;
}
}
</style>
\ No newline at end of file
--
Gitblit v1.9.3