Browse Source

数据大屏

qaz 1 week ago
parent
commit
7e120ab4e9
4 changed files with 756 additions and 9 deletions
  1. BIN
      src/assets/img/bg.png
  2. BIN
      src/assets/img/head_bg.png
  3. 9 2
      src/layout/component/main.vue
  4. 747 7
      src/views/system/home/index.vue

BIN
src/assets/img/bg.png


BIN
src/assets/img/head_bg.png


+ 9 - 2
src/layout/component/main.vue

@@ -1,10 +1,11 @@
 <template>
 	<el-main class="layout-main"
-		:style="isFixedHeader ? `height: calc(100% - ${setMainHeight})` : `minHeight: calc(100% - ${setMainHeight})`">
+		:style="isFixedHeader ? `height: calc(100% - ${setMainHeight})` : `minHeight: calc(100% - ${setMainHeight})`"
+		:class="{ 'home-page': route.path === '/home' }">
 		<el-scrollbar ref="layoutMainScrollbarRef" class="layout-main-scroll layout-backtop-header-fixed"
 			wrap-class="layout-main-scroll" view-class="layout-main-scroll">
 			<LayoutParentView />
-      <LayoutFooter v-if="isFooter" />
+     <!--  <LayoutFooter v-if="isFooter" /> -->
 		</el-scrollbar>
 		<el-backtop :target="setBacktopClass" />
 	</el-main>
@@ -60,3 +61,9 @@ defineExpose({
 	layoutMainScrollbarRef,
 });
 </script>
+<style scoped>
+
+:deep(.layout-main:not(.home-page)) {
+	padding: 0 !important;
+}
+</style>

+ 747 - 7
src/views/system/home/index.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="home-container">
-		<el-row :gutter="15" class="home-card-one">
-			<!-- 左侧主要内容区域 -->
+		<!-- <el-row :gutter="15" class="home-card-one">
+			
 			<el-col :span="18">
 				<el-row :gutter="12" class="home-card-one mb15">
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
@@ -39,11 +39,9 @@
 				</el-row>
 			</el-col>
 
-			<!-- 右侧辅助区域 -->
 			<el-col :span="6">
 				<div class="home-right" style="margin-top: 75px;">
 					<div class="home-card-item">
-						<!-- <div class="home-card-item-title">快捷操作</div> -->
 						<div class="home-card-item-content">
 							<el-select placeholder="Select" style="margin-right: 5px;">
 								<el-option label="Option 1" value="1" />
@@ -86,7 +84,7 @@
 						</div>
 						<p style="margin-top: 20px; font-size: 12px;  color:#808080;">招聘情况总览</p>
 						<p style="font-size: 14px;  color:#808080;">共计 10 位候选人参与面试,通过率 <span style="color: #409EFF;">20%</span></p>
-												<!-- 这里可以添加右侧内容 -->
+											
 					</div>
 				</div>
 			</el-col>
@@ -104,7 +102,7 @@
 					<div class="flex-margin flex w100" :class="` home-one-animation${k}`">
 						<div class="flex-auto">
 							<span class="font30">{{ v.num1 }}</span>
-							<!-- <span class="ml5 font16" :style="{ color: v.color1 }">{{ v.num2 }}%</span -->
+							
 							<div class="mt10">{{ v.num3 }}</div>
 						</div>
 						<div class="home-card-item-icon flex" :style="{ background: `var(${v.color2})` }">
@@ -113,6 +111,105 @@
 					</div>
 				</div>
 			</el-col>
