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 | 1152 +++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 942 insertions(+), 210 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 d8a44bd..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,28 +107,40 @@
<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>
+ <span class="task-count">鍏� {{ taskList.length }} 鏉′换鍔�</span>
</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"
+ :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 }">
- <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="120">
<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="鎵樼洏缂栧彿" 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>
@@ -115,27 +149,334 @@
</template>
<script>
-import { ref, onMounted, onUnmounted } from 'vue'
+import { ref, onMounted, onUnmounted, nextTick, watch } 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
+ },
+ {
+ 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
+ }
])
+ // 浠诲姟鍒楄〃鐩稿叧
const taskList = ref([])
+ const showTaskList = ref([])
+ 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) // 涓婁竴娆″綋澶╁嚭搴撻噺
+ const refreshInterval = ref(5 * 60 * 1000) // 瀹氭椂鍒锋柊闂撮殧锛�5鍒嗛挓锛�
+ const minRefreshGap = ref(30 * 1000) // 鏈�灏忓埛鏂伴棿闅旓紙闃叉姈锛�30绉掞級
+ 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] || `鏈煡鐘舵��(${statusNum})`;
+ }
+
+ // 鍚姩浠诲姟杞挱
+ const startTaskCarousel = () => {
+ // 娓呴櫎鏃у畾鏃跺櫒
+ if (taskCarouselTimer) clearInterval(taskCarouselTimer);
+
+ 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) {
+ tableElement.classList.add('flash-effect');
+ setTimeout(() => {
+ tableElement.classList.remove('flash-effect');
+ }, 600);
+ }
+
+ // 鏂板涓�1鏉★紝鍒犻櫎鏈�鍓�1鏉★紙淇濇寔7鏉℃樉绀猴級
+ showTaskList.value.push(taskList.value[currentTaskIndex.value]);
+ showTaskList.value.shift();
+
+ // 寰幆绱㈠紩
+ currentTaskIndex.value++;
+ if (currentTaskIndex.value >= totalTask) {
+ 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父
+ }
+
+ // 鑾峰彇浠诲姟绫诲瀷鏂囨湰
+ 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 === 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";
+ }
+
+ // 鑾峰彇浠诲姟绫诲瀷鏍峰紡绫�
+ 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 now = Date.now();
+ if (now - lastRefreshTime.value < minRefreshGap.value) {
+ return;
+ }
+ lastRefreshTime.value = now;
+
+ const res = await http.get('/api/BigScreen/GetBigGreenData');
+ console.log('澶у睆鏁版嵁', res);
+ bigscreendata.value = res.data || res;
+
+ updateMetrics();
+
+ // 鏇存柊浠诲姟鍒楄〃
+ 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.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; // 绌虹鏁伴噺
+ }
// 鏇存柊鏃堕棿
let timer
@@ -143,84 +484,139 @@
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;
+
+ // 閿�姣佹棫瀹炰緥
+ if (trendChart.value) {
+ trendChart.value.dispose();
+ }
+
+ 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 = {
- tooltip: { trigger: 'axis' },
+ 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%', 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: hasData ? dates : ['鏆傛棤鏁版嵁'],
+ axisLine: { lineStyle: { color: '#666' } },
+ axisLabel: { color: '#e0e0e0', fontSize: 11 }
},
yAxis: {
type: 'value',
- axisLine: { lineStyle: { color: '#fff' } },
- splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } }
+ axisLine: { lineStyle: { color: '#666' } },
+ splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
+ axisLabel: { color: '#e0e0e0', fontSize: 11 },
+ min: 0
},
series: [
{
name: '鍏ュ簱閲�',
type: 'line',
smooth: true,
- data: [120, 200, 450, 680, 520, 780, 650],
- itemStyle: { color: '#43e97b' },
+ data: hasData ? inboundData : [0],
+ 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: hasData ? outboundData : [0],
+ 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;
+
+ // 閿�姣佹棫瀹炰緥
+ 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: [
{
@@ -236,46 +632,89 @@
},
label: { show: false },
emphasis: {
- label: { show: true, fontSize: 16, fontWeight: 'bold' }
+ label: { show: true, fontSize: 14, fontWeight: 'bold', color: '#fff' }
},
- 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: chartData
}
]
- }
- //chart.setOption(option)
- return chart
+ };
+
+ categoryChart.value.setOption(option);
+ return categoryChart.value;
}
// 鍒濆鍖栨晥鐜囩粺璁″浘
const initEfficiencyChart = () => {
- const chart = echarts.init(efficiencyChartRef.value)
+ 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
+ };
+
+ 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 = {
- tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
+ 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/>');
+ }
+ },
grid: {
- left: '3%', right: '4%', bottom: '3%', top: '10%',
+ left: '5%',
+ right: '5%',
+ bottom: '10%',
+ top: '15%',
containLabel: true
},
xAxis: {
type: 'category',
- data: ['鍏ュ簱浣滀笟', '鍑哄簱浣滀笟', '鐩樼偣浣滀笟', '璋冩嫧浣滀笟', '琛ヨ揣浣滀笟'],
- axisLine: { lineStyle: { color: '#fff' } },
- axisLabel: { color: '#fff' }
+ data: hasData ? ['鍏ュ簱浣滀笟', '鍑哄簱浣滀笟'] : ['鏆傛棤鏁版嵁'],
+ axisLine: { lineStyle: { color: '#666' } },
+ axisLabel: { color: '#e0e0e0', fontSize: 11 }
},
yAxis: {
type: 'value',
- name: '鏁堢巼(鍗曚綅/灏忔椂)',
- axisLine: { lineStyle: { color: '#fff' } },
+ name: '瀹屾垚鏁伴噺(鍗�)',
+ nameTextStyle: { color: '#e0e0e0', fontSize: 12 },
+ axisLine: { lineStyle: { color: '#666' } },
splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
- axisLabel: { color: '#fff' }
+ axisLabel: { color: '#e0e0e0', fontSize: 11 },
+ min: 0
},
series: [
{
- data: [180, 156, 95, 78, 120],
+ name: '浣滀笟鏁伴噺',
+ data: hasData ? [taskData['鍏ュ簱'], taskData['鍑哄簱']] : [0],
type: 'bar',
barWidth: '40%',
itemStyle: {
@@ -284,110 +723,162 @@
{ 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);
+ };
+
+ // 鍒锋柊鍥捐〃鏁版嵁
+ 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
+
+ // 閲嶆柊鍒濆鍖栧浘琛�
+ 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 stopAutoRefresh = () => {
+ if (autoRefreshTimer) {
+ clearInterval(autoRefreshTimer);
+ autoRefreshTimer = null;
+ }
+ }
+
+ // 绐楀彛澶у皬鏀瑰彉鏃堕噸缁樺浘琛ㄥ拰璋冩暣琛ㄦ牸楂樺害
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)
+ console.warn('鍥捐〃閲嶇粯鏃跺嚭閿�:', error);
}
}
onMounted(() => {
- updateTime()
- timer = setInterval(updateTime, 1000)
+ // 鍒濆鍖栨椂闂�
+ updateTime();
+ timer = setInterval(updateTime, 1000);
- initTrendChart()
- initCategoryChart()
- initEfficiencyChart()
- fetchTaskList()
-
- window.addEventListener('resize', handleResize)
- })
+ // 鍒濆鍖栨暟鎹�
+ fetchBigGreenData();
+
+ nextTick(() => {
+ handleResize();
+ startAutoRefresh(); // 鍚姩鑷姩鍒锋柊
+ });
+
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ window.addEventListener('resize', handleResize);
+ });
onUnmounted(() => {
- clearInterval(timer)
- window.removeEventListener('resize', handleResize)
+ // 娓呴櫎鎵�鏈夊畾鏃跺櫒
+ clearInterval(timer);
+ stopTaskCarousel();
+ stopExpirationCarousel();
+ stopAutoRefresh();
+
+ // 绉婚櫎绐楀彛鐩戝惉
+ 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)
+ console.warn('鍥捐〃閿�姣佹椂鍑洪敊:', error);
}
- })
+ });
+
+ // 鐩戝惉浠诲姟鍒楄〃鍙樺寲锛岃嚜鍔ㄩ噸鍚疆鎾�
+ watch(taskList, () => {
+ stopTaskCarousel();
+ startTaskCarousel();
+ }, { deep: true });
return {
currentTime,
metrics,
taskList,
+ showTaskList,
+ nearExpirationList,
+ showNearExpirationList,
trendChartRef,
categoryChartRef,
efficiencyChartRef,
- getStatusType,
+ tableHeight,
+ formatNumber,
+ getTaskTypeText,
+ getTaskStatusText,
+ getStatusClass,
+ getTypeClass,
+ getExpirationClass,
refreshData
- }
+ };
}
-}
+};
</script>
<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 {
@@ -398,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 {
@@ -407,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 {
@@ -426,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;
@@ -437,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 {
@@ -451,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;
}
@@ -463,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;
}
@@ -471,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 {
@@ -488,22 +987,26 @@
}
.metric-value {
- font-size: 28px;
- font-weight: bold;
+ 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 {
@@ -514,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 {
@@ -533,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;
}
@@ -550,22 +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 鏍峰紡娣卞害浼樺寲 */
: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: #e0e0e0 !important;
+ padding: 12px 0;
}
:deep(.el-table tr) {
@@ -573,43 +1096,278 @@
}
: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;
+ padding: 4px 10px;
+ border-radius: 20px;
+ position: relative;
+ overflow: hidden;
+ font-size: 12px;
+ font-weight: 600;
+}
+
+.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);
+}
+
+.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;
+ padding: 4px 10px;
+ border-radius: 20px;
+ position: relative;
+ font-size: 12px;
+ font-weight: 600;
+}
+
+.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;
+}
+
+.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;
+}
+
+/* 鍔ㄧ敾鏁堟灉 */
+@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: 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;
}
}
@@ -632,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 {
@@ -655,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;
}
}
@@ -698,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 {
@@ -722,8 +1454,8 @@
height: 45px;
}
- .chart-container {
- height: 150px;
+ .metric-trend {
+ justify-content: center;
}
}
-</style>
+</style>
\ No newline at end of file
--
Gitblit v1.9.3