From 4434480f32d517065d3ddb96343cdd74e31b7dbe Mon Sep 17 00:00:00 2001 From: zuqijia <2924963185@qq.com> Date: Tue, 19 May 2026 17:56:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E5=A4=A7=E5=B1=8F?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/components/Navbar/index.vue | 88 ++- src/layout/components/Sidebar/index.vue | 219 ++---- src/layout/index.vue | 48 +- src/modules/dashboardBig/views/cost.vue | 426 +++++++----- src/modules/dashboardBig/views/energy.vue | 451 +++++++----- src/modules/dashboardBig/views/index.vue | 376 ++++++---- src/modules/dashboardBig/views/oee.vue | 324 ++++++--- src/modules/dashboardBig/views/order.vue | 422 +++++++----- src/modules/dashboardBig/views/output.vue | 338 ++++++--- .../dashboardBig/views/stopAnalysis.vue | 355 +++++++--- src/router/index.js | 112 +-- src/store/modules/permission.js | 23 +- src/views/dashboard/cost/index.vue | 602 ---------------- src/views/dashboard/demo/index.vue | 458 ------------- src/views/dashboard/energy/index.vue | 644 ------------------ src/views/dashboard/order/index.vue | 78 --- src/views/data-source/index.vue | 70 -- src/views/home/index.vue | 278 -------- src/views/reports/acid-rolling/index.vue | 332 --------- src/views/reports/acid-stop/index.vue | 308 --------- src/views/reports/index.vue | 107 --- src/views/screens/acid-rolling/index.vue | 502 +++++++------- src/views/screens/create.vue | 170 ----- src/views/screens/edit.vue | 178 ----- src/views/screens/index.vue | 201 ------ src/views/screens/list.vue | 198 ------ src/views/system/config/index.vue | 34 - src/views/system/index.vue | 180 ----- src/views/system/menu/index.vue | 126 ---- src/views/system/role/index.vue | 109 --- src/views/system/user/index.vue | 121 ---- 31 files changed, 2162 insertions(+), 5716 deletions(-) delete mode 100644 src/views/dashboard/cost/index.vue delete mode 100644 src/views/dashboard/demo/index.vue delete mode 100644 src/views/dashboard/energy/index.vue delete mode 100644 src/views/dashboard/order/index.vue delete mode 100644 src/views/data-source/index.vue delete mode 100644 src/views/home/index.vue delete mode 100644 src/views/reports/acid-rolling/index.vue delete mode 100644 src/views/reports/acid-stop/index.vue delete mode 100644 src/views/reports/index.vue delete mode 100644 src/views/screens/create.vue delete mode 100644 src/views/screens/edit.vue delete mode 100644 src/views/screens/index.vue delete mode 100644 src/views/screens/list.vue delete mode 100644 src/views/system/config/index.vue delete mode 100644 src/views/system/index.vue delete mode 100644 src/views/system/menu/index.vue delete mode 100644 src/views/system/role/index.vue delete mode 100644 src/views/system/user/index.vue diff --git a/src/layout/components/Navbar/index.vue b/src/layout/components/Navbar/index.vue index fbbbd98..e56cb8f 100644 --- a/src/layout/components/Navbar/index.vue +++ b/src/layout/components/Navbar/index.vue @@ -5,39 +5,58 @@ {{ title }} \ No newline at end of file + diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue index 393630a..0fecaae 100644 --- a/src/layout/components/Sidebar/index.vue +++ b/src/layout/components/Sidebar/index.vue @@ -3,7 +3,7 @@ @@ -16,24 +16,10 @@ router unique-opened > - + + + {{ item.meta?.title }} + @@ -43,7 +29,7 @@ import { computed } from 'vue' import { useRoute } from 'vue-router' import { useStore } from 'vuex' -import { Refresh, Monitor, PieChart, Document, List, Plus, Bell, Setting } from '@element-plus/icons-vue' +import { Monitor, PieChart, Document, Bell } from '@element-plus/icons-vue' const route = useRoute() const store = useStore() @@ -52,24 +38,14 @@ const sidebar = computed(() => store.state.app.sidebar) const activeMenu = computed(() => route.path) const iconMap = { - 'dashboard': Monitor, 'monitor': Monitor, 'example': PieChart, 'order': Document, 'cost': PieChart, 'energy': Monitor, - 'pie-chart': PieChart, - 'list': List, - 'plus': Plus, - 'document': Document, + 'oee': PieChart, 'output': PieChart, - 'stop': Bell, - 'system': Setting, - 'user': Refresh, - 'role': Refresh, - 'menu': List, - 'config': Setting, - 'database': Monitor + 'stop': Bell } const getIcon = (iconName) => { @@ -77,52 +53,14 @@ const getIcon = (iconName) => { } const menuItems = [ - { - path: '/index', - meta: { title: '工作台', icon: 'dashboard' }, - children: [] - }, - { - path: '/dashboard', - meta: { title: '数据大屏', icon: 'monitor' }, - children: [ - { path: '/dashboard/demo', meta: { title: '示例大屏', icon: 'example' }, children: [] }, - { path: '/dashboard/order', meta: { title: '订单大屏', icon: 'order' }, children: [] }, - { path: '/dashboard/cost', meta: { title: '成本大屏', icon: 'cost' }, children: [] }, - { path: '/dashboard/energy', meta: { title: '能源大屏', icon: 'energy' }, children: [] }, - { path: '/dashboard/acid-rolling', meta: { title: '酸轧数据大屏', icon: 'example' }, children: [] } - ] - }, - { - path: '/screen-manage', - meta: { title: '大屏管理', icon: 'pie-chart' }, - children: [ - { path: '/screen-manage', meta: { title: '大屏列表', icon: 'list' }, children: [] }, - { path: '/screen-manage/create', meta: { title: '新建大屏', icon: 'plus' }, children: [] } - ] - }, - { - path: '/reports', - meta: { title: '报表管理', icon: 'document' }, - children: [ - { path: '/reports', meta: { title: '报表列表', icon: 'list' }, children: [] }, - { path: '/reports/acid-rolling', meta: { title: '酸轧产出报表', icon: 'output' }, children: [] }, - { path: '/reports/acid-stop', meta: { title: '酸轧停机报表', icon: 'stop' }, children: [] } - ] - }, - { - path: '/system', - meta: { title: '系统管理', icon: 'system' }, - children: [ - { path: '/system/menu', meta: { title: '菜单管理', icon: 'menu' }, children: [] }, - { path: '/system/config', meta: { title: '系统配置', icon: 'config' }, children: [] } - ] - }, - { - path: '/data-source', - meta: { title: '数据源配置', icon: 'database' }, - children: [] - } + { path: '/dashboard/demo', meta: { title: '示例大屏', icon: 'example' } }, + { path: '/dashboard/order', meta: { title: '订单大屏', icon: 'order' } }, + { path: '/dashboard/cost', meta: { title: '成本大屏', icon: 'cost' } }, + { path: '/dashboard/energy', meta: { title: '能源大屏', icon: 'energy' } }, + { path: '/dashboard/oee', meta: { title: 'OEE综合大屏', icon: 'oee' } }, + { path: '/dashboard/output', meta: { title: '产出监控大屏', icon: 'output' } }, + { path: '/dashboard/stop-analysis', meta: { title: '停机分析大屏', icon: 'stop' } }, + { path: '/dashboard/acid-rolling', meta: { title: '酸轧数据大屏', icon: 'example' } } ] @@ -131,9 +69,9 @@ const menuItems = [ flex-shrink: 0; width: 200px; height: 100vh; - background: #ffffff; - border-right: 1px solid #e8e8e8; - box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.15); + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 100%); + border-right: 1px solid rgba(0, 212, 255, 0.2); + box-shadow: 2px 2px 20px rgba(0, 0, 0, 0.3); transition: width 0.28s ease; overflow: hidden; @@ -147,8 +85,8 @@ const menuItems = [ display: flex; align-items: center; justify-content: center; - background: linear-gradient(135deg, #3A71A8, #324157); - border-bottom: 1px solid rgba(0, 0, 0, 0.1); + background: linear-gradient(90deg, #00a8cc 0%, #00d4ff 50%, #00a8cc 100%); + border-bottom: 1px solid rgba(0, 212, 255, 0.3); .logo-wrapper { display: flex; @@ -157,13 +95,13 @@ const menuItems = [ .logo-icon { font-size: 20px; - color: #ffffff; + color: #0a1428; } .logo-text { font-size: 16px; font-weight: bold; - color: #ffffff; + color: #0a1428; transition: opacity 0.2s ease; } } @@ -175,22 +113,22 @@ const menuItems = [ overflow-x: hidden; &::-webkit-scrollbar { - width: 8px; - height: 8px; + width: 6px; + height: 6px; } &::-webkit-scrollbar-track { - background: #f1f1f1; - border-radius: 4px; + background: rgba(0, 212, 255, 0.1); + border-radius: 3px; } &::-webkit-scrollbar-thumb { - background: #c1c1c1; - border-radius: 4px; + background: rgba(0, 212, 255, 0.3); + border-radius: 3px; transition: background 0.2s; &:hover { - background: #a8a8a8; + background: rgba(0, 212, 255, 0.5); } } } @@ -198,78 +136,62 @@ const menuItems = [ .sidebar-menu { border-right: none; background: transparent; - padding: 4px; + padding: 8px; :deep(.el-menu) { border-right: none; background: transparent; } - :deep(.el-menu-item), - :deep(.el-sub-menu__title) { - height: 38px; - line-height: 38px; - color: #333333; - margin: 2px 0; - padding: 0 8px; - border-radius: 0; + :deep(.el-menu-item) { + height: 44px; + line-height: 44px; + color: #ffffff; + margin: 6px 4px; + padding: 0 16px; + border-radius: 8px; position: relative; border-left: 3px solid transparent; - transition: all 0.2s ease; + transition: all 0.25s ease; + background: rgba(0, 212, 255, 0.08); + font-size: 14px; .el-icon { - color: #8c8c8c; - margin-right: 8px; - font-size: 14px; + color: #00d4ff; + margin-right: 12px; + font-size: 16px; } &:hover { - background: rgba(0, 0, 0, 0.06); - color: #1a1a1a; + background: rgba(0, 212, 255, 0.25); + color: #ffffff; + transform: translateX(4px); .el-icon { - color: #555555; + color: #00d4ff; + text-shadow: 0 0 10px rgba(0, 212, 255, 0.6); } } &.is-active { - border-left: 3px solid #409eff; - background: rgba(64, 158, 255, 0.1); - color: #1a1a1a; + border-left: 3px solid #00d4ff; + background: rgba(0, 212, 255, 0.3); + color: #ffffff; font-weight: 600; + box-shadow: 0 0 15px rgba(0, 212, 255, 0.25); .el-icon { - color: #409eff; + color: #00d4ff; + text-shadow: 0 0 15px rgba(0, 212, 255, 0.9); } } } - :deep(.el-sub-menu__title) { - &::after { - font-size: 12px; - color: #8c8c8c; - } - } - - :deep(.el-sub-menu .el-menu-item) { - padding-left: 18px !important; - font-size: 13px; - - &.is-active { - padding-left: 18px !important; - } - } - - :deep(.el-sub-menu .el-sub-menu .el-menu-item) { - padding-left: 28px !important; - font-size: 12px; - } - &.is-collapse { - :deep(.el-menu-item), - :deep(.el-sub-menu__title) { + :deep(.el-menu-item) { padding: 0; text-align: center; + border-left: none; span { display: none; @@ -278,27 +200,12 @@ const menuItems = [ .el-icon { margin-right: 0; } + + &.is-active { + border-left: none; + background: rgba(0, 212, 255, 0.2); + } } } } - -:deep(.el-menu--popup) { - border: 1px solid #e8e8e8; - border-radius: 4px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - - .el-menu-item { - padding: 0 20px; - border-left: none; - - &:hover { - background: rgba(64, 158, 255, 0.08); - } - - &.is-active { - border-left: none; - background: rgba(64, 158, 255, 0.12); - } - } -} - \ No newline at end of file + diff --git a/src/layout/index.vue b/src/layout/index.vue index f1d3ee6..226070c 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -1,17 +1,48 @@ \ No newline at end of file + diff --git a/src/modules/dashboardBig/views/cost.vue b/src/modules/dashboardBig/views/cost.vue index eb21d1c..319c225 100644 --- a/src/modules/dashboardBig/views/cost.vue +++ b/src/modules/dashboardBig/views/cost.vue @@ -3,29 +3,34 @@

成本数据大屏

- {{ currentTime }} +
+ {{ currentTime }} + +
-
-
-
{{ card.title }}
-
{{ card.value }}
-
{{ card.unit }}
+
+
+
{{ card.title }}
+
{{ card.value }}
+
{{ card.unit }}
-
-
-
成本趋势
+
+
+
成本趋势
-
-
成本构成
+
+
成本构成
-
-
成本对比
+
+
成本对比
{{ item.name }} @@ -38,9 +43,9 @@
-
-
-
成本类型对比
+
+
+
成本类型对比
@@ -54,12 +59,12 @@
-
-
月度成本对比
+
+
月度成本对比
-
-
成本分析
+
+
成本分析
{{ item.label }} @@ -79,6 +84,7 @@ import { ref, onMounted, onBeforeUnmount, onUnmounted, nextTick } from 'vue' import * as echarts from 'echarts' const currentTime = ref('') +const isFullscreen = ref(false) const trendChartRef = ref(null) const pieChartRef = ref(null) const barChartRef = ref(null) @@ -87,35 +93,36 @@ let pieChart = null let barChart = null let timeInterval = null let resizeObserver = null +let fullscreenChangeHandler = null const cards = ref([ - { title: '总成本', value: '156.8', unit: '万', color: '#f56c6c' }, - { title: '材料成本', value: '98.5', unit: '万', color: '#4a90d9' }, - { title: '人工成本', value: '23.4', unit: '万', color: '#5cd9e8' }, - { title: '能源成本', value: '18.9', unit: '万', color: '#ff9800' } + { title: '总成本', value: '156.8', unit: '万', color: '#ff6b6b' }, + { title: '材料成本', value: '98.5', unit: '万', color: '#00d4ff' }, + { title: '人工成本', value: '23.4', unit: '万', color: '#7c63ff' }, + { title: '能源成本', value: '18.9', unit: '万', color: '#ff9f43' } ]) const compareList = ref([ - { name: '材料成本', percent: 62.8, value: '98.5万', color: '#4a90d9' }, - { name: '人工成本', percent: 14.9, value: '23.4万', color: '#5cd9e8' }, - { name: '能源成本', percent: 12.1, value: '18.9万', color: '#ff9800' }, - { name: '其他成本', percent: 10.2, value: '16.0万', color: '#f56c6c' } + { name: '材料成本', percent: 62.8, value: '98.5万', color: '#00d4ff' }, + { name: '人工成本', percent: 14.9, value: '23.4万', color: '#7c63ff' }, + { name: '能源成本', percent: 12.1, value: '18.9万', color: '#ff9f43' }, + { name: '其他成本', percent: 10.2, value: '16.0万', color: '#ff6b6b' } ]) const costItems = ref([ - { name: '材料成本', percent: 62.8, value: '¥98.5万', color: '#4a90d9' }, - { name: '人工成本', percent: 14.9, value: '¥23.4万', color: '#5cd9e8' }, - { name: '能源成本', percent: 12.1, value: '¥18.9万', color: '#ff9800' }, - { name: '其他成本', percent: 10.2, value: '¥16.0万', color: '#f56c6c' } + { name: '材料成本', percent: 62.8, value: '¥98.5万', color: '#00d4ff' }, + { name: '人工成本', percent: 14.9, value: '¥23.4万', color: '#7c63ff' }, + { name: '能源成本', percent: 12.1, value: '¥18.9万', color: '#ff9f43' }, + { name: '其他成本', percent: 10.2, value: '¥16.0万', color: '#ff6b6b' } ]) const analysisList = ref([ - { label: '材料成本占比', value: '62.8%', change: 2.5, color: '#4a90d9' }, - { label: '人工成本占比', value: '14.9%', change: -1.2, color: '#5cd9e8' }, - { label: '能源成本占比', value: '12.1%', change: 3.8, color: '#ff9800' }, - { label: '成本同比增长', value: '8.5%', change: 5.2, color: '#52c41a' }, - { label: '预算执行率', value: '92.3%', change: -1.5, color: '#9c27b0' }, - { label: '成本节约率', value: '5.6%', change: 2.1, color: '#33cea0' } + { label: '材料成本占比', value: '62.8%', change: 2.5, color: '#00d4ff' }, + { label: '人工成本占比', value: '14.9%', change: -1.2, color: '#7c63ff' }, + { label: '能源成本占比', value: '12.1%', change: 3.8, color: '#ff9f43' }, + { label: '成本同比增长', value: '8.5%', change: 5.2, color: '#00ff88' }, + { label: '预算执行率', value: '92.3%', change: -1.5, color: '#a0c4e8' }, + { label: '成本节约率', value: '5.6%', change: 2.1, color: '#00ff88' } ]) const updateTime = () => { @@ -125,26 +132,51 @@ const updateTime = () => { }) } +const toggleFullscreen = () => { + if (!document.fullscreenElement) { + document.documentElement.requestFullscreen().then(() => { + isFullscreen.value = true + }).catch(err => { + console.error('全屏请求失败:', err) + }) + } else { + document.exitFullscreen().then(() => { + isFullscreen.value = false + }).catch(err => { + console.error('退出全屏失败:', err) + }) + } +} + +const handleFullscreenChange = () => { + isFullscreen.value = !!document.fullscreenElement +} + const initCharts = () => { if (trendChartRef.value) { trendChart = echarts.init(trendChartRef.value) trendChart.setOption({ - backgroundColor: '#ffffff', + backgroundColor: 'transparent', grid: { top: 30, right: 30, bottom: 30, left: 60 }, - tooltip: { trigger: 'axis' }, + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, xAxis: { type: 'category', data: ['1月', '2月', '3月', '4月', '5月', '6月'], - axisLine: { lineStyle: { color: '#ddd' } }, + axisLine: { lineStyle: { color: '#3a5a8a' } }, axisTick: { show: false }, - axisLabel: { color: '#666' } + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, axisTick: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666', formatter: (v) => (v / 10000).toFixed(0) + '万' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8', formatter: (v) => (v / 10000).toFixed(0) + '万' } }, series: [{ type: 'line', @@ -152,12 +184,12 @@ const initCharts = () => { data: [1420000, 1380000, 1520000, 1490000, 1568000, 1568000], areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: 'rgba(74,144,217,0.5)' }, - { offset: 1, color: 'rgba(74,144,217,0.1)' } + { offset: 0, color: 'rgba(0, 212, 255, 0.3)' }, + { offset: 1, color: 'rgba(0, 212, 255, 0.05)' } ]) }, - lineStyle: { color: '#4a90d9', width: 3 }, - itemStyle: { color: '#4a90d9' }, + lineStyle: { color: '#00d4ff', width: 3 }, + itemStyle: { color: '#00d4ff' }, symbol: 'circle', symbolSize: 8 }] @@ -167,18 +199,23 @@ const initCharts = () => { if (pieChartRef.value) { pieChart = echarts.init(pieChartRef.value) pieChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item' }, - legend: { bottom: 10, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['45%', '75%'], center: ['50%', '45%'], data: [ - { value: 62.8, name: '材料成本', itemStyle: { color: '#4a90d9' } }, - { value: 14.9, name: '人工成本', itemStyle: { color: '#5cd9e8' } }, - { value: 12.1, name: '能源成本', itemStyle: { color: '#ff9800' } }, - { value: 10.2, name: '其他成本', itemStyle: { color: '#f56c6c' } } + { value: 62.8, name: '材料成本', itemStyle: { color: '#00d4ff' } }, + { value: 14.9, name: '人工成本', itemStyle: { color: '#7c63ff' } }, + { value: 12.1, name: '能源成本', itemStyle: { color: '#ff9f43' } }, + { value: 10.2, name: '其他成本', itemStyle: { color: '#ff6b6b' } } ], label: { show: false } }] @@ -188,33 +225,38 @@ const initCharts = () => { if (barChartRef.value) { barChart = echarts.init(barChartRef.value) barChart.setOption({ - backgroundColor: '#ffffff', + backgroundColor: 'transparent', grid: { top: 20, right: 20, bottom: 30, left: 50 }, - tooltip: { trigger: 'axis' }, + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, xAxis: { type: 'category', data: ['1月', '2月', '3月', '4月', '5月'], - axisLine: { lineStyle: { color: '#ddd' } }, + axisLine: { lineStyle: { color: '#3a5a8a' } }, axisTick: { show: false }, - axisLabel: { color: '#666' } + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, axisTick: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666', formatter: (v) => (v / 10000).toFixed(0) + '万' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8', formatter: (v) => (v / 10000).toFixed(0) + '万' } }, series: [{ type: 'bar', - data: [142, 138, 152, 149, 156.8], - itemStyle: { - color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: '#4a90d9' }, - { offset: 1, color: '#5cd9e8' } - ]), - borderRadius: [4, 4, 0, 0] - } + data: [142, 138, 152, 149, 156.8].map((value, index) => ({ + value, + itemStyle: { + color: ['#00d4ff', '#7c63ff', '#00ff88', '#ff9f43', '#ff6b6b'][index], + borderRadius: [4, 4, 0, 0] + } + })), + barWidth: '50%' }] }) } @@ -248,18 +290,32 @@ onMounted(() => { } } }) + + fullscreenChangeHandler = handleFullscreenChange + document.addEventListener('fullscreenchange', fullscreenChangeHandler) + + window.addEventListener('refresh-data', handleRefresh) }) +const handleRefresh = () => { + initCharts() +} + onBeforeUnmount(() => { if (timeInterval) { clearInterval(timeInterval) timeInterval = null } window.removeEventListener('resize', handleResize) + window.removeEventListener('refresh-data', handleRefresh) if (resizeObserver) { resizeObserver.disconnect() resizeObserver = null } + if (fullscreenChangeHandler) { + document.removeEventListener('fullscreenchange', fullscreenChangeHandler) + fullscreenChangeHandler = null + } if (trendChart) { trendChart.dispose() trendChart = null @@ -283,18 +339,16 @@ onUnmounted(() => { .screen-wrapper { width: 100%; min-height: 100%; - background: #f5f5f5; + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 50%, #0a1428 100%); overflow-y: auto; overflow-x: hidden; } .screen-content { - background: #ffffff; - color: #333333; - border-radius: 8px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + background: transparent; + color: #ffffff; width: 100%; - padding-bottom: 20px; + padding: 20px; } .screen-header { @@ -302,94 +356,143 @@ onUnmounted(() => { justify-content: space-between; align-items: center; padding: 20px 30px; - border-bottom: 1px solid #eee; + background: linear-gradient(90deg, rgba(0, 212, 255, 0.1) 0%, rgba(12, 30, 60, 0.8) 100%); + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid rgba(0, 212, 255, 0.2); .title { - font-size: 24px; + font-size: 26px; font-weight: bold; - color: #333333; - letter-spacing: 2px; + color: #00d4ff; + letter-spacing: 3px; margin: 0; + text-shadow: 0 0 20px rgba(0, 212, 255, 0.5); + } + + .header-right { + display: flex; + align-items: center; + gap: 20px; } .time { - font-size: 16px; - color: #666666; + font-size: 18px; + color: #00d4ff; font-family: 'Courier New', monospace; + font-weight: bold; + } + + .fullscreen-btn { + width: 36px; + height: 36px; + border: 1px solid rgba(0, 212, 255, 0.3); + border-radius: 6px; + background: rgba(0, 212, 255, 0.1); + color: #00d4ff; + font-size: 18px; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + + &:hover { + background: rgba(0, 212, 255, 0.2); + border-color: rgba(0, 212, 255, 0.5); + box-shadow: 0 0 15px rgba(0, 212, 255, 0.3); + } + + &:active { + transform: scale(0.95); + } } } .screen-body { - padding: 15px; + padding: 0; } -.card-grid { +.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; - margin-bottom: 16px; + margin-bottom: 20px; - .data-card { - background: #fafafa; - border: 1px solid #e0e0e0; + .kpi-card { + background: linear-gradient(180deg, rgba(14, 40, 80, 0.9) 0%, rgba(10, 20, 40, 0.95) 100%); + border: 1px solid rgba(0, 212, 255, 0.2); border-radius: 8px; - padding: 20px; + padding: 0; text-align: center; - display: flex; - flex-direction: column; - justify-content: center; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .card-title { + .card-header { + background: linear-gradient(90deg, #00a8cc 0%, #00d4ff 50%, #00a8cc 100%); + padding: 10px 15px; font-size: 14px; - color: #666666; - margin-bottom: 10px; - } - - .card-value { - font-size: 32px; font-weight: bold; - margin-bottom: 4px; + color: #0a1428; + letter-spacing: 2px; } - .card-unit { - font-size: 12px; - color: #999999; + .kpi-value { + font-size: 36px; + font-weight: bold; + margin: 15px 0 5px; + text-shadow: 0 0 15px currentColor; + } + + .kpi-unit { + font-size: 14px; + color: #a0c4e8; + margin-bottom: 15px; } } } -.chart-area { - display: grid; - grid-template-columns: repeat(3, 1fr); +.chart-row { + display: flex; gap: 16px; margin-bottom: 16px; .chart-box { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.85) 0%, rgba(10, 20, 40, 0.9) 100%); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 8px; - padding: 15px; + padding: 0; display: flex; flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .box-title { + &.flex-1 { + flex: 1; + } + + .box-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 12px 18px; font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); } .chart { - height: 300px; + height: 280px; width: 100%; + padding: 15px; } .compare-list { + flex: 1; + padding: 15px; display: flex; flex-direction: column; - gap: 10px; + gap: 12px; .compare-item { display: flex; @@ -398,14 +501,14 @@ onUnmounted(() => { .name { width: 80px; - font-size: 14px; - color: #333333; + font-size: 13px; + color: #a0c4e8; } .bar-container { flex: 1; height: 12px; - background: #e0e0e0; + background: rgba(0, 212, 255, 0.2); border-radius: 6px; overflow: hidden; } @@ -420,42 +523,15 @@ onUnmounted(() => { width: 60px; text-align: right; font-size: 14px; - color: #4a90d9; + color: #00d4ff; font-weight: 600; } } } - } -} - -.bottom-area { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 16px; - - .bottom-box { - background: #fafafa; - border: 1px solid #e0e0e0; - border-radius: 8px; - padding: 15px; - display: flex; - flex-direction: column; - - .box-title { - font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; - } - - .chart { - height: 300px; - width: 100%; - } .cost-grid { + flex: 1; + padding: 15px; display: flex; flex-direction: column; gap: 15px; @@ -467,20 +543,20 @@ onUnmounted(() => { margin-bottom: 5px; .cost-name { - font-size: 14px; - color: #333333; + font-size: 13px; + color: #a0c4e8; } .cost-percent { font-size: 14px; - color: #4a90d9; + color: #00d4ff; font-weight: 600; } } .cost-bar { height: 8px; - background: #e0e0e0; + background: rgba(0, 212, 255, 0.2); border-radius: 4px; overflow: hidden; margin-bottom: 5px; @@ -493,33 +569,35 @@ onUnmounted(() => { } .cost-value { - font-size: 14px; - color: #666666; + font-size: 13px; + color: #ffffff; } } } .analysis-list { + flex: 1; + padding: 15px; display: flex; flex-direction: column; - gap: 12px; + gap: 10px; .analysis-item { display: flex; align-items: center; justify-content: space-between; padding: 10px; - background: #ffffff; - border: 1px solid #e0e0e0; + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 6px; .label { - font-size: 14px; - color: #666666; + font-size: 13px; + color: #a0c4e8; } .value { - font-size: 16px; + font-size: 14px; font-weight: bold; } @@ -529,13 +607,15 @@ onUnmounted(() => { border-radius: 4px; &.up { - background: rgba(82, 196, 26, 0.2); - color: #52c41a; + background: rgba(0, 255, 136, 0.15); + color: #00ff88; + border: 1px solid rgba(0, 255, 136, 0.3); } &.down { - background: rgba(245, 108, 108, 0.2); - color: #f56c6c; + background: rgba(255, 107, 107, 0.15); + color: #ff6b6b; + border: 1px solid rgba(255, 107, 107, 0.3); } } } @@ -544,25 +624,17 @@ onUnmounted(() => { } @media screen and (max-width: 1200px) { - .chart-area { + .kpi-grid { grid-template-columns: repeat(2, 1fr); } - .card-grid { - grid-template-columns: repeat(2, 1fr); + .chart-row { + flex-direction: column; } } @media screen and (max-width: 768px) { - .chart-area { - grid-template-columns: 1fr; - } - - .card-grid { - grid-template-columns: 1fr; - } - - .bottom-area { + .kpi-grid { grid-template-columns: 1fr; } } diff --git a/src/modules/dashboardBig/views/energy.vue b/src/modules/dashboardBig/views/energy.vue index f3481ad..9b0129d 100644 --- a/src/modules/dashboardBig/views/energy.vue +++ b/src/modules/dashboardBig/views/energy.vue @@ -3,39 +3,45 @@

能源监控大屏

- {{ currentTime }} +
+ {{ currentTime }} + +
-
-
-
{{ card.title }}
-
{{ card.value }}
-
{{ card.unit }}
-
- {{ card.trend > 0 ? '↑' : '↓' }} {{ Math.abs(card.trend) }}% +
+
+
{{ card.title }}
+
{{ card.value }}
+
{{ card.unit }}
+
+ {{ card.trend > 0 ? '↑' : '↓' }} + {{ Math.abs(card.trend) }}%
-
-
-
实时用电量
+
+
+
实时用电量
-
-
能源消耗趋势
+
+
能源消耗趋势
-
-
能源类型分布
+
+
能源类型分布
-
-
-
设备能耗排名
+
+
+
设备能耗排名
{{ index + 1 }} @@ -47,12 +53,12 @@
-
-
生产班次能耗
+
+
生产班次能耗
-
-
实时告警
+
+
实时告警
{{ alarm.icon }} @@ -74,6 +80,7 @@ import { ref, onMounted, onBeforeUnmount, onUnmounted, nextTick } from 'vue' import * as echarts from 'echarts' const currentTime = ref('') +const isFullscreen = ref(false) const gaugeChartRef = ref(null) const lineChartRef = ref(null) const pieChartRef = ref(null) @@ -81,23 +88,24 @@ const barChartRef = ref(null) let gaugeChart = null let lineChart = null let pieChart = null +let fullscreenChangeHandler = null let barChart = null let timeInterval = null let resizeObserver = null const energyOverview = ref([ - { title: '今日用电', value: '25,600', unit: 'kWh', color: '#5cd9e8', trend: 5.2 }, - { title: '今日用气', value: '1,850', unit: 'm³', color: '#52c41a', trend: -2.1 }, - { title: '今日用水', value: '320', unit: 't', color: '#4a90d9', trend: 1.8 }, - { title: '综合能耗', value: '38.5', unit: 'kgce/t', color: '#ff9800', trend: -3.5 } + { title: '今日用电', value: '25,600', unit: 'kWh', color: '#00d4ff', trend: 5.2 }, + { title: '今日用气', value: '1,850', unit: 'm³', color: '#00ff88', trend: -2.1 }, + { title: '今日用水', value: '320', unit: 't', color: '#7c63ff', trend: 1.8 }, + { title: '综合能耗', value: '38.5', unit: 'kgce/t', color: '#ff9f43', trend: -3.5 } ]) const equipmentRanking = ref([ - { name: '酸轧机组', value: '8,500', percent: 85, color: '#f56c6c' }, - { name: '退火炉', value: '5,200', percent: 52, color: '#e6a23c' }, - { name: '轧机', value: '4,800', percent: 48, color: '#4a90d9' }, - { name: '酸洗槽', value: '3,200', percent: 32, color: '#52c41a' }, - { name: '剪切线', value: '2,600', percent: 26, color: '#909399' } + { name: '酸轧机组', value: '8,500', percent: 85, color: '#ff6b6b' }, + { name: '退火炉', value: '5,200', percent: 52, color: '#ffd43b' }, + { name: '轧机', value: '4,800', percent: 48, color: '#00d4ff' }, + { name: '酸洗槽', value: '3,200', percent: 32, color: '#00ff88' }, + { name: '剪切线', value: '2,600', percent: 26, color: '#7c63ff' } ]) const alarms = ref([ @@ -121,7 +129,7 @@ const initCharts = () => { if (gaugeChartRef.value) { gaugeChart = echarts.init(gaugeChartRef.value) gaugeChart.setOption({ - backgroundColor: '#ffffff', + backgroundColor: 'transparent', series: [{ type: 'gauge', center: ['50%', '60%'], @@ -130,10 +138,10 @@ const initCharts = () => { min: 0, max: 100, splitNumber: 10, - itemStyle: { color: '#5cd9e8' }, + itemStyle: { color: '#00d4ff' }, progress: { show: true, width: 20 }, pointer: { show: false }, - axisLine: { lineStyle: { width: 20, color: [[1, 'rgba(92,217,232,0.2)']] } }, + axisLine: { lineStyle: { width: 20, color: [[1, 'rgba(0, 212, 255, 0.2)']] } }, axisTick: { show: false }, splitLine: { show: false }, axisLabel: { show: false }, @@ -142,7 +150,7 @@ const initCharts = () => { valueAnimation: true, fontSize: 32, fontWeight: 'bold', - color: '#5cd9e8', + color: '#00d4ff', formatter: '{value}%', offsetCenter: [0, '10%'] }, @@ -154,20 +162,27 @@ const initCharts = () => { if (lineChartRef.value) { lineChart = echarts.init(lineChartRef.value) lineChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'axis', axisPointer: { type: 'line', lineStyle: { color: '#5cd9e8' } } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' }, + axisPointer: { type: 'line', lineStyle: { color: '#00d4ff' } } + }, grid: { top: 20, right: 20, bottom: 30, left: 50 }, xAxis: { type: 'category', data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'], - axisLine: { lineStyle: { color: '#ddd' } }, - axisLabel: { color: '#666' } + axisLine: { lineStyle: { color: '#3a5a8a' } }, + axisTick: { show: false }, + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, series: [ { @@ -177,20 +192,20 @@ const initCharts = () => { data: [620, 680, 650, 720, 780, 820], areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: 'rgba(92, 217, 232, 0.3)' }, - { offset: 1, color: 'rgba(92, 217, 232, 0.05)' } + { offset: 0, color: 'rgba(0, 212, 255, 0.3)' }, + { offset: 1, color: 'rgba(0, 212, 255, 0.05)' } ]) }, - lineStyle: { color: '#5cd9e8', width: 2 }, - itemStyle: { color: '#5cd9e8' } + lineStyle: { color: '#00d4ff', width: 2 }, + itemStyle: { color: '#00d4ff' } }, { name: '用气', type: 'line', smooth: true, data: [45, 48, 46, 52, 55, 58], - lineStyle: { color: '#52c41a', width: 2 }, - itemStyle: { color: '#52c41a' } + lineStyle: { color: '#00ff88', width: 2 }, + itemStyle: { color: '#00ff88' } } ] }) @@ -199,18 +214,24 @@ const initCharts = () => { if (pieChartRef.value) { pieChart = echarts.init(pieChartRef.value) pieChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' }, - legend: { bottom: 10, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + formatter: '{b}: {c}% ({d}%)', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['45%', '75%'], center: ['50%', '45%'], data: [ - { value: 65, name: '电能', itemStyle: { color: '#5cd9e8' } }, - { value: 20, name: '天然气', itemStyle: { color: '#ff9800' } }, - { value: 10, name: '水', itemStyle: { color: '#4a90d9' } }, - { value: 5, name: '其他', itemStyle: { color: '#909399' } } + { value: 65, name: '电能', itemStyle: { color: '#00d4ff' } }, + { value: 20, name: '天然气', itemStyle: { color: '#ff9f43' } }, + { value: 10, name: '水', itemStyle: { color: '#7c63ff' } }, + { value: 5, name: '其他', itemStyle: { color: '#a0c4e8' } } ], label: { show: false } }] @@ -220,30 +241,36 @@ const initCharts = () => { if (barChartRef.value) { barChart = echarts.init(barChartRef.value) barChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'axis' }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, grid: { top: 20, right: 20, bottom: 30, left: 50 }, xAxis: { type: 'category', data: ['早班', '中班', '晚班'], - axisLine: { lineStyle: { color: '#ddd' } }, - axisLabel: { color: '#666' } + axisLine: { lineStyle: { color: '#3a5a8a' } }, + axisTick: { show: false }, + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, series: [{ type: 'bar', - data: [9800, 12500, 8500], - itemStyle: { - color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: '#5cd9e8' }, - { offset: 1, color: '#4a90d9' } - ]) - }, + data: [9800, 12500, 8500].map((value, index) => ({ + value, + itemStyle: { + color: ['#00d4ff', '#7c63ff', '#00ff88'][index], + borderRadius: [4, 4, 0, 0] + } + })), barWidth: '50%' }] }) @@ -279,18 +306,42 @@ onMounted(() => { } } }) + + window.addEventListener('refresh-data', handleRefresh) + + fullscreenChangeHandler = () => { + isFullscreen.value = !!document.fullscreenElement + } + document.addEventListener('fullscreenchange', fullscreenChangeHandler) }) +const handleRefresh = () => { + initCharts() +} + +const exitFullscreen = () => { + if (document.fullscreenElement) { + document.exitFullscreen().catch(err => { + console.error('退出全屏失败:', err) + }) + } +} + onBeforeUnmount(() => { if (timeInterval) { clearInterval(timeInterval) timeInterval = null } window.removeEventListener('resize', handleResize) + window.removeEventListener('refresh-data', handleRefresh) if (resizeObserver) { resizeObserver.disconnect() resizeObserver = null } + if (fullscreenChangeHandler) { + document.removeEventListener('fullscreenchange', fullscreenChangeHandler) + fullscreenChangeHandler = null + } if (gaugeChart) { gaugeChart.dispose() gaugeChart = null @@ -318,18 +369,16 @@ onUnmounted(() => { .screen-wrapper { width: 100%; min-height: 100%; - background: #f5f5f5; + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 50%, #0a1428 100%); overflow-y: auto; overflow-x: hidden; } .screen-content { - background: #ffffff; - color: #333333; - border-radius: 8px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + background: transparent; + color: #ffffff; width: 100%; - padding-bottom: 20px; + padding: 20px; } .screen-header { @@ -337,128 +386,153 @@ onUnmounted(() => { justify-content: space-between; align-items: center; padding: 20px 30px; - border-bottom: 1px solid #eee; + background: linear-gradient(90deg, rgba(0, 212, 255, 0.1) 0%, rgba(12, 30, 60, 0.8) 100%); + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid rgba(0, 212, 255, 0.2); .title { - font-size: 24px; + font-size: 26px; font-weight: bold; - color: #333333; - letter-spacing: 2px; + color: #00d4ff; + letter-spacing: 3px; margin: 0; + text-shadow: 0 0 20px rgba(0, 212, 255, 0.5); + } + + .header-right { + display: flex; + align-items: center; + gap: 20px; } .time { - font-size: 16px; - color: #666666; + font-size: 18px; + color: #00d4ff; font-family: 'Courier New', monospace; + font-weight: bold; + } + + .exit-fullscreen-btn { + padding: 8px 16px; + border: 1px solid rgba(255, 107, 107, 0.5); + border-radius: 6px; + background: rgba(255, 107, 107, 0.2); + color: #ff6b6b; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(255, 107, 107, 0.3); + border-color: #ff6b6b; + box-shadow: 0 0 15px rgba(255, 107, 107, 0.3); + } } } .screen-body { - padding: 15px; + padding: 0; } -.card-grid { +.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; - margin-bottom: 16px; + margin-bottom: 20px; - .data-card { - background: #fafafa; - border: 1px solid #e0e0e0; + .kpi-card { + background: linear-gradient(180deg, rgba(14, 40, 80, 0.9) 0%, rgba(10, 20, 40, 0.95) 100%); + border: 1px solid rgba(0, 212, 255, 0.2); border-radius: 8px; - padding: 20px; + padding: 0; text-align: center; - display: flex; - flex-direction: column; - justify-content: center; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .card-title { + .card-header { + background: linear-gradient(90deg, #00a8cc 0%, #00d4ff 50%, #00a8cc 100%); + padding: 10px 15px; font-size: 14px; - color: #666666; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + } + + .kpi-value { + font-size: 36px; + font-weight: bold; + margin: 15px 0 5px; + text-shadow: 0 0 15px currentColor; + } + + .kpi-unit { + font-size: 14px; + color: #a0c4e8; margin-bottom: 10px; } - .card-value { - font-size: 32px; - font-weight: bold; - margin-bottom: 4px; - } + .kpi-trend { + font-size: 13px; + padding: 3px 10px; + border-radius: 12px; + display: inline-block; + margin-bottom: 15px; + font-weight: 600; - .card-unit { - font-size: 12px; - color: #999999; - } + &.positive { + background: rgba(0, 255, 136, 0.15); + color: #00ff88; + border: 1px solid rgba(0, 255, 136, 0.3); + } - .card-trend { - font-size: 12px; - margin-top: 6px; - - &.up { color: #f56c6c; } - &.down { color: #52c41a; } + &.negative { + background: rgba(255, 107, 107, 0.15); + color: #ff6b6b; + border: 1px solid rgba(255, 107, 107, 0.3); + } } } } -.chart-area { - display: grid; - grid-template-columns: repeat(3, 1fr); +.chart-row { + display: flex; gap: 16px; margin-bottom: 16px; .chart-box { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.85) 0%, rgba(10, 20, 40, 0.9) 100%); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 8px; - padding: 15px; + padding: 0; display: flex; flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .box-title { + &.flex-1 { + flex: 1; + } + + .box-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 12px 18px; font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); } .chart { - height: 300px; - width: 100%; - } - } -} - -.bottom-area { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 16px; - - .bottom-box { - background: #fafafa; - border: 1px solid #e0e0e0; - border-radius: 8px; - padding: 15px; - display: flex; - flex-direction: column; - - .box-title { - font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; - } - - .chart { - height: 300px; + height: 280px; width: 100%; + padding: 15px; } .ranking-list { + flex: 1; + padding: 15px; display: flex; flex-direction: column; gap: 10px; @@ -466,39 +540,48 @@ onUnmounted(() => { .ranking-item { display: flex; align-items: center; - padding: 8px 12px; - background: #ffffff; - border: 1px solid #e0e0e0; + padding: 10px 12px; + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 6px; .rank { - width: 22px; - height: 22px; + width: 24px; + height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; - margin-right: 10px; - background: #e0e0e0; - color: #666; + margin-right: 12px; + background: #3a5a8a; + color: #a0c4e8; - &.rank-1 { background: linear-gradient(135deg, #ffd700, #ffb700); color: #fff; } - &.rank-2 { background: linear-gradient(135deg, #c0c0c0, #a0a0a0); color: #fff; } - &.rank-3 { background: linear-gradient(135deg, #cd7f32, #b87333); color: #fff; } + &.rank-1 { + background: linear-gradient(135deg, #ffd43b, #ff9f43); + color: #0a1428; + } + &.rank-2 { + background: linear-gradient(135deg, #a0c4e8, #74c0fc); + color: #0a1428; + } + &.rank-3 { + background: linear-gradient(135deg, #ffa94d, #ff6b6b); + color: #fff; + } } .name { flex: 1; font-size: 13px; - color: #333333; + color: #a0c4e8; } .bar-wrapper { width: 80px; height: 8px; - background: #e0e0e0; + background: rgba(0, 212, 255, 0.2); border-radius: 4px; margin-right: 10px; overflow: hidden; @@ -513,12 +596,14 @@ onUnmounted(() => { .value { font-size: 14px; font-weight: bold; - color: #4a90d9; + color: #00d4ff; } } } .alarm-list { + flex: 1; + padding: 15px; display: flex; flex-direction: column; gap: 10px; @@ -526,42 +611,42 @@ onUnmounted(() => { .alarm-item { display: flex; align-items: center; - padding: 10px; + padding: 12px; border-radius: 6px; border-left: 4px solid; - background: #ffffff; - border: 1px solid #e0e0e0; + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.15); border-left-width: 4px; &.danger { - border-color: #f56c6c; + border-color: #ff6b6b; } &.warning { - border-color: #e6a23c; + border-color: #ffd43b; } &.success { - border-color: #52c41a; + border-color: #00ff88; } .alarm-icon { - font-size: 16px; - margin-right: 10px; + font-size: 18px; + margin-right: 12px; } .alarm-content { flex: 1; .alarm-title { - font-size: 13px; - color: #333333; - margin-bottom: 2px; + font-size: 14px; + color: #ffffff; + margin-bottom: 4px; } .alarm-time { - font-size: 11px; - color: #999999; + font-size: 12px; + color: #a0c4e8; } } } @@ -570,25 +655,17 @@ onUnmounted(() => { } @media screen and (max-width: 1200px) { - .chart-area { + .kpi-grid { grid-template-columns: repeat(2, 1fr); } - .card-grid { - grid-template-columns: repeat(2, 1fr); + .chart-row { + flex-direction: column; } } @media screen and (max-width: 768px) { - .chart-area { - grid-template-columns: 1fr; - } - - .card-grid { - grid-template-columns: 1fr; - } - - .bottom-area { + .kpi-grid { grid-template-columns: 1fr; } } diff --git a/src/modules/dashboardBig/views/index.vue b/src/modules/dashboardBig/views/index.vue index f6e952c..711c7c5 100644 --- a/src/modules/dashboardBig/views/index.vue +++ b/src/modules/dashboardBig/views/index.vue @@ -3,29 +3,34 @@

大数据可视化平台

- {{ currentTime }} +
+ {{ currentTime }} + +
-
-
-
{{ card.title }}
-
{{ card.value }}
-
{{ card.unit }}
+
+
+
{{ card.title }}
+
{{ card.value }}
+
{{ card.unit }}
-
-
-
产量趋势
+
+
+
产量趋势
-
-
运行状态
+
+
运行状态
-
-
班组排名
+
+
班组排名
{{ index + 1 }} @@ -37,9 +42,9 @@
-
-
-
实时告警
+
+
+
实时告警
{{ alarm.icon }} @@ -61,18 +66,20 @@ import { ref, onMounted, onBeforeUnmount, onUnmounted, nextTick } from 'vue' import * as echarts from 'echarts' const currentTime = ref('') +const isFullscreen = ref(false) const lineChartRef = ref(null) const pieChartRef = ref(null) let lineChart = null let pieChart = null let timeInterval = null let resizeObserver = null +let fullscreenChangeHandler = null const cards = ref([ - { title: '总产量', value: '12,580', unit: '吨', color: '#4a90d9' }, - { title: '日产量', value: '1,258', unit: '吨', color: '#52c41a' }, - { title: '运行效率', value: '96.8', unit: '%', color: '#5cd9e8' }, - { title: '良品率', value: '99.2', unit: '%', color: '#ff9800' } + { title: '总产量', value: '12,580', unit: '吨', color: '#00d4ff' }, + { title: '日产量', value: '1,258', unit: '吨', color: '#00ff88' }, + { title: '运行效率', value: '96.8', unit: '%', color: '#7c63ff' }, + { title: '良品率', value: '99.2', unit: '%', color: '#ff9f43' } ]) const rankingList = ref([ @@ -83,9 +90,9 @@ const rankingList = ref([ ]) const alarmList = ref([ - { icon: '✅', title: '系统运行正常', time: '15:30:00' }, - { icon: '⚠️', title: '速度损失告警', time: '14:25:00' }, - { icon: '🔴', title: '设备故障停机', time: '13:15:00' } + { icon: '✅', title: '系统运行正常', time: '15:30:00', level: 'success' }, + { icon: '⚠️', title: '速度损失告警', time: '14:25:00', level: 'warning' }, + { icon: '🔴', title: '设备故障停机', time: '13:15:00', level: 'danger' } ]) const updateTime = () => { @@ -103,20 +110,26 @@ const initCharts = () => { if (lineChartRef.value) { lineChart = echarts.init(lineChartRef.value) lineChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'axis' }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, grid: { top: 20, right: 20, bottom: 30, left: 50 }, xAxis: { type: 'category', data: ['08:00', '10:00', '12:00', '14:00', '16:00', '18:00'], - axisLine: { lineStyle: { color: '#ddd' } }, - axisLabel: { color: '#666' } + axisLine: { lineStyle: { color: '#3a5a8a' } }, + axisTick: { show: false }, + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, series: [{ name: '产量', @@ -125,12 +138,12 @@ const initCharts = () => { data: [820, 932, 901, 1234, 1290, 1330], areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: 'rgba(74, 144, 217, 0.3)' }, - { offset: 1, color: 'rgba(74, 144, 217, 0.05)' } + { offset: 0, color: 'rgba(0, 212, 255, 0.3)' }, + { offset: 1, color: 'rgba(0, 212, 255, 0.05)' } ]) }, - lineStyle: { color: '#4a90d9', width: 2 }, - itemStyle: { color: '#4a90d9' } + lineStyle: { color: '#00d4ff', width: 2 }, + itemStyle: { color: '#00d4ff' } }] }) } @@ -138,18 +151,24 @@ const initCharts = () => { if (pieChartRef.value) { pieChart = echarts.init(pieChartRef.value) pieChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item', formatter: '{b}: {c}% ({d}%)' }, - legend: { bottom: 10, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + formatter: '{b}: {c}% ({d}%)', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['45%', '75%'], center: ['50%', '45%'], data: [ - { value: 65, name: '运行中', itemStyle: { color: '#52c41a' } }, - { value: 20, name: '待机', itemStyle: { color: '#ff9800' } }, - { value: 10, name: '故障', itemStyle: { color: '#f56c6c' } }, - { value: 5, name: '维护', itemStyle: { color: '#5cd9e8' } } + { value: 65, name: '运行中', itemStyle: { color: '#00ff88' } }, + { value: 20, name: '待机', itemStyle: { color: '#ffd43b' } }, + { value: 10, name: '故障', itemStyle: { color: '#ff6b6b' } }, + { value: 5, name: '维护', itemStyle: { color: '#00d4ff' } } ], label: { show: false } }] @@ -184,18 +203,42 @@ onMounted(() => { } } }) + + window.addEventListener('refresh-data', handleRefresh) + + fullscreenChangeHandler = () => { + isFullscreen.value = !!document.fullscreenElement + } + document.addEventListener('fullscreenchange', fullscreenChangeHandler) }) +const handleRefresh = () => { + initCharts() +} + +const exitFullscreen = () => { + if (document.fullscreenElement) { + document.exitFullscreen().catch(err => { + console.error('退出全屏失败:', err) + }) + } +} + onBeforeUnmount(() => { if (timeInterval) { clearInterval(timeInterval) timeInterval = null } window.removeEventListener('resize', handleResize) + window.removeEventListener('refresh-data', handleRefresh) if (resizeObserver) { resizeObserver.disconnect() resizeObserver = null } + if (fullscreenChangeHandler) { + document.removeEventListener('fullscreenchange', fullscreenChangeHandler) + fullscreenChangeHandler = null + } if (lineChart) { lineChart.dispose() lineChart = null @@ -215,18 +258,16 @@ onUnmounted(() => { .screen-wrapper { width: 100%; min-height: 100%; - background: #f5f5f5; + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 50%, #0a1428 100%); overflow-y: auto; overflow-x: hidden; } .screen-content { - background: #ffffff; - color: #333333; - border-radius: 8px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + background: transparent; + color: #ffffff; width: 100%; - padding-bottom: 20px; + padding: 20px; } .screen-header { @@ -234,106 +275,151 @@ onUnmounted(() => { justify-content: space-between; align-items: center; padding: 20px 30px; - border-bottom: 1px solid #eee; + background: linear-gradient(90deg, rgba(0, 212, 255, 0.1) 0%, rgba(12, 30, 60, 0.8) 100%); + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid rgba(0, 212, 255, 0.2); .title { - font-size: 24px; + font-size: 26px; font-weight: bold; - color: #333333; - letter-spacing: 2px; + color: #00d4ff; + letter-spacing: 3px; margin: 0; + text-shadow: 0 0 20px rgba(0, 212, 255, 0.5); + } + + .header-right { + display: flex; + align-items: center; + gap: 20px; } .time { - font-size: 16px; - color: #666666; + font-size: 18px; + color: #00d4ff; font-family: 'Courier New', monospace; + font-weight: bold; + } + + .exit-fullscreen-btn { + padding: 8px 16px; + border: 1px solid rgba(255, 107, 107, 0.5); + border-radius: 6px; + background: rgba(255, 107, 107, 0.2); + color: #ff6b6b; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(255, 107, 107, 0.3); + border-color: #ff6b6b; + box-shadow: 0 0 15px rgba(255, 107, 107, 0.3); + } } } .screen-body { - padding: 15px; + padding: 0; } -.card-grid { +.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; - margin-bottom: 16px; + margin-bottom: 20px; - .data-card { - background: #fafafa; - border: 1px solid #e0e0e0; + .kpi-card { + background: linear-gradient(180deg, rgba(14, 40, 80, 0.9) 0%, rgba(10, 20, 40, 0.95) 100%); + border: 1px solid rgba(0, 212, 255, 0.2); border-radius: 8px; - padding: 20px; + padding: 0; text-align: center; - display: flex; - flex-direction: column; - justify-content: center; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .card-title { + .card-header { + background: linear-gradient(90deg, #00a8cc 0%, #00d4ff 50%, #00a8cc 100%); + padding: 10px 15px; font-size: 14px; - color: #666666; - margin-bottom: 10px; - } - - .card-value { - font-size: 32px; font-weight: bold; - margin-bottom: 4px; + color: #0a1428; + letter-spacing: 2px; } - .card-unit { - font-size: 12px; - color: #999999; + .kpi-value { + font-size: 36px; + font-weight: bold; + margin: 15px 0 5px; + text-shadow: 0 0 15px currentColor; + } + + .kpi-unit { + font-size: 14px; + color: #a0c4e8; + margin-bottom: 15px; } } } -.chart-area { - display: grid; - grid-template-columns: repeat(3, 1fr); +.chart-row { + display: flex; gap: 16px; margin-bottom: 16px; .chart-box { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.85) 0%, rgba(10, 20, 40, 0.9) 100%); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 8px; - padding: 15px; + padding: 0; display: flex; flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .box-title { + &.flex-1 { + flex: 1; + } + + &.flex-2 { + flex: 2; + } + + .box-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 12px 18px; font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); } .chart { height: 300px; width: 100%; + padding: 15px; } .ranking-list { + flex: 1; + padding: 15px; display: flex; flex-direction: column; - gap: 10px; + gap: 12px; .ranking-item { display: flex; align-items: center; - padding: 10px 12px; - background: #ffffff; - border: 1px solid #e0e0e0; + padding: 12px; + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 6px; .rank { - width: 22px; - height: 22px; + width: 24px; + height: 24px; border-radius: 50%; display: flex; align-items: center; @@ -341,89 +427,89 @@ onUnmounted(() => { font-size: 12px; font-weight: bold; margin-right: 12px; - background: #e0e0e0; - color: #666; + background: #3a5a8a; + color: #a0c4e8; - &.rank-1 { background: linear-gradient(135deg, #ffd700, #ffb700); color: #fff; } - &.rank-2 { background: linear-gradient(135deg, #c0c0c0, #a0a0a0); color: #fff; } - &.rank-3 { background: linear-gradient(135deg, #cd7f32, #b87333); color: #fff; } + &.rank-1 { + background: linear-gradient(135deg, #ffd43b, #ff9f43); + color: #0a1428; + } + &.rank-2 { + background: linear-gradient(135deg, #a0c4e8, #74c0fc); + color: #0a1428; + } + &.rank-3 { + background: linear-gradient(135deg, #ffa94d, #ff6b6b); + color: #fff; + } } .name { flex: 1; - font-size: 13px; - color: #333333; + font-size: 14px; + color: #a0c4e8; } .value { - font-size: 14px; + font-size: 16px; font-weight: bold; - color: #4a90d9; + color: #00d4ff; } .unit { - font-size: 12px; - color: #999999; - margin-left: 4px; + font-size: 13px; + color: #a0c4e8; + margin-left: 5px; } } } - } -} - -.alarm-area { - display: grid; - grid-template-columns: 1fr; - gap: 16px; - - .alarm-box { - background: #fafafa; - border: 1px solid #e0e0e0; - border-radius: 8px; - padding: 15px; - display: flex; - flex-direction: column; - - .box-title { - font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; - } .alarm-list { + flex: 1; + padding: 15px; display: flex; flex-direction: column; - gap: 10px; + gap: 12px; .alarm-item { display: flex; align-items: center; - padding: 10px; + padding: 15px; border-radius: 6px; - border-left: 4px solid #4a90d9; - background: #ffffff; - border: 1px solid #e0e0e0; + border-left: 4px solid; + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.15); + border-left-width: 4px; + + &.success { + border-color: #00ff88; + } + + &.warning { + border-color: #ffd43b; + } + + &.danger { + border-color: #ff6b6b; + } .alarm-icon { - font-size: 16px; - margin-right: 10px; + font-size: 20px; + margin-right: 14px; } .alarm-content { flex: 1; .alarm-title { - font-size: 13px; - color: #333333; - margin-bottom: 2px; + font-size: 14px; + color: #ffffff; + margin-bottom: 5px; } .alarm-time { - font-size: 11px; - color: #999999; + font-size: 12px; + color: #a0c4e8; } } } @@ -432,21 +518,17 @@ onUnmounted(() => { } @media screen and (max-width: 1200px) { - .chart-area { + .kpi-grid { grid-template-columns: repeat(2, 1fr); } - .card-grid { - grid-template-columns: repeat(2, 1fr); + .chart-row { + flex-direction: column; } } @media screen and (max-width: 768px) { - .chart-area { - grid-template-columns: 1fr; - } - - .card-grid { + .kpi-grid { grid-template-columns: 1fr; } } diff --git a/src/modules/dashboardBig/views/oee.vue b/src/modules/dashboardBig/views/oee.vue index 1f51699..d0e8fc2 100644 --- a/src/modules/dashboardBig/views/oee.vue +++ b/src/modules/dashboardBig/views/oee.vue @@ -6,39 +6,42 @@
当前班组:{{ currentShift }} {{ currentTime }} +
-
OEE
-
{{ oeeData.oee.toFixed(1) }}%
-
+
OEE
+
{{ oeeData.oee.toFixed(1) }}%
+
{{ oeeData.oeeTrend > 0 ? '↑' : '↓' }} {{ Math.abs(oeeData.oeeTrend).toFixed(1) }}%
-
时间稼动率
-
{{ oeeData.availability.toFixed(1) }}%
-
+
时间稼动率
+
{{ oeeData.availability.toFixed(1) }}%
+
{{ oeeData.availabilityTrend > 0 ? '↑' : '↓' }} {{ Math.abs(oeeData.availabilityTrend).toFixed(1) }}%
-
性能稼动率
-
{{ oeeData.performance.toFixed(1) }}%
-
+
性能稼动率
+
{{ oeeData.performance.toFixed(1) }}%
+
{{ oeeData.performanceTrend > 0 ? '↑' : '↓' }} {{ Math.abs(oeeData.performanceTrend).toFixed(1) }}%
-
良品率
-
{{ oeeData.quality.toFixed(1) }}%
-
+
良品率
+
{{ oeeData.quality.toFixed(1) }}%
+
{{ oeeData.qualityTrend > 0 ? '↑' : '↓' }} {{ Math.abs(oeeData.qualityTrend).toFixed(1) }}%
@@ -47,22 +50,22 @@
-
OEE趋势分析
+
OEE趋势分析
-
7大损失分布
+
7大损失分布
-
设备状态监控
+
设备状态监控
-
停机事件明细
+
停机事件明细
@@ -87,6 +90,7 @@ import { getOeeDailySummary, getOeeLossSummary, getOeeStoppageEvents } from '@/a const currentTime = ref('') const currentShift = ref('甲班') +const isFullscreen = ref(false) const trendChartRef = ref(null) const lossChartRef = ref(null) const statusChartRef = ref(null) @@ -96,6 +100,7 @@ let statusChart = null let timeInterval = null let dataInterval = null let resizeObserver = null +let fullscreenChangeHandler = null const oeeData = ref({ oee: 0, @@ -112,6 +117,12 @@ const summaryList = ref([]) const lossList = ref([]) const stoppageList = ref([]) +const getTrendClass = (value) => { + if (value > 0) return 'positive' + if (value < 0) return 'negative' + return 'zero' +} + const updateTime = () => { currentTime.value = new Date().toLocaleString('zh-CN', { year: 'numeric', @@ -221,28 +232,33 @@ const updateTrendChart = () => { const qualValues = summaryList.value.map(item => item.quality) trendChart.setOption({ - backgroundColor: '#ffffff', + backgroundColor: 'transparent', grid: { top: 40, right: 20, bottom: 30, left: 50 }, - tooltip: { trigger: 'axis' }, + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, legend: { data: ['OEE', '时间稼动率', '性能稼动率', '良品率'], bottom: 0, - textStyle: { color: '#666' } + textStyle: { color: '#a0c4e8' } }, xAxis: { type: 'category', data: dates, - axisLine: { lineStyle: { color: '#ddd' } }, + axisLine: { lineStyle: { color: '#3a5a8a' } }, axisTick: { show: false }, - axisLabel: { color: '#666' } + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', min: 70, max: 100, axisLine: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, series: [ { @@ -250,34 +266,40 @@ const updateTrendChart = () => { type: 'line', smooth: true, data: oeeValues, - lineStyle: { color: '#4a90d9', width: 3 }, - itemStyle: { color: '#4a90d9' }, + lineStyle: { color: '#00d4ff', width: 3 }, + itemStyle: { color: '#00d4ff' }, symbol: 'circle', - symbolSize: 8 + symbolSize: 8, + areaStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { offset: 0, color: 'rgba(0, 212, 255, 0.3)' }, + { offset: 1, color: 'rgba(0, 212, 255, 0.05)' } + ]) + } }, { name: '时间稼动率', type: 'line', smooth: true, data: avalValues, - lineStyle: { color: '#52c41a', width: 2 }, - itemStyle: { color: '#52c41a' } + lineStyle: { color: '#00ff88', width: 2 }, + itemStyle: { color: '#00ff88' } }, { name: '性能稼动率', type: 'line', smooth: true, data: perfValues, - lineStyle: { color: '#5cd9e8', width: 2 }, - itemStyle: { color: '#5cd9e8' } + lineStyle: { color: '#7c63ff', width: 2 }, + itemStyle: { color: '#7c63ff' } }, { name: '良品率', type: 'line', smooth: true, data: qualValues, - lineStyle: { color: '#ff9800', width: 2 }, - itemStyle: { color: '#ff9800' } + lineStyle: { color: '#ff9f43', width: 2 }, + itemStyle: { color: '#ff9f43' } } ] }) @@ -287,9 +309,15 @@ const updateLossChart = () => { if (!lossChart) return lossChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item', formatter: '{b}: {c}分钟 ({d}%)' }, - legend: { bottom: 0, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + formatter: '{b}: {c}分钟 ({d}%)', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['40%', '70%'], @@ -298,10 +326,17 @@ const updateLossChart = () => { value: item.lossTimeMin || 0, name: item.lossCategoryName || '损失' + (index + 1), itemStyle: { - color: ['#4a90d9', '#5cd9e8', '#52c41a', '#ff9800', '#ff5722', '#9c27b0', '#673ab7'][index] + color: ['#ff6b6b', '#ffa94d', '#ffd43b', '#69db7c', '#74c0fc', '#b197fc', '#ff8fab'][index] } })), - label: { show: false } + label: { show: false }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } }] }) } @@ -310,20 +345,32 @@ const updateStatusChart = () => { if (!statusChart) return statusChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item' }, - legend: { bottom: 0, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['40%', '70%'], center: ['50%', '45%'], data: [ - { value: 65, name: '运行中', itemStyle: { color: '#52c41a' } }, - { value: 15, name: '待机', itemStyle: { color: '#ff9800' } }, - { value: 12, name: '故障', itemStyle: { color: '#f56c6c' } }, - { value: 8, name: '维护', itemStyle: { color: '#5cd9e8' } } + { value: 65, name: '运行中', itemStyle: { color: '#00ff88' } }, + { value: 15, name: '待机', itemStyle: { color: '#ffd43b' } }, + { value: 12, name: '故障', itemStyle: { color: '#ff6b6b' } }, + { value: 8, name: '维护', itemStyle: { color: '#74c0fc' } } ], - label: { show: false } + label: { show: false }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } }] }) } @@ -366,8 +413,27 @@ onMounted(() => { dataInterval = setInterval(loadData, 30000) }) + + window.addEventListener('refresh-data', handleRefresh) + + fullscreenChangeHandler = () => { + isFullscreen.value = !!document.fullscreenElement + } + document.addEventListener('fullscreenchange', fullscreenChangeHandler) }) +const handleRefresh = () => { + loadData() +} + +const exitFullscreen = () => { + if (document.fullscreenElement) { + document.exitFullscreen().catch(err => { + console.error('退出全屏失败:', err) + }) + } +} + onBeforeUnmount(() => { if (timeInterval) { clearInterval(timeInterval) @@ -378,10 +444,15 @@ onBeforeUnmount(() => { dataInterval = null } window.removeEventListener('resize', handleResize) + window.removeEventListener('refresh-data', handleRefresh) if (resizeObserver) { resizeObserver.disconnect() resizeObserver = null } + if (fullscreenChangeHandler) { + document.removeEventListener('fullscreenchange', fullscreenChangeHandler) + fullscreenChangeHandler = null + } if (trendChart) { trendChart.dispose() trendChart = null @@ -405,18 +476,16 @@ onUnmounted(() => { .screen-wrapper { width: 100%; min-height: 100%; - background: #f5f5f5; + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 50%, #0a1428 100%); overflow-y: auto; overflow-x: hidden; } .screen-content { - background: #ffffff; - color: #333333; - border-radius: 8px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + background: transparent; + color: #ffffff; width: 100%; - padding-bottom: 20px; + padding: 20px; } .screen-header { @@ -424,88 +493,117 @@ onUnmounted(() => { justify-content: space-between; align-items: center; padding: 20px 30px; - border-bottom: 1px solid #eee; + background: linear-gradient(90deg, rgba(0, 212, 255, 0.1) 0%, rgba(12, 30, 60, 0.8) 100%); + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid rgba(0, 212, 255, 0.2); .title { - font-size: 24px; + font-size: 26px; font-weight: bold; - color: #333333; - letter-spacing: 2px; + color: #00d4ff; + letter-spacing: 3px; margin: 0; + text-shadow: 0 0 20px rgba(0, 212, 255, 0.5); } .header-right { display: flex; - gap: 20px; + gap: 25px; align-items: center; .current-shift { - font-size: 14px; - color: #4a90d9; + font-size: 16px; + color: #a0c4e8; font-weight: 600; } .time { - font-size: 16px; - color: #666666; + font-size: 18px; + color: #00d4ff; font-family: 'Courier New', monospace; + font-weight: bold; + } + + .exit-fullscreen-btn { + padding: 8px 16px; + border: 1px solid rgba(255, 107, 107, 0.5); + border-radius: 6px; + background: rgba(255, 107, 107, 0.2); + color: #ff6b6b; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(255, 107, 107, 0.3); + border-color: #ff6b6b; + box-shadow: 0 0 15px rgba(255, 107, 107, 0.3); + } } } } .screen-body { - padding: 15px; + padding: 0; } .kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; - margin-bottom: 16px; + margin-bottom: 20px; .kpi-card { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.9) 0%, rgba(10, 20, 40, 0.95) 100%); + border: 1px solid rgba(0, 212, 255, 0.2); border-radius: 8px; - padding: 20px; + padding: 0; text-align: center; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .kpi-title { + .card-header { + background: linear-gradient(90deg, #00a8cc 0%, #00d4ff 50%, #00a8cc 100%); + padding: 10px 15px; font-size: 14px; - color: #666666; - margin-bottom: 10px; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; } .kpi-value { - font-size: 32px; + font-size: 40px; font-weight: bold; - margin-bottom: 8px; - - &.oee { color: #4a90d9; } - &.availability { color: #52c41a; } - &.performance { color: #5cd9e8; } - &.quality { color: #ff9800; } + color: #00d4ff; + margin: 15px 0; + text-shadow: 0 0 15px rgba(0, 212, 255, 0.6); } .kpi-trend { - font-size: 12px; - padding: 2px 8px; - border-radius: 10px; + font-size: 14px; + padding: 4px 12px; + border-radius: 15px; display: inline-block; + margin-bottom: 15px; + font-weight: 600; &.positive { - background: #f0f9eb; - color: #52c41a; + background: rgba(0, 255, 136, 0.15); + color: #00ff88; + border: 1px solid rgba(0, 255, 136, 0.3); } &.negative { - background: #fef0f0; - color: #f56c6c; + background: rgba(255, 107, 107, 0.15); + color: #ff6b6b; + border: 1px solid rgba(255, 107, 107, 0.3); } &.zero { - background: #fafafa; - color: #999999; + background: rgba(160, 196, 232, 0.15); + color: #a0c4e8; + border: 1px solid rgba(160, 196, 232, 0.3); } } } @@ -517,12 +615,14 @@ onUnmounted(() => { margin-bottom: 16px; .chart-box { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.85) 0%, rgba(10, 20, 40, 0.9) 100%); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 8px; - padding: 15px; + padding: 0; display: flex; flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); &.flex-1 { flex: 1; @@ -532,22 +632,60 @@ onUnmounted(() => { flex: 2; } - .box-title { + .box-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 12px 18px; font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); } .chart { height: 300px; width: 100%; + padding: 15px; } .event-table { flex: 1; + padding: 15px; + } + } +} + +:deep(.el-table) { + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.2); + + .el-table__header-wrapper { + .el-table__header { + th { + background: rgba(0, 212, 255, 0.15); + color: #00d4ff; + font-weight: bold; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); + } + } + } + + .el-table__body-wrapper { + .el-table__body { + tr { + td { + color: #a0c4e8; + border-bottom: 1px solid rgba(0, 212, 255, 0.1); + } + + &:nth-child(even) { + background: rgba(0, 212, 255, 0.05); + } + + &:hover { + background: rgba(0, 212, 255, 0.1); + } + } } } } diff --git a/src/modules/dashboardBig/views/order.vue b/src/modules/dashboardBig/views/order.vue index 7b8ed4a..3cbd4dd 100644 --- a/src/modules/dashboardBig/views/order.vue +++ b/src/modules/dashboardBig/views/order.vue @@ -3,46 +3,53 @@

订单数据大屏

- {{ currentTime }} +
+ {{ currentTime }} + +
-
-
-
{{ card.title }}
-
{{ card.value }}
-
{{ card.unit }}
+
+
+
{{ card.title }}
+
{{ card.value }}
+
{{ card.unit }}
-
-
-
订单趋势
+
+
+
订单趋势
-
-
订单状态分布
+
+
订单状态分布
-
-
订单列表
-
-
- 订单号 - 客户 - 金额 - 状态 - 时间 -
-
-
- {{ order.orderNo }} - {{ order.customer }} - {{ formatAmount(order.amount) }} - {{ order.status }} - {{ order.time }} +
+
+
订单列表
+
+
+ 订单号 + 客户 + 金额 + 状态 + 时间 +
+
+
+ {{ order.orderNo }} + {{ order.customer }} + {{ formatAmount(order.amount) }} + {{ order.status }} + {{ order.time }} +
@@ -57,17 +64,20 @@ import { ref, onMounted, onBeforeUnmount, onUnmounted, nextTick } from 'vue' import * as echarts from 'echarts' const currentTime = ref('') +const isFullscreen = ref(false) const trendChartRef = ref(null) const pieChartRef = ref(null) let trendChart = null let pieChart = null let timeInterval = null let resizeObserver = null +let fullscreenChangeHandler = null const cards = ref([ - { title: '今日订单', value: '45', unit: '单', color: '#4a90d9' }, - { title: '待处理订单', value: '12', unit: '单', color: '#ff9800' }, - { title: '已完成订单', value: '156', unit: '单', color: '#52c41a' } + { title: '今日订单', value: '45', unit: '单', color: '#00d4ff' }, + { title: '待处理订单', value: '12', unit: '单', color: '#ffd43b' }, + { title: '已完成订单', value: '156', unit: '单', color: '#00ff88' }, + { title: '订单总额', value: '568', unit: '万', color: '#7c63ff' } ]) const orderList = ref([ @@ -93,33 +103,38 @@ const initCharts = () => { if (trendChartRef.value) { trendChart = echarts.init(trendChartRef.value) trendChart.setOption({ - backgroundColor: '#ffffff', + backgroundColor: 'transparent', grid: { top: 20, right: 20, bottom: 30, left: 50 }, - tooltip: { trigger: 'axis' }, + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, xAxis: { type: 'category', data: ['1月', '2月', '3月', '4月', '5月', '6月'], - axisLine: { lineStyle: { color: '#ddd' } }, + axisLine: { lineStyle: { color: '#3a5a8a' } }, axisTick: { show: false }, - axisLabel: { color: '#666' } + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, axisTick: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, series: [{ type: 'bar', - data: [35, 42, 38, 45, 40, 48], - itemStyle: { - color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ - { offset: 0, color: '#4a90d9' }, - { offset: 1, color: '#5cd9e8' } - ]), - borderRadius: [4, 4, 0, 0] - } + data: [35, 42, 38, 45, 40, 48].map((value, index) => ({ + value, + itemStyle: { + color: ['#00d4ff', '#7c63ff', '#00ff88', '#ff9f43', '#ff6b6b', '#ffd43b'][index], + borderRadius: [4, 4, 0, 0] + } + })), + barWidth: '50%' }] }) } @@ -127,17 +142,22 @@ const initCharts = () => { if (pieChartRef.value) { pieChart = echarts.init(pieChartRef.value) pieChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item' }, - legend: { bottom: 10, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['45%', '75%'], center: ['50%', '45%'], data: [ - { value: 45, name: '生产中', itemStyle: { color: '#4a90d9' } }, - { value: 12, name: '待生产', itemStyle: { color: '#e6a23c' } }, - { value: 156, name: '已完成', itemStyle: { color: '#52c41a' } } + { value: 45, name: '生产中', itemStyle: { color: '#00d4ff' } }, + { value: 12, name: '待生产', itemStyle: { color: '#ffd43b' } }, + { value: 156, name: '已完成', itemStyle: { color: '#00ff88' } } ], label: { show: false } }] @@ -172,18 +192,42 @@ onMounted(() => { } } }) + + window.addEventListener('refresh-data', handleRefresh) + + fullscreenChangeHandler = () => { + isFullscreen.value = !!document.fullscreenElement + } + document.addEventListener('fullscreenchange', fullscreenChangeHandler) }) +const handleRefresh = () => { + initCharts() +} + +const exitFullscreen = () => { + if (document.fullscreenElement) { + document.exitFullscreen().catch(err => { + console.error('退出全屏失败:', err) + }) + } +} + onBeforeUnmount(() => { if (timeInterval) { clearInterval(timeInterval) timeInterval = null } window.removeEventListener('resize', handleResize) + window.removeEventListener('refresh-data', handleRefresh) if (resizeObserver) { resizeObserver.disconnect() resizeObserver = null } + if (fullscreenChangeHandler) { + document.removeEventListener('fullscreenchange', fullscreenChangeHandler) + fullscreenChangeHandler = null + } if (trendChart) { trendChart.dispose() trendChart = null @@ -203,18 +247,16 @@ onUnmounted(() => { .screen-wrapper { width: 100%; min-height: 100%; - background: #f5f5f5; + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 50%, #0a1428 100%); overflow-y: auto; overflow-x: hidden; } .screen-content { - background: #ffffff; - color: #333333; - border-radius: 8px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + background: transparent; + color: #ffffff; width: 100%; - padding-bottom: 20px; + padding: 20px; } .screen-header { @@ -222,170 +264,210 @@ onUnmounted(() => { justify-content: space-between; align-items: center; padding: 20px 30px; - border-bottom: 1px solid #eee; + background: linear-gradient(90deg, rgba(0, 212, 255, 0.1) 0%, rgba(12, 30, 60, 0.8) 100%); + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid rgba(0, 212, 255, 0.2); .title { - font-size: 24px; + font-size: 26px; font-weight: bold; - color: #333333; - letter-spacing: 2px; + color: #00d4ff; + letter-spacing: 3px; margin: 0; + text-shadow: 0 0 20px rgba(0, 212, 255, 0.5); + } + + .header-right { + display: flex; + align-items: center; + gap: 20px; } .time { - font-size: 16px; - color: #666666; + font-size: 18px; + color: #00d4ff; font-family: 'Courier New', monospace; + font-weight: bold; + } + + .exit-fullscreen-btn { + padding: 8px 16px; + border: 1px solid rgba(255, 107, 107, 0.5); + border-radius: 6px; + background: rgba(255, 107, 107, 0.2); + color: #ff6b6b; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(255, 107, 107, 0.3); + border-color: #ff6b6b; + box-shadow: 0 0 15px rgba(255, 107, 107, 0.3); + } } } .screen-body { - padding: 15px; + padding: 0; } -.card-grid { +.kpi-grid { display: grid; - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(4, 1fr); gap: 16px; - margin-bottom: 16px; + margin-bottom: 20px; - .data-card { - background: #fafafa; - border: 1px solid #e0e0e0; + .kpi-card { + background: linear-gradient(180deg, rgba(14, 40, 80, 0.9) 0%, rgba(10, 20, 40, 0.95) 100%); + border: 1px solid rgba(0, 212, 255, 0.2); border-radius: 8px; - padding: 20px; + padding: 0; text-align: center; - display: flex; - flex-direction: column; - justify-content: center; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .card-title { + .card-header { + background: linear-gradient(90deg, #00a8cc 0%, #00d4ff 50%, #00a8cc 100%); + padding: 10px 15px; font-size: 14px; - color: #666666; - margin-bottom: 10px; - } - - .card-value { - font-size: 32px; font-weight: bold; - margin-bottom: 5px; + color: #0a1428; + letter-spacing: 2px; } - .card-unit { - font-size: 12px; - color: #999999; + .kpi-value { + font-size: 36px; + font-weight: bold; + margin: 15px 0 5px; + text-shadow: 0 0 15px currentColor; + } + + .kpi-unit { + font-size: 14px; + color: #a0c4e8; + margin-bottom: 15px; } } } -.chart-area { - display: grid; - grid-template-columns: 1fr 1fr; +.chart-row { + display: flex; gap: 16px; margin-bottom: 16px; .chart-box { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.85) 0%, rgba(10, 20, 40, 0.9) 100%); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 8px; - padding: 15px; + padding: 0; display: flex; flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); - .box-title { + &.flex-1 { + flex: 1; + } + + &.flex-2 { + flex: 2; + } + + .box-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 12px 18px; font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 10px; - padding-left: 10px; - border-left: 3px solid #4a90d9; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); } .chart { height: 300px; width: 100%; - } - } -} - -.order-list-box { - background: #fafafa; - border: 1px solid #e0e0e0; - border-radius: 8px; - padding: 15px; - display: flex; - flex-direction: column; - - .box-title { - font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 10px; - padding-left: 10px; - border-left: 3px solid #4a90d9; - } - - .order-table { - display: flex; - flex-direction: column; - - .table-header { - display: grid; - grid-template-columns: 2fr 2fr 1.5fr 1fr 1fr; - gap: 15px; - padding: 10px 15px; - background: #e0e0e0; - border-radius: 4px; - font-size: 13px; - color: #666666; - font-weight: 500; + padding: 15px; } - .table-body { - .table-row { + .order-table { + flex: 1; + padding: 15px; + display: flex; + flex-direction: column; + + .table-header { display: grid; grid-template-columns: 2fr 2fr 1.5fr 1fr 1fr; gap: 15px; - padding: 10px 15px; - border-bottom: 1px solid #eee; + padding: 12px 15px; + background: rgba(0, 212, 255, 0.15); + border-radius: 6px; font-size: 13px; + color: #00d4ff; + font-weight: bold; + border: 1px solid rgba(0, 212, 255, 0.3); + } - .order-no { - color: #4a90d9; - font-family: 'Courier New', monospace; - } + .table-body { + .table-row { + display: grid; + grid-template-columns: 2fr 2fr 1.5fr 1fr 1fr; + gap: 15px; + padding: 12px 15px; + border-bottom: 1px solid rgba(0, 212, 255, 0.1); + font-size: 13px; - .amount { - color: #ff9800; - font-weight: 600; - } - - .status { - padding: 2px 8px; - border-radius: 4px; - font-size: 11px; - text-align: center; - display: inline-block; - width: fit-content; - - &.已完成 { - background: rgba(82, 196, 26, 0.2); - color: #52c41a; + &:nth-child(even) { + background: rgba(0, 212, 255, 0.05); } - &.生产中 { - background: rgba(74, 144, 217, 0.2); - color: #4a90d9; + &:hover { + background: rgba(0, 212, 255, 0.1); } - &.待生产 { - background: rgba(230, 162, 60, 0.2); - color: #e6a23c; + .order-no { + color: #00d4ff; + font-family: 'Courier New', monospace; + font-weight: 600; } - } - .time { - color: #999999; + .amount { + color: #ff9f43; + font-weight: bold; + } + + .status { + padding: 3px 10px; + border-radius: 4px; + font-size: 12px; + text-align: center; + display: inline-block; + width: fit-content; + + &.已完成 { + background: rgba(0, 255, 136, 0.15); + color: #00ff88; + border: 1px solid rgba(0, 255, 136, 0.3); + } + + &.生产中 { + background: rgba(0, 212, 255, 0.15); + color: #00d4ff; + border: 1px solid rgba(0, 212, 255, 0.3); + } + + &.待生产 { + background: rgba(255, 212, 59, 0.15); + color: #ffd43b; + border: 1px solid rgba(255, 212, 59, 0.3); + } + } + + .time { + color: #a0c4e8; + } } } } @@ -393,17 +475,17 @@ onUnmounted(() => { } @media screen and (max-width: 1200px) { - .card-grid { - grid-template-columns: repeat(3, 1fr); + .kpi-grid { + grid-template-columns: repeat(2, 1fr); } - .chart-area { - grid-template-columns: 1fr; + .chart-row { + flex-direction: column; } } @media screen and (max-width: 768px) { - .card-grid { + .kpi-grid { grid-template-columns: 1fr; } } diff --git a/src/modules/dashboardBig/views/output.vue b/src/modules/dashboardBig/views/output.vue index e323fcb..b6a13b0 100644 --- a/src/modules/dashboardBig/views/output.vue +++ b/src/modules/dashboardBig/views/output.vue @@ -3,39 +3,44 @@

产出监控大屏

- {{ currentTime }} +
+ {{ currentTime }} + +
+
今日产量
📦
-
今日产量
{{ outputData.todayCount }}
+
今日重量
⚖️
-
今日重量
{{ outputData.todayWeight.toFixed(1) }}
+
月累计
📊
-
月累计
{{ outputData.monthCount }}
+
年累计
🏭
-
年累计
{{ outputData.yearCount }}
@@ -44,7 +49,7 @@
-
产出明细
+
产出明细
@@ -77,22 +82,22 @@
-
质量分布
+
质量分布
-
产品类型分布
+
产品类型分布
-
库存状态分布
+
库存状态分布
-
重量分布
+
重量分布
@@ -107,11 +112,13 @@ import * as echarts from 'echarts' import { getProductionOutput, getDashboardOverview } from '@/api/acidOee' const currentTime = ref('') +const isFullscreen = ref(false) const qualityChartRef = ref(null) const productTypeChartRef = ref(null) const stockChartRef = ref(null) const weightChartRef = ref(null) let qualityChart = null +let fullscreenChangeHandler = null let productTypeChart = null let stockChart = null let weightChart = null @@ -207,18 +214,31 @@ const updateQualityChart = () => { const unqualified = outputList.value.filter(item => item.qualityStatus === '不合格').length qualityChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' }, - legend: { bottom: 0, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + formatter: '{b}: {c} ({d}%)', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['45%', '75%'], center: ['50%', '45%'], data: [ - { value: qualified || 150, name: '合格', itemStyle: { color: '#52c41a' } }, - { value: unqualified || 6, name: '不合格', itemStyle: { color: '#f56c6c' } } + { value: qualified || 150, name: '合格', itemStyle: { color: '#00ff88' } }, + { value: unqualified || 6, name: '不合格', itemStyle: { color: '#ff6b6b' } } ], - label: { show: false } + label: { show: false }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } }] }) } @@ -235,24 +255,37 @@ const updateProductTypeChart = () => { name, value, itemStyle: { - color: ['#4a90d9', '#5cd9e8', '#52c41a', '#ff9800', '#ff5722'][index % 5] + color: ['#00d4ff', '#7c63ff', '#00ff88', '#ffd43b', '#ff6b6b'][index % 5] } })) productTypeChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' }, - legend: { bottom: 0, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + formatter: '{b}: {c} ({d}%)', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['40%', '70%'], center: ['50%', '45%'], data: data.length > 0 ? data : [ - { value: 100, name: 'SPHC', itemStyle: { color: '#4a90d9' } }, - { value: 80, name: 'SPHD', itemStyle: { color: '#5cd9e8' } }, - { value: 60, name: 'SPHE', itemStyle: { color: '#52c41a' } } + { value: 100, name: 'SPHC', itemStyle: { color: '#00d4ff' } }, + { value: 80, name: 'SPHD', itemStyle: { color: '#7c63ff' } }, + { value: 60, name: 'SPHE', itemStyle: { color: '#00ff88' } } ], - label: { show: false } + label: { show: false }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } }] }) } @@ -269,24 +302,37 @@ const updateStockChart = () => { name, value, itemStyle: { - color: ['#52c41a', '#ff9800', '#f56c6c'][index % 3] + color: ['#00ff88', '#ffd43b', '#ff6b6b'][index % 3] } })) stockChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' }, - legend: { bottom: 0, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + formatter: '{b}: {c} ({d}%)', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['40%', '70%'], center: ['50%', '45%'], data: data.length > 0 ? data : [ - { value: 120, name: '在库', itemStyle: { color: '#52c41a' } }, - { value: 25, name: '已出库', itemStyle: { color: '#ff9800' } }, - { value: 11, name: '待处理', itemStyle: { color: '#f56c6c' } } + { value: 120, name: '在库', itemStyle: { color: '#00ff88' } }, + { value: 25, name: '已出库', itemStyle: { color: '#ffd43b' } }, + { value: 11, name: '待处理', itemStyle: { color: '#ff6b6b' } } ], - label: { show: false } + label: { show: false }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } }] }) } @@ -295,30 +341,35 @@ const updateWeightChart = () => { if (!weightChart) return weightChart.setOption({ - backgroundColor: '#ffffff', + backgroundColor: 'transparent', grid: { top: 20, right: 20, bottom: 30, left: 50 }, - tooltip: { trigger: 'axis' }, + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, xAxis: { type: 'category', data: ['<6t', '6-7t', '7-8t', '8-9t', '>9t'], - axisLine: { lineStyle: { color: '#ddd' } }, + axisLine: { lineStyle: { color: '#3a5a8a' } }, axisTick: { show: false }, - axisLabel: { color: '#666' } + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, series: [{ type: 'bar', data: [ - { value: 20, itemStyle: { color: '#4a90d9' } }, - { value: 85, itemStyle: { color: '#5cd9e8' } }, - { value: 95, itemStyle: { color: '#52c41a' } }, - { value: 45, itemStyle: { color: '#ff9800' } }, - { value: 10, itemStyle: { color: '#ff5722' } } + { value: 20, itemStyle: { color: '#00d4ff' } }, + { value: 85, itemStyle: { color: '#7c63ff' } }, + { value: 95, itemStyle: { color: '#00ff88' } }, + { value: 45, itemStyle: { color: '#ffd43b' } }, + { value: 10, itemStyle: { color: '#ff6b6b' } } ], barWidth: '50%' }] @@ -367,8 +418,27 @@ onMounted(() => { dataInterval = setInterval(loadData, 30000) }) + + window.addEventListener('refresh-data', handleRefresh) + + fullscreenChangeHandler = () => { + isFullscreen.value = !!document.fullscreenElement + } + document.addEventListener('fullscreenchange', fullscreenChangeHandler) }) +const handleRefresh = () => { + loadData() +} + +const exitFullscreen = () => { + if (document.fullscreenElement) { + document.exitFullscreen().catch(err => { + console.error('退出全屏失败:', err) + }) + } +} + onBeforeUnmount(() => { if (timeInterval) { clearInterval(timeInterval) @@ -379,10 +449,15 @@ onBeforeUnmount(() => { dataInterval = null } window.removeEventListener('resize', handleResize) + window.removeEventListener('refresh-data', handleRefresh) if (resizeObserver) { resizeObserver.disconnect() resizeObserver = null } + if (fullscreenChangeHandler) { + document.removeEventListener('fullscreenchange', fullscreenChangeHandler) + fullscreenChangeHandler = null + } if (qualityChart) { qualityChart.dispose() qualityChart = null @@ -410,18 +485,16 @@ onUnmounted(() => { .screen-wrapper { width: 100%; min-height: 100%; - background: #f5f5f5; + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 50%, #0a1428 100%); overflow-y: auto; overflow-x: hidden; } .screen-content { - background: #ffffff; - color: #333333; - border-radius: 8px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + background: transparent; + color: #ffffff; width: 100%; - padding-bottom: 20px; + padding: 20px; } .screen-header { @@ -429,65 +502,102 @@ onUnmounted(() => { justify-content: space-between; align-items: center; padding: 20px 30px; - border-bottom: 1px solid #eee; + background: linear-gradient(90deg, rgba(0, 212, 255, 0.1) 0%, rgba(12, 30, 60, 0.8) 100%); + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid rgba(0, 212, 255, 0.2); .title { - font-size: 24px; + font-size: 26px; font-weight: bold; - color: #333333; - letter-spacing: 2px; + color: #00d4ff; + letter-spacing: 3px; margin: 0; + text-shadow: 0 0 20px rgba(0, 212, 255, 0.5); + } + + .header-right { + display: flex; + align-items: center; + gap: 20px; } .time { - font-size: 16px; - color: #666666; + font-size: 18px; + color: #00d4ff; font-family: 'Courier New', monospace; + font-weight: bold; + } + + .exit-fullscreen-btn { + padding: 8px 16px; + border: 1px solid rgba(255, 107, 107, 0.5); + border-radius: 6px; + background: rgba(255, 107, 107, 0.2); + color: #ff6b6b; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(255, 107, 107, 0.3); + border-color: #ff6b6b; + box-shadow: 0 0 15px rgba(255, 107, 107, 0.3); + } } } .screen-body { - padding: 15px; + padding: 0; } .kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; - margin-bottom: 16px; + margin-bottom: 20px; .kpi-card { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.9) 0%, rgba(10, 20, 40, 0.95) 100%); + border: 1px solid rgba(0, 212, 255, 0.2); border-radius: 8px; - padding: 20px; + padding: 0; display: flex; + flex-direction: column; align-items: center; - gap: 16px; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + + .card-header { + background: linear-gradient(90deg, #00a8cc 0%, #00d4ff 50%, #00a8cc 100%); + padding: 10px 15px; + font-size: 14px; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + width: 100%; + text-align: center; + } .kpi-icon { font-size: 36px; + margin-top: 15px; } .kpi-info { - flex: 1; - - .kpi-title { - font-size: 14px; - color: #666666; - margin-bottom: 8px; - } + text-align: center; + margin: 10px 0 15px; .kpi-value { - font-size: 28px; + font-size: 36px; font-weight: bold; - color: #4a90d9; - margin-bottom: 4px; + color: #00d4ff; + text-shadow: 0 0 15px rgba(0, 212, 255, 0.6); } .kpi-unit { - font-size: 12px; - color: #999999; + font-size: 14px; + color: #a0c4e8; } } } @@ -499,12 +609,14 @@ onUnmounted(() => { margin-bottom: 16px; .chart-box { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.85) 0%, rgba(10, 20, 40, 0.9) 100%); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 8px; - padding: 15px; + padding: 0; display: flex; flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); &.flex-1 { flex: 1; @@ -514,26 +626,88 @@ onUnmounted(() => { flex: 2; } - .box-title { + .box-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 12px 18px; font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); } .chart { height: 280px; width: 100%; + padding: 15px; } .table-container { flex: 1; + padding: 15px; } } } +:deep(.el-table) { + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.2); + + .el-table__header-wrapper { + .el-table__header { + th { + background: rgba(0, 212, 255, 0.15); + color: #00d4ff; + font-weight: bold; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); + } + } + } + + .el-table__body-wrapper { + .el-table__body { + tr { + td { + color: #a0c4e8; + border-bottom: 1px solid rgba(0, 212, 255, 0.1); + } + + &:nth-child(even) { + background: rgba(0, 212, 255, 0.05); + } + + &:hover { + background: rgba(0, 212, 255, 0.1); + } + } + } + } +} + +:deep(.el-tag) { + background: rgba(0, 212, 255, 0.15); + border-color: rgba(0, 212, 255, 0.3); + color: #00d4ff; + + &.el-tag--success { + background: rgba(0, 255, 136, 0.15); + border-color: rgba(0, 255, 136, 0.3); + color: #00ff88; + } + + &.el-tag--danger { + background: rgba(255, 107, 107, 0.15); + border-color: rgba(255, 107, 107, 0.3); + color: #ff6b6b; + } + + &.el-tag--warning { + background: rgba(255, 212, 59, 0.15); + border-color: rgba(255, 212, 59, 0.3); + color: #ffd43b; + } +} + @media screen and (max-width: 1200px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); diff --git a/src/modules/dashboardBig/views/stopAnalysis.vue b/src/modules/dashboardBig/views/stopAnalysis.vue index 0fdd7be..1c42b18 100644 --- a/src/modules/dashboardBig/views/stopAnalysis.vue +++ b/src/modules/dashboardBig/views/stopAnalysis.vue @@ -3,63 +3,60 @@

停机分析大屏

- {{ currentTime }} +
+ {{ currentTime }} + +
+
今日停机时长
⏱️
-
-
今日停机时长
-
{{ stopData.todayDuration }}
-
分钟
-
+
{{ stopData.todayDuration }}
+
分钟
+
今日停机次数
🔴
-
-
今日停机次数
-
{{ stopData.todayCount }}
-
-
+
{{ stopData.todayCount }}
+
+
运行率
-
-
运行率
-
{{ stopData.runningRate.toFixed(1) }}
-
%
-
+
{{ stopData.runningRate.toFixed(1) }}
+
%
+
平均停机时长
📊
-
-
平均停机时长
-
{{ stopData.avgDuration }}
-
分钟/次
-
+
{{ stopData.avgDuration }}
+
分钟/次
-
停机类型分布
+
停机类型分布
-
班组停机分布
+
班组停机分布
-
停机时长TOP10
+
停机时长TOP10
-
停机事件明细
+
停机事件明细
@@ -90,6 +87,7 @@ import * as echarts from 'echarts' import { getProductionStop } from '@/api/acidOee' const currentTime = ref('') +const isFullscreen = ref(false) const typeChartRef = ref(null) const teamChartRef = ref(null) const top10ChartRef = ref(null) @@ -99,6 +97,7 @@ let top10Chart = null let timeInterval = null let dataInterval = null let resizeObserver = null +let fullscreenChangeHandler = null const stopData = ref({ todayDuration: 0, @@ -201,9 +200,15 @@ const updateTypeChart = () => { if (!typeChart) return typeChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'item', formatter: '{b}: {c}分钟 ({d}%)' }, - legend: { bottom: 0, textStyle: { color: '#666' } }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'item', + formatter: '{b}: {c}分钟 ({d}%)', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, + legend: { bottom: 0, textStyle: { color: '#a0c4e8' } }, series: [{ type: 'pie', radius: ['40%', '70%'], @@ -211,16 +216,23 @@ const updateTypeChart = () => { data: typeDistribution.value.length > 0 ? typeDistribution.value.map((item, index) => ({ ...item, itemStyle: { - color: ['#f56c6c', '#ff9800', '#5cd9e8', '#52c41a', '#4a90d9'][index % 5] + color: ['#ff6b6b', '#ffd43b', '#74c0fc', '#00ff88', '#00d4ff'][index % 5] } })) : [ - { name: '设备故障', value: 120, itemStyle: { color: '#f56c6c' } }, - { name: '换模换线', value: 85, itemStyle: { color: '#ff9800' } }, - { name: '质量异常', value: 55, itemStyle: { color: '#5cd9e8' } }, - { name: '物料等待', value: 40, itemStyle: { color: '#52c41a' } }, - { name: '计划停机', value: 30, itemStyle: { color: '#4a90d9' } } + { name: '设备故障', value: 120, itemStyle: { color: '#ff6b6b' } }, + { name: '换模换线', value: 85, itemStyle: { color: '#ffd43b' } }, + { name: '质量异常', value: 55, itemStyle: { color: '#74c0fc' } }, + { name: '物料等待', value: 40, itemStyle: { color: '#00ff88' } }, + { name: '计划停机', value: 30, itemStyle: { color: '#00d4ff' } } ], - label: { show: false } + label: { show: false }, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } }] }) } @@ -229,33 +241,38 @@ const updateTeamChart = () => { if (!teamChart) return teamChart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'axis' }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, grid: { top: 20, right: 20, bottom: 30, left: 50 }, xAxis: { type: 'category', data: teamDistribution.value.length > 0 ? teamDistribution.value.map(item => item.name) : ['甲班', '乙班', '丙班', '丁班', '戊班'], - axisLine: { lineStyle: { color: '#ddd' } }, + axisLine: { lineStyle: { color: '#3a5a8a' } }, axisTick: { show: false }, - axisLabel: { color: '#666' } + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'value', axisLine: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, series: [{ type: 'bar', data: teamDistribution.value.length > 0 ? teamDistribution.value.map((item, index) => ({ value: item.value, itemStyle: { - color: ['#4a90d9', '#5cd9e8', '#52c41a', '#ff9800', '#ff5722'][index % 5] + color: ['#00d4ff', '#7c63ff', '#00ff88', '#ffd43b', '#ff6b6b'][index % 5] } })) : [95, 85, 75, 65, 50].map((value, index) => ({ value, itemStyle: { - color: ['#4a90d9', '#5cd9e8', '#52c41a', '#ff9800', '#ff5722'][index] + color: ['#00d4ff', '#7c63ff', '#00ff88', '#ffd43b', '#ff6b6b'][index] } })), barWidth: '50%' @@ -271,40 +288,46 @@ const updateTop10Chart = () => { .slice(0, 10) top10Chart.setOption({ - backgroundColor: '#ffffff', - tooltip: { trigger: 'axis' }, + backgroundColor: 'transparent', + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(10, 20, 40, 0.9)', + borderColor: '#1e3a5f', + textStyle: { color: '#fff' } + }, grid: { top: 20, right: 80, bottom: 30, left: 50 }, xAxis: { type: 'value', axisLine: { show: false }, - splitLine: { lineStyle: { color: '#eee' } }, - axisLabel: { color: '#666' } + splitLine: { lineStyle: { color: '#1e3a5f', type: 'dashed' } }, + axisLabel: { color: '#a0c4e8' } }, yAxis: { type: 'category', data: top10Data.length > 0 ? top10Data.map(item => item.stopType) : ['设备故障', '换模换线', '质量异常'], - axisLine: { lineStyle: { color: '#ddd' } }, + axisLine: { lineStyle: { color: '#3a5a8a' } }, axisTick: { show: false }, - axisLabel: { color: '#666' } + axisLabel: { color: '#a0c4e8' } }, series: [{ type: 'bar', data: top10Data.length > 0 ? top10Data.map((item, index) => ({ value: item.duration, itemStyle: { - color: ['#f56c6c', '#ff9800', '#5cd9e8', '#52c41a', '#4a90d9', '#9c27b0', '#673ab7', '#00bcd4', '#ff5722', '#795548'][index % 10] + color: ['#ff6b6b', '#ffd43b', '#74c0fc', '#00ff88', '#00d4ff', '#7c63ff', '#b197fc', '#ff8fab', '#ffa94d', '#69db7c'][index % 10] } })) : [120, 85, 55].map((value, index) => ({ value, itemStyle: { - color: ['#f56c6c', '#ff9800', '#5cd9e8'][index] + color: ['#ff6b6b', '#ffd43b', '#74c0fc'][index] } })), barWidth: '50%', label: { show: true, position: 'right', - formatter: '{c}分钟' + formatter: '{c}分钟', + color: '#a0c4e8' } }] }) @@ -348,8 +371,27 @@ onMounted(() => { dataInterval = setInterval(loadData, 30000) }) + + window.addEventListener('refresh-data', handleRefresh) + + fullscreenChangeHandler = () => { + isFullscreen.value = !!document.fullscreenElement + } + document.addEventListener('fullscreenchange', fullscreenChangeHandler) }) +const handleRefresh = () => { + loadData() +} + +const exitFullscreen = () => { + if (document.fullscreenElement) { + document.exitFullscreen().catch(err => { + console.error('退出全屏失败:', err) + }) + } +} + onBeforeUnmount(() => { if (timeInterval) { clearInterval(timeInterval) @@ -360,10 +402,15 @@ onBeforeUnmount(() => { dataInterval = null } window.removeEventListener('resize', handleResize) + window.removeEventListener('refresh-data', handleRefresh) if (resizeObserver) { resizeObserver.disconnect() resizeObserver = null } + if (fullscreenChangeHandler) { + document.removeEventListener('fullscreenchange', fullscreenChangeHandler) + fullscreenChangeHandler = null + } if (typeChart) { typeChart.dispose() typeChart = null @@ -387,18 +434,16 @@ onUnmounted(() => { .screen-wrapper { width: 100%; min-height: 100%; - background: #f5f5f5; + background: linear-gradient(180deg, #0a1428 0%, #0d1b34 50%, #0a1428 100%); overflow-y: auto; overflow-x: hidden; } .screen-content { - background: #ffffff; - color: #333333; - border-radius: 8px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + background: transparent; + color: #ffffff; width: 100%; - padding-bottom: 20px; + padding: 20px; } .screen-header { @@ -406,87 +451,121 @@ onUnmounted(() => { justify-content: space-between; align-items: center; padding: 20px 30px; - border-bottom: 1px solid #eee; + background: linear-gradient(90deg, rgba(0, 212, 255, 0.1) 0%, rgba(12, 30, 60, 0.8) 100%); + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid rgba(0, 212, 255, 0.2); .title { - font-size: 24px; + font-size: 26px; font-weight: bold; - color: #333333; - letter-spacing: 2px; + color: #00d4ff; + letter-spacing: 3px; margin: 0; + text-shadow: 0 0 20px rgba(0, 212, 255, 0.5); + } + + .header-right { + display: flex; + align-items: center; + gap: 20px; } .time { - font-size: 16px; - color: #666666; + font-size: 18px; + color: #00d4ff; font-family: 'Courier New', monospace; + font-weight: bold; + } + + .exit-fullscreen-btn { + padding: 8px 16px; + border: 1px solid rgba(255, 107, 107, 0.5); + border-radius: 6px; + background: rgba(255, 107, 107, 0.2); + color: #ff6b6b; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(255, 107, 107, 0.3); + border-color: #ff6b6b; + box-shadow: 0 0 15px rgba(255, 107, 107, 0.3); + } } } .screen-body { - padding: 15px; + padding: 0; } .kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; - margin-bottom: 16px; + margin-bottom: 20px; .kpi-card { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.9) 0%, rgba(10, 20, 40, 0.95) 100%); + border: 1px solid rgba(0, 212, 255, 0.2); border-radius: 8px; - padding: 20px; + padding: 0; display: flex; + flex-direction: column; align-items: center; - gap: 16px; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); border-left: 4px solid; &.warning { - border-left-color: #ff9800; - background: #fffbf0; + border-left-color: #ffd43b; } &.danger { - border-left-color: #f56c6c; - background: #fff5f5; + border-left-color: #ff6b6b; } &.success { - border-left-color: #52c41a; - background: #f0f9eb; + border-left-color: #00ff88; } &.info { - border-left-color: #4a90d9; - background: #f0f7ff; + border-left-color: #00d4ff; + } + + .card-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 10px 15px; + font-size: 14px; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + width: 100%; + text-align: center; } .kpi-icon { - font-size: 36px; + font-size: 32px; + margin-top: 15px; } - .kpi-info { - flex: 1; + .kpi-value { + font-size: 36px; + font-weight: bold; + margin: 10px 0; + text-shadow: 0 0 15px rgba(0, 212, 255, 0.6); - .kpi-title { - font-size: 14px; - color: #666666; - margin-bottom: 8px; - } + .warning & { color: #ffd43b; } + .danger & { color: #ff6b6b; } + .success & { color: #00ff88; } + .info & { color: #00d4ff; } + } - .kpi-value { - font-size: 28px; - font-weight: bold; - color: #333333; - margin-bottom: 4px; - } - - .kpi-unit { - font-size: 12px; - color: #999999; - } + .kpi-unit { + font-size: 14px; + color: #a0c4e8; + margin-bottom: 15px; } } } @@ -497,12 +576,14 @@ onUnmounted(() => { margin-bottom: 16px; .chart-box { - background: #fafafa; - border: 1px solid #e0e0e0; + background: linear-gradient(180deg, rgba(14, 40, 80, 0.85) 0%, rgba(10, 20, 40, 0.9) 100%); + border: 1px solid rgba(0, 212, 255, 0.15); border-radius: 8px; - padding: 15px; + padding: 0; display: flex; flex-direction: column; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); &.flex-1 { flex: 1; @@ -512,26 +593,88 @@ onUnmounted(() => { flex: 2; } - .box-title { + .box-header { + background: linear-gradient(90deg, rgba(0, 168, 204, 0.8) 0%, rgba(0, 212, 255, 0.6) 100%); + padding: 12px 18px; font-size: 14px; - font-weight: 600; - color: #333333; - margin-bottom: 12px; - padding-left: 10px; - border-left: 3px solid #4a90d9; + font-weight: bold; + color: #0a1428; + letter-spacing: 2px; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); } .chart { height: 280px; width: 100%; + padding: 15px; } .table-container { flex: 1; + padding: 15px; } } } +:deep(.el-table) { + background: rgba(10, 20, 40, 0.8); + border: 1px solid rgba(0, 212, 255, 0.2); + + .el-table__header-wrapper { + .el-table__header { + th { + background: rgba(0, 212, 255, 0.15); + color: #00d4ff; + font-weight: bold; + border-bottom: 1px solid rgba(0, 212, 255, 0.3); + } + } + } + + .el-table__body-wrapper { + .el-table__body { + tr { + td { + color: #a0c4e8; + border-bottom: 1px solid rgba(0, 212, 255, 0.1); + } + + &:nth-child(even) { + background: rgba(0, 212, 255, 0.05); + } + + &:hover { + background: rgba(0, 212, 255, 0.1); + } + } + } + } +} + +:deep(.el-tag) { + background: rgba(0, 212, 255, 0.15); + border-color: rgba(0, 212, 255, 0.3); + color: #00d4ff; + + &.el-tag--success { + background: rgba(0, 255, 136, 0.15); + border-color: rgba(0, 255, 136, 0.3); + color: #00ff88; + } + + &.el-tag--danger { + background: rgba(255, 107, 107, 0.15); + border-color: rgba(255, 107, 107, 0.3); + color: #ff6b6b; + } + + &.el-tag--warning { + background: rgba(255, 212, 59, 0.15); + border-color: rgba(255, 212, 59, 0.3); + color: #ffd43b; + } +} + @media screen and (max-width: 1200px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); diff --git a/src/router/index.js b/src/router/index.js index 8381e01..b3255c8 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -4,15 +4,8 @@ export const constantRoutes = [ { path: '/', component: () => import('@/layout/index.vue'), - redirect: '/index', - children: [ - { - path: 'index', - name: 'Dashboard', - component: () => import('@/views/home/index.vue'), - meta: { title: '工作台', icon: 'dashboard' } - } - ] + redirect: '/dashboard/demo', + children: [] }, { path: '/dashboard', @@ -43,6 +36,24 @@ export const constantRoutes = [ component: () => import('@/modules/dashboardBig/views/energy.vue'), meta: { title: '能源大屏', icon: 'energy' } }, + { + path: 'oee', + name: 'Oee', + component: () => import('@/modules/dashboardBig/views/oee.vue'), + meta: { title: 'OEE综合大屏', icon: 'oee' } + }, + { + path: 'output', + name: 'Output', + component: () => import('@/modules/dashboardBig/views/output.vue'), + meta: { title: '产出监控大屏', icon: 'output' } + }, + { + path: 'stop-analysis', + name: 'StopAnalysis', + component: () => import('@/modules/dashboardBig/views/stopAnalysis.vue'), + meta: { title: '停机分析大屏', icon: 'stop' } + }, { path: 'acid-rolling', name: 'AcidRolling', @@ -50,87 +61,6 @@ export const constantRoutes = [ meta: { title: '酸轧数据大屏', icon: 'example' } } ] - }, - { - path: '/screen-manage', - component: () => import('@/layout/index.vue'), - meta: { title: '大屏管理', icon: 'pie-chart' }, - children: [ - { - path: '', - name: 'ScreenList', - component: () => import('@/views/screens/list.vue'), - meta: { title: '大屏列表', icon: 'list' } - }, - { - path: 'create', - name: 'ScreenCreate', - component: () => import('@/views/screens/create.vue'), - meta: { title: '新建大屏', icon: 'plus' } - }, - { - path: 'edit/:id', - name: 'ScreenEdit', - component: () => import('@/views/screens/edit.vue'), - meta: { title: '编辑大屏', icon: 'edit', hidden: true } - } - ] - }, - { - path: '/reports', - component: () => import('@/layout/index.vue'), - meta: { title: '报表管理', icon: 'document' }, - children: [ - { - path: '', - name: 'ReportList', - component: () => import('@/views/reports/index.vue'), - meta: { title: '报表列表', icon: 'list' } - }, - { - path: 'acid-rolling', - name: 'AcidRollingReport', - component: () => import('@/views/reports/acid-rolling/index.vue'), - meta: { title: '酸轧产出报表', icon: 'output' } - }, - { - path: 'acid-stop', - name: 'AcidStopReport', - component: () => import('@/views/reports/acid-stop/index.vue'), - meta: { title: '酸轧停机报表', icon: 'stop' } - } - ] - }, - { - path: '/system', - component: () => import('@/layout/index.vue'), - meta: { title: '系统管理', icon: 'system' }, - children: [ - { - path: 'menu', - name: 'MenuManagement', - component: () => import('@/views/system/menu/index.vue'), - meta: { title: '菜单管理', icon: 'menu' } - }, - { - path: 'config', - name: 'SystemConfig', - component: () => import('@/views/system/index.vue'), - meta: { title: '系统配置', icon: 'config' } - } - ] - }, - { - path: '/data-source', - component: () => import('@/layout/index.vue'), - children: [ - { - path: '', - name: 'DataSource', - component: () => import('@/views/data-source/index.vue'), - meta: { title: '数据源配置', icon: 'database' } - } - ] } ] @@ -149,4 +79,4 @@ export function resetRouter() { router.matcher = newRouter.matcher } -export default router +export default router \ No newline at end of file diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js index 8c40370..bb720ac 100644 --- a/src/store/modules/permission.js +++ b/src/store/modules/permission.js @@ -16,7 +16,6 @@ const mutations = { const actions = { generateRoutes({ commit, state }) { return new Promise(resolve => { - // 避免重复加载 if (state.addRoutes.length > 0) { resolve(state.addRoutes) return @@ -34,11 +33,10 @@ const actions = { } } -// 修复:Layout正常加载,空组件赋值首页 function filterAsyncRoutes(routes) { return routes.filter(route => { if (!route.component || route.component === '') { - route.component = () => import('@/views/home/index.vue') + route.component = () => import('@/modules/dashboardBig/views/index.vue') } else if (route.component !== 'Layout') { route.component = loadComponent(route.component) } @@ -50,11 +48,9 @@ function filterAsyncRoutes(routes) { } function loadComponent(componentPath) { - // 去除开头/和.vue后缀 const path = componentPath.replace(/^\//, '').replace(/\.vue$/, '') const componentMap = { 'Layout': () => import('@/layout/index.vue'), - 'home/index': () => import('@/views/home/index.vue'), 'modules/dashboardBig/views/index': () => import('@/modules/dashboardBig/views/index.vue'), 'modules/dashboardBig/views/order': () => import('@/modules/dashboardBig/views/order.vue'), 'modules/dashboardBig/views/cost': () => import('@/modules/dashboardBig/views/cost.vue'), @@ -62,20 +58,9 @@ function loadComponent(componentPath) { 'modules/dashboardBig/views/oee': () => import('@/modules/dashboardBig/views/oee.vue'), 'modules/dashboardBig/views/output': () => import('@/modules/dashboardBig/views/output.vue'), 'modules/dashboardBig/views/stopAnalysis': () => import('@/modules/dashboardBig/views/stopAnalysis.vue'), - 'screens/list': () => import('@/views/screens/list.vue'), - 'screens/create': () => import('@/views/screens/create.vue'), - 'screens/edit': () => import('@/views/screens/edit.vue'), - 'screens/acid-rolling/index': () => import('@/views/screens/acid-rolling/index.vue'), - 'reports/index': () => import('@/views/reports/index.vue'), - 'reports/acid-rolling/index': () => import('@/views/reports/acid-rolling/index.vue'), - 'reports/acid-stop/index': () => import('@/views/reports/acid-stop/index.vue'), - 'system/user/index': () => import('@/views/system/user/index.vue'), - 'system/role/index': () => import('@/views/system/role/index.vue'), - 'system/menu/index': () => import('@/views/system/menu/index.vue'), - 'system/config/index': () => import('@/views/system/config/index.vue'), - 'data-source/index': () => import('@/views/data-source/index.vue') + 'screens/acid-rolling/index': () => import('@/views/screens/acid-rolling/index.vue') } - return componentMap[path] || (() => import('@/views/home/index.vue')) + return componentMap[path] || (() => import('@/modules/dashboardBig/views/index.vue')) } export default { @@ -83,4 +68,4 @@ export default { state, mutations, actions -} \ No newline at end of file +} diff --git a/src/views/dashboard/cost/index.vue b/src/views/dashboard/cost/index.vue deleted file mode 100644 index c3f577e..0000000 --- a/src/views/dashboard/cost/index.vue +++ /dev/null @@ -1,602 +0,0 @@ - - - - - diff --git a/src/views/dashboard/demo/index.vue b/src/views/dashboard/demo/index.vue deleted file mode 100644 index 3537e6b..0000000 --- a/src/views/dashboard/demo/index.vue +++ /dev/null @@ -1,458 +0,0 @@ - - - - - diff --git a/src/views/dashboard/energy/index.vue b/src/views/dashboard/energy/index.vue deleted file mode 100644 index 1f98070..0000000 --- a/src/views/dashboard/energy/index.vue +++ /dev/null @@ -1,644 +0,0 @@ - - - - - diff --git a/src/views/dashboard/order/index.vue b/src/views/dashboard/order/index.vue deleted file mode 100644 index f5575c5..0000000 --- a/src/views/dashboard/order/index.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/views/data-source/index.vue b/src/views/data-source/index.vue deleted file mode 100644 index fab3c97..0000000 --- a/src/views/data-source/index.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - - - diff --git a/src/views/home/index.vue b/src/views/home/index.vue deleted file mode 100644 index 27083a0..0000000 --- a/src/views/home/index.vue +++ /dev/null @@ -1,278 +0,0 @@ - - - - - diff --git a/src/views/reports/acid-rolling/index.vue b/src/views/reports/acid-rolling/index.vue deleted file mode 100644 index a23441a..0000000 --- a/src/views/reports/acid-rolling/index.vue +++ /dev/null @@ -1,332 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/views/reports/acid-stop/index.vue b/src/views/reports/acid-stop/index.vue deleted file mode 100644 index f44464b..0000000 --- a/src/views/reports/acid-stop/index.vue +++ /dev/null @@ -1,308 +0,0 @@ - - - - - diff --git a/src/views/reports/index.vue b/src/views/reports/index.vue deleted file mode 100644 index ce0f726..0000000 --- a/src/views/reports/index.vue +++ /dev/null @@ -1,107 +0,0 @@ - - - - - diff --git a/src/views/screens/acid-rolling/index.vue b/src/views/screens/acid-rolling/index.vue index 11eac8e..206dc56 100644 --- a/src/views/screens/acid-rolling/index.vue +++ b/src/views/screens/acid-rolling/index.vue @@ -3,29 +3,34 @@

酸轧数据大屏

- {{ currentTime }} +
+ {{ currentTime }} + +
-
-
-
{{ card.title }}
-
{{ card.value }}
-
{{ card.unit }}
+
+
+
{{ card.title }}
+
{{ card.value }}
+
{{ card.unit }}
-
-
-
OEE趋势分析
+
+
+
OEE趋势分析
-
-
7大损失分布
+
+
7大损失分布
-
-
班组产量排名
+
+
班组产量排名
{{ index + 1 }} @@ -36,9 +41,9 @@
-
-
-
实时告警
+
+
+
实时告警
{{ alarm.icon }} @@ -56,11 +61,11 @@ \ No newline at end of file + diff --git a/src/views/screens/create.vue b/src/views/screens/create.vue deleted file mode 100644 index 3e9e98c..0000000 --- a/src/views/screens/create.vue +++ /dev/null @@ -1,170 +0,0 @@ - - - - - diff --git a/src/views/screens/edit.vue b/src/views/screens/edit.vue deleted file mode 100644 index f9c190d..0000000 --- a/src/views/screens/edit.vue +++ /dev/null @@ -1,178 +0,0 @@ - - - - - diff --git a/src/views/screens/index.vue b/src/views/screens/index.vue deleted file mode 100644 index 046e4e1..0000000 --- a/src/views/screens/index.vue +++ /dev/null @@ -1,201 +0,0 @@ - - - - - diff --git a/src/views/screens/list.vue b/src/views/screens/list.vue deleted file mode 100644 index e13b3dc..0000000 --- a/src/views/screens/list.vue +++ /dev/null @@ -1,198 +0,0 @@ - - - - - diff --git a/src/views/system/config/index.vue b/src/views/system/config/index.vue deleted file mode 100644 index b82d5fa..0000000 --- a/src/views/system/config/index.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - diff --git a/src/views/system/index.vue b/src/views/system/index.vue deleted file mode 100644 index 84544b1..0000000 --- a/src/views/system/index.vue +++ /dev/null @@ -1,180 +0,0 @@ - - - - - diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue deleted file mode 100644 index 27f146f..0000000 --- a/src/views/system/menu/index.vue +++ /dev/null @@ -1,126 +0,0 @@ - - - - - diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue deleted file mode 100644 index 1cdc7f0..0000000 --- a/src/views/system/role/index.vue +++ /dev/null @@ -1,109 +0,0 @@ - - - - - diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue deleted file mode 100644 index 2aea02e..0000000 --- a/src/views/system/user/index.vue +++ /dev/null @@ -1,121 +0,0 @@ - - - - -