+		</el-row> -->
+
+		<!-- 添加英雄联盟数据可视化部分 -->
+		<el-row :gutter="15" class="lol-data-section">
+			<el-col :span="24">
+				<div class="lol-container" >
+					<div class="head">
+						<div class="weather"><span id="showTime"></span></div>
+						<h1>设备运维数据中心</h1>
+					</div>
+
+					<div class="mainbox">
+						<ul class="clearfix">
+							<li>
+								<div class="boxall" style="height:400px;">
+									<div class="alltitle">设备运行状态</div>
+									<div class="navboxall" id="echart5" style="height: 95%;"></div>
+								</div>
+								<div class="boxall" style="height:260px; overflow: hidden;">
+									<div class="alltitle">设备实时运行情况</div>
+									<div class="navboxall">
+										<div class="wraptit">
+											<span>设备编号</span><span>运行时长</span><span>运行状态</span><span>故障次数</span>
+										</div>
+										<div class="wrap">
+											<ul>
+												<li v-for="(hero, index) in heroData" :key="index" style="width: 100%;">
+													<div style="display: flex;justify-content: space-between; width: 100%;">
+														<span>{{hero.name}}</span>
+														<span>{{hero.appearances}}</span>
+														<span>{{hero.pickRate}}</span>
+														<span>{{hero.winRate}}</span>
+													</div>
+												</li>
+											</ul>
+										</div>
+									</div>
+								</div>
+								<div class="boxall" style="height:260px; overflow: hidden;">
+									<div class="alltitle">设备故障统计</div>
+									<div class="navboxall" id="echart1" style="height: 95%;"></div>
+								</div>
+							</li>
+
+							<li>
+								<div class="boxall" style="height:230px">
+									<div class="clearfix navboxall" style="height: 100%">
+										<div class="pulll_left zhibiao">
+											<div class="zb1">
+												<span>运行<br>0个</span>
+												<div id="zb1" style="height: 95%;"></div>
+											</div>
+											<div class="zb2">
+												<span>故障<br>0个</span>
+												<div id="zb2" style="height: 95%;"></div>
+											</div>
+											<div class="zb3">
+												<span>等待<br>0个</span>
+												<div id="zb3" style="height: 95%;"></div>
+											</div>
+										</div>
+									</div>
+								</div>
+
+								<div class="boxall" style="height:350px">
+									<div class="alltitle">设备实时执行情况</div>
+									<div class="navboxall" id="echart4" style="height: 95%;"></div>
+								</div>
+								<div class="boxall" style="height:340px">
+									<div class="alltitle">故障维修执行情况</div>
+									<div class="navboxall" id="echart3" style="height: 95%;"></div>
+								</div>
+							</li>
+
+							<li>
+								<div class="boxall" style="height:300px">
+									<div class="alltitle">设备故障次数排行</div>
+									<div class="navboxall">
+										<el-table :data="teamRankings" style="width: 100%">
+											<el-table-column prop="rank" label="排名" width="80"/>
+											<el-table-column prop="name" label="设备名称"/>
+											<el-table-column prop="matches" label="故障次数"/>
+											<el-table-column prop="winRate" label="维修用时"/>
+										</el-table>
+									</div>
+								</div>
+
+								<div class="boxall" style="height:320px">
+									<div class="alltitle">设备维修用时排行</div>
+									<div class="navboxall" id="echart2" style="height: 95%;"></div>
+								</div>
+								<div class="boxall" style="height:300px">
+									<div class="alltitle">设备维修时间统计</div>
+								</div>
+							</li>
+						</ul>
+					</div>
+				</div>
+			</el-col>
 		</el-row>
 	</div>
 </template>
@@ -257,6 +354,27 @@ export default defineComponent({
 				color: '#303133',
 			},
 			apiData: null as ApiData | null,
+			
+			// 添加英雄联盟数据
+			heroData: [
+				{ name: 'DEV001', appearances: '168h', pickRate: '正常', winRate: '2次' },
+				{ name: 'DEV002', appearances: '145h', pickRate: '正常', winRate: '1次' },
+				{ name: 'DEV003', appearances: '132h', pickRate: '故障', winRate: '3次' },
+				{ name: 'DEV004', appearances: '120h', pickRate: '正常', winRate: '0次' },
+				{ name: 'DEV005', appearances: '96h', pickRate: '等待', winRate: '1次' },
+				{ name: 'DEV006', appearances: '72h', pickRate: '正常', winRate: '1次' },
+				{ name: 'DEV007', appearances: '48h', pickRate: '故障', winRate: '2次' },
+				{ name: 'DEV008', appearances: '36h', pickRate: '正常', winRate: '0次' },
+				{ name: 'DEV009', appearances: '24h', pickRate: '正常', winRate: '1次' },
+				{ name: 'DEV010', appearances: '12h', pickRate: '等待', winRate: '0次' }
+			],
+			teamRankings: [
+				{ rank: 1, name: 'DEV003', matches: 15, winRate: '2.5h' },
+				{ rank: 2, name: 'DEV007', matches: 12, winRate: '1.8h' },
+				{ rank: 3, name: 'DEV001', matches: 8, winRate: '1.2h' },
+				{ rank: 4, name: 'DEV005', matches: 6, winRate: '1.0h' },
+				{ rank: 5, name: 'DEV002', matches: 4, winRate: '0.8h' }
+			]
 		});
 		const router = useRouter();
 		// 折线图
