ソースを参照

冰箱监测点趋势图界面

like 6 ヶ月 前
コミット
8545439077

BIN
snowy-admin-web/src/assets/images/monitor/01.png


BIN
snowy-admin-web/src/assets/images/monitor/02.png


BIN
snowy-admin-web/src/assets/images/monitor/03.png


BIN
snowy-admin-web/src/assets/images/monitor/bg.png


+ 16 - 2
snowy-admin-web/src/views/biz/monitor/point/index.vue

@@ -1,8 +1,8 @@
 <template>
 	<div class="table_item">
-		<a-page-header sub-title="监测点配置" @back="goBack" style="padding: 20px 0">
+		<a-page-header sub-title="监测点配置" @back="goBack" style="padding: 0 0 20px">
 			<template #title>
-				<span style="font-size: 20px; cursor: pointer" @click="goBack">返回</span>
+				<span style="font-size: 18px; cursor: pointer" @click="goBack">返回</span>
 			</template>
 		</a-page-header>
 
@@ -52,6 +52,10 @@
 			<template #bodyCell="{ column, record, index }">
 				<!-- 序号 -->
 				<template v-if="column.dataIndex === 'index'">{{ index + 1 }} </template>
+				<template v-if="column.dataIndex === 'name'">
+					<a-button type="link" @click="leaveFor('/biz/monitor/trendchart', record)">{{ record.name }}</a-button>
+				</template>
+
 				<template v-if="column.dataIndex === 'sensorType'">
 					{{ $TOOL.dictTypeData('SENSORTYPE', record.sensorType) }}
 				</template>
@@ -185,6 +189,16 @@
 			reset()
 		})
 	}
+
+	// 跳转到趋势图界面
+	const leaveFor = (url, record) => {
+		router.push({
+			path: url,
+			query: {
+				id: record.id
+			}
+		})
+	}
 </script>
 
 <style lang="less" scoped>

+ 668 - 0
snowy-admin-web/src/views/biz/monitor/trendchart/index.vue