@@ -553,6 +671,12 @@ export default defineComponent({
 		onMounted(() => {
 			fetchApiData();
 			initEchartsResize();
+			initTime(); // 初始化时间显示
+			//initLolCharts(); // 初始化英雄联盟相关图表
+			initHeroScroll(); // 添加英雄数据轮播初始化
+			nextTick(() => {
+				initLolCharts();
+			});
 		});
 		// 由于页面缓存原因,keep-alive
 		onActivated(() => {
@@ -643,6 +767,412 @@ export default defineComponent({
 				router.push(routes[index]);
 			}
 		};
+
+		// 初始化时间显示
+		const initTime = () => {
+			const showTime = () => {
+				const dt = new Date();
+				const y = dt.getFullYear();
+				const mt = dt.getMonth() + 1;
+				const day = dt.getDate();
+				const h = dt.getHours();
+				const m = dt.getMinutes();
+				const s = dt.getSeconds();
+				document.getElementById("showTime")!.innerHTML = 
+					y + "年" + mt + "月" + day + "日" + h + "时" + m + "分" + s + "秒";
+			};
+			showTime();
+			setInterval(showTime, 1000);
+		};
+		//
+		/* function echarts_3() {
+        // 基于准备好的dom,初始化echarts实例
+        var myChart = echarts.init(document.getElementById('echart3'));
+
+		option3 
+
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+        window.addEventListener("resize", function() {
+            myChart.resize();
+        });
+    } */
+		// 初始化英雄联盟相关图表
+		const initLolCharts = () => {
+			// 设备运行状态图
+			const echart5 = echarts.init(document.getElementById('echart5'));
+			const option5 = {
+				tooltip: {
+					trigger: 'axis',
+					axisPointer: {
+						type: 'shadow'
+					}
+				},
+				legend: {
+					data: ['运行时长', '故障次数', '维修时间'],
+					textStyle: {
+						color: '#fff'
+					}
+				},
+				grid: {
+					left: '3%',
+					right: '4%',
+					bottom: '3%',
+					containLabel: true
+				},
+				xAxis: {
+					type: 'category',
+					data: ['DEV001', 'DEV002', 'DEV003', 'DEV004', 'DEV005'],
+					axisLabel: {
+						color: '#fff'
+					}
+				},
+				yAxis: {
+					type: 'value',
+					axisLabel: {
+						color: '#fff'
+					}
+				},
+				series: [
+					{
+						name: '运行时长',
+						type: 'bar',
+						data: [168, 145, 132, 120, 96],
+						itemStyle: {
+							color: '#91cc75'
+						}
+					},
+					{
+						name: '故障次数',
+						type: 'bar',
+						data: [2, 1, 3, 0, 1],
+						itemStyle: {
+							color: '#ee6666'
+						}
+					},
+					{
+						name: '维修时间',
+						type: 'line',
+						data: [2.5, 1.8, 3.2, 0, 1.5],
+						itemStyle: {
+							color: '#fac858'
+						}
+					}
+				]
+			};
+			echart5.setOption(option5);
+
+			// 故障维修执行情况
+			const echart3 = echarts.init(document.getElementById('echart3'));
+			const option3 = {
+				tooltip: {
+					trigger: 'axis',
+					axisPointer: {
+						lineStyle: {
+							color: '#57617B'
+						}
+					}
+				},
+				legend: {
+					data: ['故障数', '已修复', '待修复'],
+					top: '0',
+					textStyle: {
+						color: "#fff"
+					},
+					itemGap: 20,
+				},
+				grid: {
+					left: '0',
+					right: '20',
+					top: '10',
+					bottom: '20',
+					containLabel: true
+				},
+				xAxis: [{
+					type: 'category',
+					boundaryGap: false,
+					axisLabel: {
+						show: true,
+						textStyle: {
+							color: 'rgba(255,255,255,1)',
+							fontSize: 11
+						}
+					},
+					axisLine: {
+						lineStyle: {
+							color: 'rgba(255,255,255,.1)'
+						}
+					},
+					data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
+				}],
+				yAxis: [{
+					axisLabel: {
+						show: true,
+						textStyle: {
+							color: 'rgba(255,255,255,.6)'
+						}
+					},
+					axisLine: {
+						lineStyle: {
+							color: 'rgba(255,255,255,.1)'
+						}
+					},
+					splitLine: {
+						lineStyle: {
+							color: 'rgba(255,255,255,.1)'
+						}
+					}
+				}],
+				series: [{
+					name: '故障数',
+					type: 'line',
+					smooth: true,
+					data: [5, 3, 4, 6, 2, 5, 3, 4, 5, 3, 4, 5]
+				}, {
+					name: '已修复',
+					type: 'line',
+					smooth: true,
+					data: [4, 2, 4, 5, 2, 4, 3, 3, 5, 2, 3, 4]
+				}, {
+					name: '待修复',
+					type: 'line',
+					smooth: true,
+					data: [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1]
+				}]
+			};
+			echart3.setOption(option3);
+
+			// 设备实时执行情况
+			const echart4 = echarts.init(document.getElementById('echart4'));
+			const option4 = {
+				tooltip: {
+					trigger: 'axis'
+				},
+				legend: {
+					data: ['运行设备', '故障设备'],
+					textStyle: {
+						color: '#fff'
+					}
+				},
+				grid: {
+					left: '3%',
+					right: '4%',
+					bottom: '3%',
+					containLabel: true
+				},
+				xAxis: {
+					type: 'category',
+					data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
+					axisLabel: {
+						color: '#fff'
+					}
+				},
+				yAxis: {
+					type: 'value',
+					axisLabel: {
+						color: '#fff'
+					}
+				},
+				series: [
+					{
+						name: '运行设备',
+						type: 'bar',
+						data: [150, 145, 160, 155, 158, 152],
+						itemStyle: {
+							color: '#91cc75'
+						}
+					},
+					{
+						name: '故障设备',
+						type: 'bar',
+						data: [8, 12, 5, 7, 10, 6],
+						itemStyle: {
+							color: '#ee6666'
+						}
+					}
+				]
+			};
+			echart4.setOption(option4);
+
+			// 设备维修用时排行
+			const echart2 = echarts.init(document.getElementById('echart2'));
+			const option2 = {
+				tooltip: {
+					trigger: 'item'
+				},
+				legend: {
+					top: '5%',
+					left: 'center',
+					textStyle: {
+						color: '#fff'
+					}
+				},
+				series: [
+					{
+						name: '维修用时',
+						type: 'pie',
+						radius: ['40%', '70%'],
+						avoidLabelOverlap: false,
+						itemStyle: {
+							borderRadius: 10,
+							borderColor: '#fff',
+							borderWidth: 2
+						},
+						label: {
+							show: true,
+							formatter: '{b}: {c}h'
+						},
+						data: [
+							{ value: 2.5, name: 'DEV003' },
+							{ value: 1.8, name: 'DEV007' },
+							{ value: 1.2, name: 'DEV001' },
+							{ value: 1.0, name: 'DEV005' },
+							{ value: 0.8, name: 'DEV002' }
+						]
+					}
+				]
+			};
+			echart2.setOption(option2);
+
+			// 指标图表
+			const zb1 = echarts.init(document.getElementById('zb1'));
+			const zb2 = echarts.init(document.getElementById('zb2'));
+			const zb3 = echarts.init(document.getElementById('zb3'));
+
+			const zbOption = (value: number, color: string) => ({
+				series: [{
+					type: 'gauge',
+					startAngle: 180,
+					endAngle: 0,
+					min: 0,
+					max: 100,
+					splitNumber: 10,
+					itemStyle: {
+						color: color
+					},
+					progress: {
+						show: true,
+						roundCap: true,
+						width: 8
+					},
+					pointer: {
+						show: false
+					},
+					axisLine: {
+						roundCap: true,
+						lineStyle: {
+							width: 8
+						}
+					},
+					axisTick: {
+						show: false
+					},
+					splitLine: {
+						show: false
+					},
+					axisLabel: {
+						show: false
+					},
+					title: {
+						show: false
+					},
+					detail: {
+						show: true,
+						fontSize: 14,
+						offsetCenter: [0, '20%'],
+						color: '#fff',
+						formatter: value + '%'
+					},
+					data: [{
+						value: value
+					}]
+				}]
+			});
+
+			// 设备故障统计
+			const echart1 = echarts.init(document.getElementById('echart1'));
+			const option1 = {
+				tooltip: {
+					trigger: 'item',
+					formatter: '{b}: {c}台 ({d}%)'
+				},
+				legend: {
+					orient: 'vertical',
+					right: 10,
+					top: 'center',
+					textStyle: {
+						color: '#fff'
+					}
+				},
+				series: [{
+					type: 'pie',
+					radius: ['50%', '70%'],
+					label: {
+						show: true,
+						formatter: '{b}: {c}台'
+					},
+					data: [
+						{value: 150, name: '正常运行'},
+						{value: 10, name: '故障维修'},
+						{value: 5, name: '待机状态'},
+						{value: 3, name: '停机维护'}
+					]
+				}]
+			};
+			echart1.setOption(option1);
+
+			zb1.setOption(zbOption(89, '#91cc75')); // 运行
+			zb2.setOption(zbOption(6, '#ee6666')); // 故障
+			zb3.setOption(zbOption(5, '#fac858')); // 等待
+
+			// 监听窗口大小变化
+			window.addEventListener('resize', () => {
+				echart5.resize();
+				echart4.resize();
+				echart3.resize();
+				echart2.resize();
+				echart1.resize();
+				zb1.resize();
+				zb2.resize();
+				zb3.resize();
+			});
+		};
+
+		// 初始化英雄数据轮播
+		const initHeroScroll = () => {
+			const wrap = document.querySelector('.wrap') as HTMLElement;
+			if (!wrap) return;
+			
+			const ul = wrap.querySelector('ul') as HTMLElement;
+			if (!ul) return;
+			
+			// 克隆列表项用于无缝滚动
+			const cloneItems = ul.innerHTML;
+			ul.innerHTML = cloneItems + cloneItems;
+			
+			let scrollHeight = 0;
+			const itemHeight = 32; // 每个列表项的高度
+			const totalItems = state.heroData.length;
+			
+			const scroll = () => {
+				scrollHeight++;
+				if (scrollHeight >= totalItems * itemHeight) {
+					scrollHeight = 0;
+					ul.style.transition = 'none';
+					ul.style.transform = `translateY(0)`;
+					// 强制回流
+					ul.offsetHeight;
+					ul.style.transition = 'transform 0.5s linear';
+				} else {
+					ul.style.transform = `translateY(-${scrollHeight}px)`;
+				}
+			};
+			
+			// 每3秒滚动一次
+			setInterval(() => {
+				scroll();
+			}, 3000);
+		};
 		return {
 			homeLineRef,
 			homePieRef,
@@ -657,7 +1187,7 @@ export default defineComponent({
 <style scoped lang="scss">
 $homeNavLengh: 8;
 .home-container {
-	padding: 15px;
+	
 	overflow: hidden;
 	.home-card-one,
 	.home-card-two,
@@ -857,5 +1387,215 @@ $homeNavLengh: 8;
 			}
 		}
 	}
+
+	// 添加英雄联盟数据可视化样式
+	.lol-data-section {
+	
+		
+		.lol-container {
+			border-radius: 16px;
+			
+			color: #fff;
+			background: url(/@/assets/img/bg.png) center top #000d4a;
+			.head {
+				height: 105px;
+				background: url(/@/assets/img/head_bg.png) no-repeat center center;
+				text-align: center;
+				position: relative;
+
+				h1 {
+					font-size: 24px;
+					color: #fff;
+					line-height: 90px;
+					text-align: center;
+				}
+
+				.weather {
+					position: absolute;
+					right: 20px;
+					top: 0;
+					line-height: 85px;
+				}
+			}
+
+			.mainbox {
+				/* min-height: 600px; */
+				height: 100vh;
+				padding: 10px 20px;
+
+				.boxall {
+					border: 1px solid rgba(25, 186, 139, 0.17);
+					padding: 15px;
+					background: rgba(255, 255, 255, 0.04);
+					margin-bottom: 15px;
+					border-radius: 8px;
+
+					// 添加表格透明样式
+					:deep(.el-table) {
+						background-color: transparent;
+						
+						&::before {
+							display: none;
+						}
+						
+						tr {
+							background-color: transparent;
+						}
+						
+						th {
+							background-color: transparent;
+							border-bottom-color: rgba(255, 255, 255, 0.1);
+							color: #fff;
+						}
+						
+						td {
+							background-color: transparent;
+							border-bottom-color: rgba(255, 255, 255, 0.1);
+							color: #fff;
+						}
+						
+						.el-table__cell {
+							background-color: transparent;
+						}
+
+						// 添加表头背景透明
+						.el-table__header {
+							background-color: transparent;
+							
+							tr {
+								background-color: transparent;
+							}
+							
+							th.el-table__cell {
+								background-color: transparent !important;
+							}
+						}
+
+						// 添加表体背景透明
+						.el-table__body {
+							background-color: transparent;
+							
+							tr {
+								background-color: transparent !important;
+								
+								&:hover > td.el-table__cell {
+									background-color: rgba(255, 255, 255, 0.1) !important;
+								}
+							}
+						}
+					}
+
+					.alltitle {
+						font-size: 16px;
+						color: #fff;
+						padding-left: 12px;
+						margin-bottom: 10px;
+						position: relative;
+					}
+					.alltitle:before {
+						width: 5px;
+						height: 20px;
+						top: 2px;
+						position: absolute;
+						content: "";
+						background: #49bcf7;
+						border-radius: 20px;
+						left: 0;
+					}
+				}
+
+				ul.clearfix {
+					display: flex;
+					justify-content: space-between;
+					margin: 0;
+					padding: 0;
+					list-style: none;
+
+					li {
+						width: 32%;
+					}
+				}
+
+				.wrap {
+					height: 200px;
+					overflow: hidden;
+
+					ul {
+						list-style: none;
+						padding: 0;
+						margin: 0;
+						transition: transform 0.5s linear;
+
+						li {
+							line-height: 32px;
+							font-size: 14px;
+
+							p {
+								display: flex;
+								justify-content: space-between;
+								margin: 0;
+								padding: 0 10px;
+								color: #fff;
+
+								span {
+									flex: 1;
+									text-align: center;
+									
+									&:first-child {
+										text-align: left;
+									}
+								}
+							}
+
+							&:hover {
+								background: rgba(255, 255, 255, 0.1);
+							}
+						}
+					}
+				}
+
+				.wraptit {
+					display: flex;
+					justify-content: space-between;
+					padding: 0 10px;
+					margin-bottom: 10px;
+					color: #fff;
+					font-weight: bold;
+
+					span {
+						flex: 1;
+						text-align: center;
+						
+						&:first-child {
+							text-align: left;
+						}
+					}
+				}
+				.wrap {
+					span{
+						flex: 1;
+						text-align: center;
+						&:first-child {
+							text-align: left;
+						}
+					}
+				}
+
+				.zhibiao {
+					display: flex;
+					justify-content: space-around;
+					
+					.zb1, .zb2, .zb3 {
+						width: 33%;
+						height: 100%;
+						text-align: center;
+						color: #fff;
+						font-size: 14px;
+						padding: 10px;
+					}
+				}
+			}
+		}
+	}
 }
 </style>