@@ -0,0 +1,668 @@
+<template>
+	<div class="table_item">
+		<a-page-header sub-title="趋势图" @back="goBack" style="padding: 0 0 20px">
+			<template #title>
+				<span style="font-size: 18px; cursor: pointer" @click="goBack">返回</span>
+			</template>
+		</a-page-header>
+
+		<div class="table_head">
+			<div class="head_name">{{ data.name }}</div>
+			<div class="head_row">
+				<div class="label">
+					<img src="/src/assets/images/monitor/01.png" />
+				</div>
+				<div class="value">
+					<div>温度</div>
+					<div class="num">{{ data.temperature + '℃' }}</div>
+				</div>
+			</div>
+			<div class="head_row">
+				<div class="label">
+					<img src="/src/assets/images/monitor/02.png" />
+				</div>
+				<div class="value">
+					<div>温度</div>
+					<div class="num">{{ data.humidity + '%' }}</div>
+				</div>
+			</div>
+			<div class="head_row">
+				<div class="label">
+					<img src="/src/assets/images/monitor/03.png" />
+				</div>
+				<div class="value">
+					<div>二氧化碳</div>
+					<div class="num">{{ data.CO2 + '%' }}</div>
+				</div>
+			</div>
+
+			<div class="head_time">
+				{{ '更新时间 :' + data.time }}
+			</div>
+		</div>
+
+		<div class="table_search">
+			<div class="search_left">
+				<a-range-picker
+					v-model:value="timeValue"
+					style="width: 400px"
+					show-time
+					format="YYYY-MM-DD HH:mm:ss"
+					value-format="YYYY-MM-DD HH:mm:ss"
+					:disabled-date="disabledDate"
+				/>
+
+				<a-radio-group v-model:value="periodValue" button-style="solid">
+					<a-radio-button value="week">最近一周</a-radio-button>
+					<a-radio-button value="halfaMonth">最近半个月</a-radio-button>
+					<a-radio-button value="oneMonth">最近一个月</a-radio-button>
+					<a-radio-button value="threeMonths">最近三个月</a-radio-button>
+				</a-radio-group>
+			</div>
+
+			<div class="search_right">
+				<a-button class="xn-mg08">
+					<template #icon><download-outlined /></template>导出
+				</a-button>
+			</div>
+		</div>
+
+		<!-- 折线图 -->
+		<div class="chart">
+			<div class="echart" id="temperature"></div>
+			<div class="echart" id="humidity"></div>
+			<div class="echart" id="CO2"></div>
+		</div>
+	</div>
+</template>
+<script setup>
+	import * as echarts from 'echarts'
+	import { useRoute } from 'vue-router'
+	import router from '@/router'
+	import dayjs from 'dayjs' // 用于处理日期和时间
+	const Route = useRoute()
+	const queryId = ref() //监控对象的id
+
+	const data = ref({
+		name: '冰箱001-上层',
+		temperature: 26,
+		humidity: 80,
+		CO2: 50,
+		time: ' 2024-12-09 11:46'
+	})
+	const periodValue = ref('week')
+	const timeValue = ref([])
+
+	onBeforeMount(() => {
+		calculateDateRange()
+		if (Route.query.id) {
+			queryId.value = Route.query.id
+		}
+	})
+	onMounted(() => {
+		init()
+	})
+
+	// 监听 periodValue 变化,重新计算日期范围
+	watch(periodValue, () => {
+		calculateDateRange()
+	})
+
+	// 计算时间范围
+	const calculateDateRange = () => {
+		const now = new Date()
+		let startDate
+		const endDate = new Date(now)
+		endDate.setHours(23, 59, 59, 999) // 设置结束时间为当天的23:59:59
+
+		// 根据不同的选择设置开始时间
+		switch (periodValue.value) {
+			case 'week':
+				startDate = new Date(now)
+				startDate.setDate(now.getDate() - 7) // 最近一周
+				break
+			case 'halfaMonth':
+				startDate = new Date(now)
+				startDate.setDate(now.getDate() - 15) // 最近半个月
+				break
+			case 'oneMonth':
+				startDate = new Date(now)
+				startDate.setMonth(now.getMonth() - 1) // 最近一个月
+				break
+			case 'threeMonths':
+				startDate = new Date(now)
+				startDate.setMonth(now.getMonth() - 3) // 最近三个月
+				break
+			default:
+				startDate = new Date(now) // 默认值是今天
+		}
+		startDate.setHours(0, 0, 0, 0) // 设置开始时间为当天的00:00:00
+		timeValue.value = [formatDate(startDate), formatDate(endDate)]
+	}
+
+	const today = dayjs() // 获取当前时间和90天前的时间
+	const ninetyDaysAgo = today.subtract(90, 'day') // 90天前的日期
+
+	// 禁用超过90天之前的日期和今天之后的日期
+	const disabledDate = (current) => {
+		if (!current) return false
+		// 禁用当前日期早于90天之前的日期或今天之后的日期
+		return current.isBefore(ninetyDaysAgo, 'day') || current.isAfter(today, 'day')
+	}
+
+	// 格式化日期为 "YYYY-MM-DD HH:mm:ss"
+	const formatDate = (date) => {
+		const year = date.getFullYear()
+		const month = String(date.getMonth() + 1).padStart(2, '0')
+		const day = String(date.getDate()).padStart(2, '0')
+		const hours = String(date.getHours()).padStart(2, '0')
+		const minutes = String(date.getMinutes()).padStart(2, '0')
+		const seconds = String(date.getSeconds()).padStart(2, '0')
+
+		return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
+	}
+
+	const init = () => {
+		getEcharts1()
+		getEcharts2()
+		getEcharts3()
+	}
+	// 温度
+	const getEcharts1 = (val) => {
+		let Echarts = echarts.init(document.getElementById('temperature'))
+		const option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+					crossStyle: {
+						color: '#999'
+					},
+					label: {
+						show: false
+					}
+				},
+				formatter: function (params) {
+					let date = params[0].axisValueLabel
+					let value = params[0].value
+					return `${date}<br/>温度: ${value} °C`
+				}
+			},
+			grid: {
+				top: '15%',
+				left: '5%',
+				right: '7%',
+				bottom: '10%'
+			},
+			xAxis: {
+				type: 'category',
+				data: [
+					'2024-12-02',
+					'2024-12-03',
+					'2024-12-04',
+					'2024-12-05',
+					'2024-12-06',
+					'2024-12-07',
+					'2024-12-08',
+					'2024-12-09'
+				],
+				axisLine: {
+					show: true,
+					lineStyle: {
+						color: '#7e848e'
+					}
+				},
+				axisTick: {
+					show: false
+				},
+				splitLine: {
+					show: true
+				}
+			},
+			yAxis: {
+				type: 'value',
+				minInterval: 1,
+				axisLabel: {
+					formatter: '{value} °C'
+				},
+				splitLine: {
+					show: true
+				},
+				name: '温度',
+				nameLocation: 'end',
+				nameGap: 15,
+				nameTextStyle: {
+					color: '#484848',
+					fontSize: 14,
+					fontWeight: 'bold',
+					align: 'left',
+					padding: [0, 0, 0, -50]
+				}
+			},
+			series: [
+				{
+					name: '温度',
+					data: [16, 12, 36, 23, 20, 18, 20, 22],
+					type: 'line',
+					symbol: 'circle',
+					lineStyle: {
+						color: '#4292fa',
+						cap: 'round'
+					},
+					itemStyle: {
+						normal: {
+							color: 'transparent',
+							borderColor: '#4b93fa',
+							borderWidth: 2
+						}
+					},
+					symbolSize: 6,
+					label: {
+						show: false
+					},
+					markLine: {
+						data: [
+							{
+								name: '温度上限',
+								yAxis: 40,
+								lineStyle: {
+									color: '#f3956e',
+									width: 2,
+									type: 'solid',
+									shadowColor: 'rgba(243, 149, 110, 1)',
+									shadowBlur: 5
+								},
+								label: {
+									formatter: '温度上限: {c}°C',
+									color: '#f3956e'
+								}
+							},
+							{
+								name: '温度下限',
+								yAxis: 5,
+								lineStyle: {
+									color: '#41b982',
+									width: 2,
+									type: 'solid',
+									shadowColor: 'rgba(4, 188, 111, 1)',
+									shadowBlur: 5
+								},
+								label: {
+									formatter: '温度下限: {c}°C',
+									color: '#41b982'
+								}
+							}
+						]
+					}
+				}
+			]
+		}
+
+		// 绘制图表
+		Echarts.setOption(option)
+		// 自适应大小
+		window.onresize = () => {
+			Echarts.resize()
+		}
+	}
+	// 湿度
+	const getEcharts2 = (val) => {
+		let Echarts = echarts.init(document.getElementById('humidity'))
+		const option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+					crossStyle: {
+						color: '#999'
+					},
+					label: {
+						show: false
+					}
+				},
+				formatter: function (params) {
+					let date = params[0].axisValueLabel
+					let value = params[0].value
+					return `${date}<br/>湿度: ${value} %`
+				}
+			},
+			grid: {
+				top: '15%',
+				left: '5%',
+				right: '7%',
+				bottom: '10%'
+			},
+			xAxis: {
+				type: 'category',
+				data: [
+					'2024-12-02',
+					'2024-12-03',
+					'2024-12-04',
+					'2024-12-05',
+					'2024-12-06',
+					'2024-12-07',
+					'2024-12-08',
+					'2024-12-09'
+				],
+				axisLine: {
+					show: true,
+					lineStyle: {
+						color: '#7e848e'
+					}
+				},
+				axisTick: {
+					show: false
+				},
+				splitLine: {
+					show: true
+				}
+			},
+			yAxis: {
+				type: 'value',
+				minInterval: 1,
+				axisLabel: {
+					formatter: '{value} %'
+				},
+				splitLine: {
+					show: true
+				},
+				name: '湿度',
+				nameLocation: 'end',
+				nameGap: 15,
+				nameTextStyle: {
+					color: '#484848',
+					fontSize: 14,
+					fontWeight: 'bold',
+					align: 'left',
+					padding: [0, 0, 0, -50]
+				}
+			},
+			series: [
+				{
+					name: '湿度',
+					data: [16, 12, 36, 23, 20, 18, 20, 22],
+					type: 'line',
+					symbol: 'circle',
+					lineStyle: {
+						color: '#4292fa',
+						cap: 'round'
+					},
+					itemStyle: {
+						normal: {
+							color: 'transparent',
+							borderColor: '#4b93fa',
+							borderWidth: 2
+						}
+					},
+					symbolSize: 6,
+					label: {
+						show: false
+					},
+					markLine: {
+						data: [
+							{
+								name: '湿度上限',
+								yAxis: 40,
+								lineStyle: {
+									color: '#f3956e',
+									width: 2,
+									type: 'solid',
+									shadowColor: 'rgba(243, 149, 110, 1)',
+									shadowBlur: 5
+								},
+								label: {
+									formatter: '湿度上限: {c}%',
+									color: '#f3956e'
+								}
+							},
+							{
+								name: '湿度下限',
+								yAxis: 5,
+								lineStyle: {
+									color: '#41b982',
+									width: 2,
+									type: 'solid',
+									shadowColor: 'rgba(4, 188, 111, 1)',
+									shadowBlur: 5
+								},
+								label: {
+									formatter: '湿度下限: {c}%',
+									color: '#41b982'
+								}
+							}
+						]
+					}
+				}
+			]
+		}
+		// 绘制图表
+		Echarts.setOption(option)
+		// 自适应大小
+		window.onresize = () => {
+			Echarts.resize()
+		}
+	}
+	// CO2
+	const getEcharts3 = (val) => {
+		let Echarts = echarts.init(document.getElementById('CO2'))
+		const option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+					crossStyle: {
+						color: '#999'
+					},
+					label: {
+						show: false
+					}
+				},
+				formatter: function (params) {
+					let date = params[0].axisValueLabel
+					let value = params[0].value
+					return `${date}<br/>二氧化碳: ${value} %`
+				}
+			},
+			grid: {
+				top: '15%',
+				left: '5%',
+				right: '7%',
+				bottom: '10%'
+			},
+			xAxis: {
+				type: 'category',
+				data: [
+					'2024-12-02',
+					'2024-12-03',
+					'2024-12-04',
+					'2024-12-05',
+					'2024-12-06',
+					'2024-12-07',
+					'2024-12-08',
+					'2024-12-09'
+				],
+				axisLine: {
+					show: true,
+					lineStyle: {
+						color: '#7e848e'
+					}
+				},
+				axisTick: {
+					show: false
+				},
+				splitLine: {
+					show: true
+				}
+			},
+			yAxis: {
+				type: 'value',
+				minInterval: 1,
+				axisLabel: {
+					formatter: '{value} %'
+				},
+				splitLine: {
+					show: true
+				},
+				name: '二氧化碳',
+				nameLocation: 'end',
+				nameGap: 15,
+				nameTextStyle: {
+					color: '#484848',
+					fontSize: 14,
+					fontWeight: 'bold',
+					align: 'left',
+					padding: [0, 0, 0, -50]
+				}
+			},
+			series: [
+				{
+					name: '二氧化碳',
+					data: [16, 12, 36, 23, 20, 18, 20, 22],
+					type: 'line',
+					symbol: 'circle',
+					lineStyle: {
+						color: '#4292fa',
+						cap: 'round'
+					},
+					itemStyle: {
+						normal: {
+							color: 'transparent',
+							borderColor: '#4b93fa',
+							borderWidth: 2
+						}
+					},
+					symbolSize: 6,
+					label: {
+						show: false
+					},
+					markLine: {
+						data: [
+							{
+								name: '二氧化碳上限',
+								yAxis: 40,
+								lineStyle: {
+									color: '#f3956e',
+									width: 2,
+									type: 'solid',
+									shadowColor: 'rgba(243, 149, 110, 1)',
+									shadowBlur: 5
+								},
+								label: {
+									formatter: '二氧化碳上限: {c}%',
+									color: '#f3956e'
+								}
+							},
+							{
+								name: '二氧化碳下限',
+								yAxis: 5,
+								lineStyle: {
+									color: '#41b982',
+									width: 2,
+									type: 'solid',
+									shadowColor: 'rgba(4, 188, 111, 1)',
+									shadowBlur: 5
+								},
+								label: {
+									formatter: '二氧化碳下限: {c}%',
+									color: '#41b982'
+								}
+							}
+						]
+					}
+				}
+			]
+		}
+		// 绘制图表
+		Echarts.setOption(option)
+		// 自适应大小
+		window.onresize = () => {
+			Echarts.resize()
+		}
+	}
+
+	// 返回上一页
+	const goBack = () => {
+		router.go(-1)
+	}
+</script>
+
+<style lang="less" scoped>
+	.table_item {
+		padding: 15px 20px;
+		background-color: #ffffff;
+
+		.table_head {
+			width: 100%;
+			height: 100px;
+			padding: 0 10px;
+			background-image: url('/src/assets/images/monitor/bg.png');
+			background-size: cover;
+			background-position: center;
+			border-radius: 10px;
+			display: flex;
+			align-items: center;
+			.head_name,
+			.head_time {
+				flex: 2;
+				text-align: center;
+			}
+			.head_name {
+				font-size: 20px;
+				font-weight: bold;
+				color: #4362f0;
+			}
+			.head_row {
+				flex: 3;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+
+				.label {
+					img {
+						width: 50px;
+						height: 50px;
+					}
+				}
+
+				.value {
+					padding: 0 20px;
+					display: flex;
+					align-items: center;
+
+					.num {
+						font-weight: bold;
+						font-size: 26px;
+						padding: 0 20px;
+						width: 150px;
+						white-space: nowrap;
+						overflow: hidden;
+						text-overflow: ellipsis;
+					}
+				}
+			}
+		}
+
+		.table_search {
+			width: 100%;
+			margin: 20px 0;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+
+			:deep(.ant-radio-button-wrapper) {
+				margin: 0 10px;
+			}
+		}
+
+		// 图表
+		.chart {
+			width: 100%;
+			height: 950px;
+			.echart {
+				width: 100%;
+				height: 30%;
+				margin-bottom: 50px;
+			}
+		}
+	}
+</style>