Răsfoiți Sursa

Merge branch 'master' of http://git.nzklabs.com:3000/huangyuanhao/jfcloud-coldchain

jackzhou 7 luni în urmă
părinte
comite
125db6f294

+ 384 - 0
snowy-admin-web/src/components/HomeCard/SysTrendCard/index.vue

@@ -0,0 +1,384 @@
+<template>
+	<div class="trend-card">近三天报警趋势</div>
+
+	<div class="home_count">
+		<div class="ant-card-body">
+			<div class="card-left">
+				<img src="/src/assets/images/home/06.png" class="right-img" />
+				<div class="left-title">前天</div>
+			</div>
+			<div class="card-right">
+				<div class="echart" id="echart1"></div>
+			</div>
+		</div>
+		<div class="ant-card-body">
+			<div class="card-left">
+				<img src="/src/assets/images/home/07.png" class="right-img" />
+				<div class="left-title">昨天</div>
+			</div>
+			<div class="card-right">
+				<div class="echart" id="echart2"></div>
+			</div>
+		</div>
+		<div class="ant-card-body">
+			<div class="card-left">
+				<img src="/src/assets/images/home/08.png" class="right-img" />
+				<div class="left-title">今天</div>
+			</div>
+			<div class="card-right">
+				<div class="echart" id="echart3"></div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script setup name="SysTrendCard">
+	import * as echarts from 'echarts'
+
+	onMounted(() => {
+		getEcharts1()
+		getEcharts2()
+		getEcharts3()
+	})
+	const getEcharts1 = () => {
+		let Echarts = echarts.init(document.getElementById('echart1'))
+		const option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+					crossStyle: {
+						color: '#999'
+					}
+				}
+			},
+			grid: {
+				left: '0',
+				top: '15px',
+				right: '0',
+				bottom: '15px',
+				containLabel: true
+			},
+			xAxis: {
+				type: 'category',
+				data: [
+					'00:00-03:00',
+					'03:00-06:00',
+					'06:00-09:00',
+					'09:00-12:00',
+					'12:00-15:00',
+					'15:00-18:00',
+					'18:00-21:00',
+					'21:00-24:00'
+				],
+
+				axisPointer: {
+					type: 'shadow'
+				},
+				axisLabel: {
+					//展示角度
+					rotate: 40,
+					color: '#666',
+					show: false // 不显示坐标标签
+				},
+				axisLine: {
+					show: false, // 不显示坐标标签
+					lineStyle: {
+						color: '#ddd'
+					}
+				}
+			},
+			yAxis: {
+				type: 'value',
+				minInterval: 1,
+				axisLabel: {
+					show: false // 不显示 y 轴的数值
+				},
+				splitLine: {
+					lineStyle: {
+						type: 'dashed',
+						color: '#eee'
+					}
+				}
+			},
+			series: [
+				{
+					name: '报警次数',
+					data: [12, 34, 41, 5, 28, 19, 4, 36],
+					type: 'line',
+					smooth: true,
+					showSymbol: false,
+					itemStyle: {
+						normal: {
+							lineStyle: {
+								width: 1,
+								color: '#6c2bfb'
+							}
+						}
+					},
+					areaStyle: {
+						color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+							{
+								offset: 0,
+								color: '#8249fa'
+							},
+							{
+								offset: 1,
+								color: '#fff'
+							}
+						])
+					}
+				}
+			]
+		}
+		// 绘制图表
+		Echarts.setOption(option)
+		// 自适应大小
+		window.onresize = () => {
+			Echarts.resize()
+		}
+	}
+
+	const getEcharts2 = () => {
+		let Echarts = echarts.init(document.getElementById('echart2'))
+		const option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+					crossStyle: {
+						color: '#999'
+					}
+				}
+			},
+			grid: {
+				left: '0',
+				top: '15px',
+				right: '0',
+				bottom: '15px',
+				containLabel: true
+			},
+			xAxis: {
+				type: 'category',
+				data: [
+					'00:00-03:00',
+					'03:00-06:00',
+					'06:00-09:00',
+					'09:00-12:00',
+					'12:00-15:00',
+					'15:00-18:00',
+					'18:00-21:00',
+					'21:00-24:00'
+				],
+				axisPointer: {
+					type: 'shadow'
+				},
+				axisLabel: {
+					//展示角度
+					rotate: 40,
+					color: '#666',
+					show: false // 不显示坐标标签
+				},
+				axisLine: {
+					show: false, // 不显示坐标标签
+					lineStyle: {
+						color: '#ddd'
+					}
+				}
+			},
+			yAxis: {
+				type: 'value',
+				minInterval: 1,
+				axisLabel: {
+					show: false // 不显示 y 轴的数值
+				},
+				splitLine: {
+					lineStyle: {
+						type: 'dashed',
+						color: '#eee'
+					}
+				}
+			},
+			series: [
+				{
+					name: '报警次数',
+					data: [6, 64, 34, 10, 30, 21, 49, 14],
+					type: 'line',
+					smooth: true,
+					showSymbol: false,
+					itemStyle: {
+						normal: {
+							lineStyle: {
+								width: 1,
+								color: '#3175fb'
+							}
+						}
+					},
+					areaStyle: {
+						color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+							{
+								offset: 0,
+								color: '#96b8fa'
+							},
+							{
+								offset: 1,
+								color: '#fff'
+							}
+						])
+					}
+				}
+			]
+		}
+		// 绘制图表
+		Echarts.setOption(option)
+		// 自适应大小
+		window.onresize = () => {
+			Echarts.resize()
+		}
+	}
+	const getEcharts3 = () => {
+		let Echarts = echarts.init(document.getElementById('echart3'))
+		const option = {
+			tooltip: {
+				trigger: 'axis',
+				axisPointer: {
+					type: 'cross',
+					crossStyle: {
+						color: '#999'
+					}
+				}
+			},
+			grid: {
+				left: '0',
+				top: '15px',
+				right: '0',
+				bottom: '15px',
+				containLabel: true
+			},
+			xAxis: {
+				type: 'category',
+				data: [
+					'00:00-03:00',
+					'03:00-06:00',
+					'06:00-09:00',
+					'09:00-12:00',
+					'12:00-15:00',
+					'15:00-18:00',
+					'18:00-21:00',
+					'21:00-24:00'
+				],
+				axisPointer: {
+					type: 'shadow'
+				},
+				axisLabel: {
+					//展示角度
+					rotate: 40,
+					color: '#666',
+					show: false // 不显示坐标标签
+				},
+				axisLine: {
+					show: false, // 不显示坐标标签
+					lineStyle: {
+						color: '#ddd'
+					}
+				}
+			},
+			yAxis: {
+				type: 'value',
+				minInterval: 1,
+				axisLabel: {
+					show: false // 不显示 y 轴的数值
+				},
+				splitLine: {
+					lineStyle: {
+						type: 'dashed',
+						color: '#eee'
+					}
+				}
+			},
+			series: [
+				{
+					name: '报警次数',
+					data: [10, 25, 51, 3, 4, 0, 0, 0],
+					type: 'line',
+					smooth: true,
+					showSymbol: false,
+					itemStyle: {
+						normal: {
+							lineStyle: {
+								width: 1,
+								color: '#3ac9a2'
+							}
+						}
+					},
+					areaStyle: {
+						color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+							{
+								offset: 0,
+								color: '#4ef6f5'
+							},
+							{
+								offset: 1,
+								color: '#fff'
+							}
+						])
+					}
+				}
+			]
+		}
+		// 绘制图表
+		Echarts.setOption(option)
+		// 自适应大小
+		window.onresize = () => {
+			Echarts.resize()
+		}
+	}
+</script>
+
+<style lang="less" scoped>
+	.trend-card {
+		width: 100%;
+		padding: 15px 25px;
+		background: #ffffff;
+	}
+
+	.home_count {
+		width: 100%;
+		display: flex;
+		flex-wrap: wrap;
+		justify-content: space-between;
+
+		.ant-card-body {
+			flex: 1;
+			width: 100%;
+			height: 250px;
+			padding: 0 20px;
+			margin-bottom: 10px;
+			box-sizing: border-box;
+			background-color: #ffffff;
+			border-radius: 5px;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+
+			.card-left {
+				width: 10%;
+				text-align: center;
+				.left-title {
+					padding-top: 5px;
+				}
+			}
+
+			.card-right {
+				width: 90%;
+				height: 100%;
+				.echart {
+					height: 100%;
+				}
+			}
+		}
+		.ant-card-body:nth-child(5n) {
+			margin-right: 0;
+		}
+	}
+</style>

+ 132 - 0
snowy-admin-web/src/components/HomeCard/SysWarningCard/index.vue

@@ -0,0 +1,132 @@
+<template>
+	<div class="home_count">
+		<div class="warning-title">
+			<div>报警管理</div>
+			<a-button type="link" @click="leaveFor('/motoring/report')">更多</a-button>
+		</div>
+		<a-table :columns="columns" :data-source="dataSource" size="small" :pagination="false" :scroll="{ y: 260 }">
+			<template #bodyCell="{ column, record }">
+				<template v-if="column.dataIndex === 'state'">
+					<span>
+						<a-tag :color="record.state == '1' ? '#cd201f' : record.state == '2' ? '#2db7f5' : '#87d068'">
+							{{ record.stateVlaue }}
+						</a-tag>
+					</span>
+				</template>
+				<template v-if="column.dataIndex === 'action'">
+					<a-button type="link" size="small">编辑</a-button>
+					<a-divider type="vertical" />
+					<a-popconfirm title="删除此数据?" @confirm="deleteData(record)">
+						<a-button type="link" danger size="small">删除</a-button>
+					</a-popconfirm>
+					<a-divider type="vertical" />
+					<a-button type="link" size="small">记录</a-button>
+				</template>
+			</template>
+		</a-table>
+	</div>
+</template>
+
+<script setup name="SysWarningCard">
+	import bizIndexApi from '@/api/biz/bizIndexApi'
+	import router from '@/router'
+	const columns = [
+		{
+			title: '时间',
+			dataIndex: 'createTime',
+			ellipsis: true
+		},
+		{
+			title: '名称',
+			dataIndex: 'title',
+			ellipsis: true
+		},
+		{
+			title: '报警原因',
+			dataIndex: 'reason',
+			ellipsis: true
+		},
+		{
+			title: '状态',
+			dataIndex: 'state',
+			ellipsis: true
+		},
+		{
+			title: '操作',
+			dataIndex: 'action',
+			align: 'center',
+			width: '200px'
+		}
+	]
+	const dataSource = ref([
+		{
+			createTime: '2024-09-28 07:03:24',
+			title: 'ABSL-1超低温冰箱',
+			reason: '温度异常',
+			state: '1',
+			stateVlaue: '异常'
+		},
+		{
+			createTime: '2024-09-28 09:21:51',
+			title: 'ABSL-2超低温冰箱',
+			reason: '温度异常',
+			state: '1',
+			stateVlaue: '异常'
+		},
+		{
+			createTime: '2024-09-28 11:06:20',
+			title: 'ABSL-3超低温冰箱',
+			reason: '温度异常',
+			state: '1',
+			stateVlaue: '异常'
+		},
+		{
+			createTime: '2024-09-28 11:54:19',
+			title: 'ABSL-4超低温冰箱',
+			reason: '温度异常',
+			state: '1',
+			stateVlaue: '异常'
+		},
+		{
+			createTime: '2024-09-28 16:17:36',
+			title: 'ABSL-5超低温冰箱',
+			reason: '温度异常',
+			state: '1',
+			stateVlaue: '异常'
+		},
+		{
+			createTime: '2024-09-28 19:35:58',
+			title: 'ABSL-6超低温冰箱',
+			reason: '温度异常',
+			state: '1',
+			stateVlaue: '异常'
+		}
+	])
+	const apiLoading = ref(false)
+	onMounted(() => {})
+	const leaveFor = (url = '/') => {
+		router.replace({
+			path: url
+		})
+	}
+
+	// 删除
+	const deleteData = (record) => {
+		console.log(record.title, 'params')
+	}
+</script>
+
+<style lang="less" scoped>
+	.home_count {
+		width: 100%;
+		padding: 15px 25px;
+		background-color: #ffffff;
+
+		.warning-title {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			margin-bottom: 10px;
+		}
+	}
+</style>

+ 2 - 2
snowy-admin-web/src/views/index/index.vue

@@ -4,9 +4,9 @@
 			<!-- 顶部数据统计 -->
 			<sys-count-card class="mb-2" />
 			<!-- 近三天报警趋势 -->
-			<sys-biz-data-card class="mb-2" />
+			<sys-trend-card class="mb-2" />
 			<!-- 报警管理 -->
-			<sys-op-data-card class="mb-2" />
+			<sys-warning-card class="mb-2" />
 		</a-col>
 	</a-row>
 </template>

+ 204 - 0
snowy-admin-web/src/views/motoring/query/history.vue

@@ -0,0 +1,204 @@
+<template>
+	<div class="table_item">
+		<s-table ref="tableRef" :columns="columns" :data="loadData" :row-key="(record) => record.code">
+			<template #bodyCell="{ column, record }">
+				<template v-if="column.dataIndex === 'state'">
+					<span>
+						<a-tag :color="record.state == '1' ? '#2db7f5' : record.state == '2' ? '#cd201f' : '#87d068'">
+							{{ record.stateVlaue }}
+						</a-tag>
+					</span>
+				</template>
+			</template>
+		</s-table>
+	</div>
+</template>
+
+<script setup>
+	import tool from '@/utils/tool'
+	import jobApi from '@/api/dev/jobApi'
+	const searchFormState = ref({})
+	const tableRef = ref()
+	const columns = [
+		{
+			title: '采集时间',
+			dataIndex: 'time',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '所属部门',
+			dataIndex: 'bm',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '对象名称',
+			dataIndex: 'dxmc',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '设备状态',
+			dataIndex: 'state',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '监控点',
+			dataIndex: 'jkd',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '上下限',
+			dataIndex: 'up',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '传感器类型',
+			dataIndex: 'type',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '采集值1',
+			dataIndex: 'cjz1',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '采集值2',
+			dataIndex: 'cjz2',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '对象类型',
+			dataIndex: 'dxtype',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '冷链编号',
+			dataIndex: 'code',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		}
+	]
+
+	const loadData = (parameter) => {
+		return jobApi.jobPage(Object.assign(parameter, searchFormState.value)).then((res) => {
+			// return res
+			const obj = {
+				current: 1,
+				pages: 1,
+				records: [
+					{
+						time: '2024-08-28 07:03:24',
+						bm: '上海海关基数中心1',
+						dxmc: '-70度超低温冷冻储存箱',
+						state: '2',
+						stateVlaue: '异常',
+						jkd: '监控点1',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945621'
+					},
+					{
+						time: '2024-08-28 09:21:51',
+						bm: '上海海关基数中心2',
+						dxmc: '-71度超低温冷冻储存箱',
+						state: '2',
+						stateVlaue: '异常',
+						jkd: '监控点2',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945622'
+					},
+					{
+						time: '2024-08-28 11:06:20',
+						bm: '上海海关基数中心3',
+						dxmc: '-72度超低温冷冻储存箱',
+						state: '2',
+						stateVlaue: '异常',
+						jkd: '监控点3',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945623'
+					},
+					{
+						time: '2024-08-28 11:54:19',
+						bm: '上海海关基数中心4',
+						dxmc: '-73度超低温冷冻储存箱',
+						state: '2',
+						stateVlaue: '异常',
+						jkd: '监控点4',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945624'
+					},
+					{
+						time: '2024-08-28 16:17:36',
+						bm: '上海海关基数中心5',
+						dxmc: '-74度超低温冷冻储存箱',
+						state: '2',
+						stateVlaue: '异常',
+						jkd: '监控点5',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945625'
+					},
+					{
+						time: '2024-08-28 19:35:58',
+						bm: '上海海关基数中心6',
+						dxmc: '-75度超低温冷冻储存箱',
+						state: '2',
+						stateVlaue: '异常',
+						jkd: '监控点6',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945626'
+					}
+				],
+				size: 10,
+				total: 6
+			}
+			return obj
+		})
+	}
+</script>
+
+<style lang="less" scoped>
+	.table_item {
+		padding: 15px 20px;
+	}
+	:deep(.ant-table-pagination-right) {
+		justify-content: center !important;
+	}
+</style>

+ 76 - 3
snowy-admin-web/src/views/motoring/query/index.vue

@@ -1,12 +1,85 @@
 <template>
-	<div>数据查询</div>
+	<div class="query-box">
+		<div class="query-head">
+			<div class="query-tbas">
+				<div class="tbas-title" :class="activeKey == '1' ? 'active' : ''" @click="activeclick('1')">实时数据</div>
+				<a-divider type="vertical" style="height: 15px; background-color: #f4f5f7; margin: 8px 20px" />
+				<div class="tbas-title" :class="activeKey == '2' ? 'active' : ''" @click="activeclick('2')">历史数据</div>
+			</div>
+			<a-button type="link" @click="leaveFor('/motoring/report')">更多</a-button>
+		</div>
+
+		<div class="query-body">
+			<realtime ref="realtimeRef" v-if="activeKey == '1'" />
+			<history ref="historyRef" v-if="activeKey == '2'" />
+		</div>
+	</div>
 </template>
 <script setup>
+	import Realtime from './realtime.vue'
+	import History from './history.vue'
+
+	const activeKey = ref('1')
+	const realtimeRef = ref(null)
+	const historyRef = ref(null)
+
 	onMounted(() => {})
 
 	onBeforeMount(() => {})
 
+	// 点击标签
+	const activeclick = (v) => {
+		activeKey.value = v
+	}
+
 	// 监听
-	watch()
+	watch(
+		() => activeKey.value,
+		(newValue) => {
+			if (newValue === '1' && realtimeRef.value) {
+				realtimeRef.value.loadData()
+			} else if (newValue === '2' && historyRef.value) {
+				historyRef.value.loadData()
+			}
+		},
+		{
+			immediate: true // 立即执行
+		}
+	)
 </script>
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+	.query-box {
+		width: 100%;
+		height: 100vh;
+		overflow: hidden;
+		background-color: #fff;
+
+		// 顶部
+		.query-head {
+			width: 100%;
+			height: 50px;
+			display: flex;
+			justify-content: space-between;
+			padding: 15px;
+			border-bottom: 1px solid #e7e7e7;
+
+			.query-tbas {
+				width: 95%;
+				display: flex;
+
+				.tbas-title {
+					height: 35px;
+					line-height: 25px;
+					color: #a7a7a7;
+					font-size: 16px;
+					cursor: pointer;
+				}
+
+				.active {
+					color: #1b8fff;
+					border-bottom: 2px solid #1b8fff;
+				}
+			}
+		}
+	}
+</style>

+ 233 - 0
snowy-admin-web/src/views/motoring/query/realtime.vue

@@ -0,0 +1,233 @@
+<template>
+	<div class="table_item">
+		<s-table ref="tableRef" :columns="columns" :data="loadData" :row-key="(record) => record.code">
+			<template #operator>
+				<div class="table-head">
+					<div class="head-left">
+						剩余刷新时间:<text style="color: #1c8fff">{{ 33 }}</text>
+					</div>
+					<div class="head-right">
+						<a-button>
+							<template #icon><search-outlined /></template>搜索
+						</a-button>
+						<a-button>
+							<template #icon><download-outlined /></template>导出
+						</a-button>
+						<a-button>
+							<template #icon><printer-outlined /></template>打印
+						</a-button>
+					</div>
+				</div>
+			</template>
+			<template #bodyCell="{ column, record }">
+				<template v-if="column.dataIndex === 'state'">
+					<span>
+						<a-tag :color="record.state == '1' ? '#2db7f5' : record.state == '2' ? '#cd201f' : '#87d068'">
+							{{ record.stateVlaue }}
+						</a-tag>
+					</span>
+				</template>
+			</template>
+		</s-table>
+	</div>
+</template>
+
+<script setup>
+	import tool from '@/utils/tool'
+	import jobApi from '@/api/dev/jobApi'
+	const searchFormState = ref({})
+	const tableRef = ref()
+	const columns = [
+		{
+			title: '采集时间',
+			dataIndex: 'time',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '所属部门',
+			dataIndex: 'bm',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '对象名称',
+			dataIndex: 'dxmc',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '设备状态',
+			dataIndex: 'state',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '监控点',
+			dataIndex: 'jkd',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '上下限',
+			dataIndex: 'up',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '传感器类型',
+			dataIndex: 'type',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '采集值1',
+			dataIndex: 'cjz1',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '采集值2',
+			dataIndex: 'cjz2',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '对象类型',
+			dataIndex: 'dxtype',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '冷链编号',
+			dataIndex: 'code',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		}
+	]
+
+	const loadData = (parameter) => {
+		return jobApi.jobPage(Object.assign(parameter, searchFormState.value)).then((res) => {
+			// return res
+			const obj = {
+				current: 1,
+				pages: 1,
+				records: [
+					{
+						time: '2024-09-28 07:03:24',
+						bm: '广州海关基数中心1',
+						dxmc: '-80度超低温冷冻储存箱',
+						state: '1',
+						stateVlaue: '正常',
+						jkd: '监控点1',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945621'
+					},
+					{
+						time: '2024-09-28 09:21:51',
+						bm: '广州海关基数中心2',
+						dxmc: '-81度超低温冷冻储存箱',
+						state: '1',
+						stateVlaue: '正常',
+						jkd: '监控点2',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945622'
+					},
+					{
+						time: '2024-09-28 11:06:20',
+						bm: '广州海关基数中心3',
+						dxmc: '-82度超低温冷冻储存箱',
+						state: '1',
+						stateVlaue: '正常',
+						jkd: '监控点3',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945623'
+					},
+					{
+						time: '2024-09-28 11:54:19',
+						bm: '广州海关基数中心4',
+						dxmc: '-83度超低温冷冻储存箱',
+						state: '1',
+						stateVlaue: '正常',
+						jkd: '监控点4',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945624'
+					},
+					{
+						time: '2024-09-28 16:17:36',
+						bm: '广州海关基数中心5',
+						dxmc: '-84度超低温冷冻储存箱',
+						state: '1',
+						stateVlaue: '正常',
+						jkd: '监控点5',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945625'
+					},
+					{
+						time: '2024-09-28 19:35:58',
+						bm: '广州海关基数中心6',
+						dxmc: '-85度超低温冷冻储存箱',
+						state: '1',
+						stateVlaue: '正常',
+						jkd: '监控点6',
+						up: '-30~-10℃',
+						type: '温度',
+						cjz1: '-18.9℃',
+						cjz2: '/',
+						dxtype: '冰箱',
+						code: '6578945626'
+					}
+				],
+				size: 10,
+				total: 6
+			}
+			return obj
+		})
+	}
+</script>
+
+<style lang="less" scoped>
+	.table_item {
+		padding: 15px 20px;
+
+		.table-head {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+
+			.ant-btn {
+				margin-left: 10px;
+			}
+		}
+
+		:deep(.ant-table-pagination-right) {
+			justify-content: center !important;
+		}
+	}
+</style>

+ 76 - 3
snowy-admin-web/src/views/motoring/report/index.vue

@@ -1,12 +1,85 @@
 <template>
-	<div>监控管理</div>
+	<div class="query-box">
+		<div class="query-head">
+			<div class="query-tbas">
+				<div class="tbas-title" :class="activeKey == '1' ? 'active' : ''" @click="activeclick('1')">报警列表</div>
+				<a-divider type="vertical" style="height: 15px; background-color: #f4f5f7; margin: 8px 20px" />
+				<div class="tbas-title" :class="activeKey == '2' ? 'active' : ''" @click="activeclick('2')">报警通知列表</div>
+			</div>
+			<a-button type="link" @click="leaveFor('/motoring/report')">更多</a-button>
+		</div>
+
+		<div class="query-body">
+			<list ref="listRef" v-if="activeKey == '1'" />
+			<noticelist ref="noticelistRef" v-if="activeKey == '2'" />
+		</div>
+	</div>
 </template>
 <script setup>
+	import List from './list.vue'
+	import Noticelist from './noticelist.vue'
+
+	const activeKey = ref('1')
+	const listRef = ref(null)
+	const noticelistRef = ref(null)
+
 	onMounted(() => {})
 
 	onBeforeMount(() => {})
 
+	// 点击标签
+	const activeclick = (v) => {
+		activeKey.value = v
+	}
+
 	// 监听
-	watch()
+	watch(
+		() => activeKey.value,
+		(newValue) => {
+			if (newValue === '1' && listRef.value) {
+				listRef.value.loadData()
+			} else if (newValue === '2' && noticelistRef.value) {
+				noticelistRef.value.loadData()
+			}
+		},
+		{
+			immediate: true // 立即执行
+		}
+	)
 </script>
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+	.query-box {
+		width: 100%;
+		height: 100vh;
+		overflow: hidden;
+		background-color: #fff;
+
+		// 顶部
+		.query-head {
+			width: 100%;
+			height: 50px;
+			display: flex;
+			justify-content: space-between;
+			padding: 15px;
+			border-bottom: 1px solid #e7e7e7;
+
+			.query-tbas {
+				width: 95%;
+				display: flex;
+
+				.tbas-title {
+					height: 35px;
+					line-height: 25px;
+					color: #a7a7a7;
+					font-size: 16px;
+					cursor: pointer;
+				}
+
+				.active {
+					color: #1b8fff;
+					border-bottom: 2px solid #1b8fff;
+				}
+			}
+		}
+	}
+</style>

+ 324 - 0
snowy-admin-web/src/views/motoring/report/list.vue

@@ -0,0 +1,324 @@
+<template>
+	<div class="table_item">
+		<s-table ref="tableRef" :columns="columns" :data="loadData" :row-key="(record) => record.dxbh">
+			<template #operator>
+				<div class="table-head">
+					<div class="head-left">
+						<a-form
+							ref="searchFormRef"
+							name="advanced_search"
+							:model="searchFormState"
+							class="ant-advanced-search-form"
+						>
+							<a-form-item label="报警时间" name="searchKey">
+								<a-range-picker v-model:value="searchFormState.searchKey" value-format="YYYY/MM/DD" />
+							</a-form-item>
+						</a-form>
+						<a-button type="primary" @click="tableRef.refresh(true)">查询</a-button>
+						<a-button class="xn-mg08" @click="reset">重置</a-button>
+					</div>
+					<div class="head-right">
+						<a-button>
+							<template #icon><logout-outlined /></template>处理
+						</a-button>
+						<a-button>
+							<template #icon><logout-outlined /></template>全部处理
+						</a-button>
+						<a-button>
+							<template #icon><download-outlined /></template>导出
+						</a-button>
+						<a-button>
+							<template #icon><search-outlined /></template>搜索模式
+						</a-button>
+					</div>
+				</div>
+			</template>
+			<template #bodyCell="{ column, record }">
+				<template v-if="column.dataIndex === 'clzt'">
+					<span>
+						<a-tag :color="record.clzt == '1' ? '#cd201f' : record.clzt == '2' ? '#2db7f5' : '#87d068'">
+							{{ record.clztValue }}
+						</a-tag>
+					</span>
+				</template>
+			</template>
+		</s-table>
+	</div>
+</template>
+
+<script setup>
+	import tool from '@/utils/tool'
+	import jobApi from '@/api/dev/jobApi'
+	const searchFormRef = ref()
+	const searchFormState = ref({})
+	const tableRef = ref()
+	const columns = [
+		{
+			title: '处理状态',
+			dataIndex: 'clzt',
+			align: 'center',
+			ellipsis: true,
+			sorter: true,
+			width: '10%'
+		},
+		{
+			title: '报警开始时间',
+			dataIndex: 'bjkssj',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '最近报警时间',
+			dataIndex: 'zjbjsj',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '所属部门',
+			dataIndex: 'ssbm',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '对象编码',
+			dataIndex: 'dxbh',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '对象名称',
+			dataIndex: 'dxmc',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '报警类型',
+			dataIndex: 'bjlx',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '报警原因',
+			dataIndex: 'bjyy',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '恢复正常时间',
+			dataIndex: 'hfzcsj',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '相应时间',
+			dataIndex: 'xysj',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '处理时间',
+			dataIndex: 'clsj',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '处理人',
+			dataIndex: 'clr',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '异常原因',
+			dataIndex: 'ycyy',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '处理措施',
+			dataIndex: 'clcs',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		}
+	]
+
+	const loadData = (parameter) => {
+		if (searchFormState.value.searchKey) {
+			searchFormState.value.startCreateTime = searchFormState.value.searchKey[0]
+			searchFormState.value.endCreateTime = searchFormState.value.searchKey[1]
+			delete searchFormState.value.searchKey
+		}
+
+		return jobApi.jobPage(Object.assign(parameter, searchFormState.value)).then((res) => {
+			// return res
+			const obj = {
+				current: 1,
+				pages: 1,
+				records: [
+					{
+						clzt: '1',
+						clztValue: '未处理',
+						bjkssj: '2024-08-28 07:03:24',
+						zjbjsj: '2024-08-28 09:03:42',
+						ssbm: '上海海关技术中心',
+						dxbh: '',
+						dxmc: '-20度冰箱',
+						jsr: '周小杰',
+						bjlx: '超限报警',
+						bjyy: '温度超上限',
+						bjyy: '温度超上限',
+						hfzcsj: '',
+						xysj: '',
+						clsj: '',
+						clr: '',
+						ycyy: '',
+						clcs: '',
+						name: '-21度冰箱',
+						fsnr: '广州海关基数中心-[-20度冰箱]报警;温度超过上限:-7.7℃',
+						type: '短信报警',
+						dx: '13578945780',
+						dh: '/',
+						wx: '/',
+						yj: '/',
+						zt: '发送成功',
+						clcs: ''
+					},
+					{
+						clzt: '2',
+						clztValue: '已处理',
+						bjkssj: '2024-08-28 11:32:12',
+						zjbjsj: '2024-08-28 11:52:42',
+						ssbm: '上海海关技术中心',
+						dxbh: '',
+						dxmc: '-20度冰箱',
+						jsr: '周小杰',
+						bjlx: '超限报警',
+						bjyy: '温度超上限',
+						bjyy: '温度超上限',
+						hfzcsj: '',
+						xysj: '',
+						clsj: '',
+						clr: '',
+						ycyy: '',
+						clcs: ''
+					},
+					{
+						clzt: '1',
+						clztValue: '未处理',
+						bjkssj: '2024-08-28 13:07:34',
+						zjbjsj: '2024-08-28 13:10:12',
+						ssbm: '上海海关技术中心',
+						dxbh: '',
+						dxmc: '-20度冰箱',
+						jsr: '周小杰',
+						bjlx: '超限报警',
+						bjyy: '温度超上限',
+						bjyy: '温度超上限',
+						hfzcsj: '',
+						xysj: '',
+						clsj: '',
+						clr: '',
+						ycyy: '',
+						clcs: '',
+						name: '-23度冰箱'
+					},
+					{
+						clzt: '2',
+						clztValue: '已处理',
+						bjkssj: '2024-08-28 15:41:04',
+						zjbjsj: '2024-08-28 15:55:51',
+						ssbm: '上海海关技术中心',
+						dxbh: '',
+						dxmc: '-20度冰箱',
+						jsr: '周小杰',
+						bjlx: '超限报警',
+						bjyy: '温度超上限',
+						bjyy: '温度超上限',
+						hfzcsj: '',
+						xysj: '',
+						clsj: '',
+						clr: '',
+						ycyy: '',
+						clcs: ''
+					},
+					{
+						clzt: '1',
+						clztValue: '未处理',
+						bjkssj: '2024-08-28 16:43:14',
+						zjbjsj: '2024-08-28 16:57:32',
+						ssbm: '上海海关技术中心',
+						dxbh: '',
+						dxmc: '-20度冰箱',
+						jsr: '周小杰',
+						bjlx: '超限报警',
+						bjyy: '温度超上限',
+						bjyy: '温度超上限',
+						hfzcsj: '',
+						xysj: '',
+						clsj: '',
+						clr: '',
+						ycyy: '',
+						clcs: ''
+					},
+					{
+						clzt: '2',
+						clztValue: '已处理',
+						bjkssj: '2024-08-28 18:21:33',
+						zjbjsj: '2024-08-28 18:33:12',
+						ssbm: '上海海关技术中心',
+						dxbh: '',
+						dxmc: '-20度冰箱',
+						jsr: '周小杰',
+						bjlx: '超限报警',
+						bjyy: '温度超上限',
+						bjyy: '温度超上限',
+						hfzcsj: '',
+						xysj: '',
+						clsj: '',
+						clr: '',
+						ycyy: '',
+						clcs: ''
+					}
+				],
+				size: 10,
+				total: 6
+			}
+			return obj
+		})
+	}
+	// 重置
+	const reset = () => {
+		searchFormRef.value.resetFields()
+		tableRef.value.refresh(true)
+	}
+</script>
+
+<style lang="less" scoped>
+	.table_item {
+		padding: 15px 20px;
+		.table-head {
+			width: 100%;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+
+			.head-left {
+				display: flex;
+			}
+
+			.ant-btn {
+				margin-left: 10px;
+			}
+		}
+	}
+	:deep(.ant-table-pagination-right) {
+		justify-content: center !important;
+	}
+</style>

+ 270 - 0
snowy-admin-web/src/views/motoring/report/noticelist.vue

@@ -0,0 +1,270 @@
+<template>
+	<div class="table_item">
+		<s-table ref="tableRef" :columns="columns" :data="loadData" :row-key="(record) => record.sctime">
+			<template #operator>
+				<div class="table-head">
+					<div class="head-left">
+						<a-form
+							ref="searchFormRef"
+							name="advanced_search"
+							:model="searchFormState"
+							class="ant-advanced-search-form"
+						>
+							<a-form-item label="报警时间" name="searchKey">
+								<a-range-picker v-model:value="searchFormState.searchKey" value-format="YYYY/MM/DD" />
+							</a-form-item>
+						</a-form>
+						<a-button type="primary" @click="tableRef.refresh(true)">查询</a-button>
+						<a-button class="xn-mg08" @click="reset">重置</a-button>
+					</div>
+					<div class="head-right">
+						<a-button>
+							<template #icon><download-outlined /></template>导出
+						</a-button>
+						<a-button>
+							<template #icon><search-outlined /></template>搜索模式
+						</a-button>
+					</div>
+				</div>
+			</template>
+		</s-table>
+	</div>
+</template>
+
+<script setup>
+	import tool from '@/utils/tool'
+	import jobApi from '@/api/dev/jobApi'
+	const searchFormRef = ref()
+	const searchFormState = ref({})
+	const tableRef = ref()
+	const columns = [
+		{
+			title: '生成时间',
+			dataIndex: 'sctime',
+			align: 'center',
+			ellipsis: true,
+			sorter: true,
+			width: '10%'
+		},
+		{
+			title: '发送时间',
+			dataIndex: 'fstime',
+			align: 'center',
+			ellipsis: true,
+			sorter: true,
+			width: '10%'
+		},
+		{
+			title: '接收人',
+			dataIndex: 'jsr',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '对象编码',
+			dataIndex: 'dxcpde',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '对象名称',
+			dataIndex: 'name',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '发送内容',
+			dataIndex: 'fsnr',
+			align: 'center',
+			ellipsis: true,
+			width: '20%'
+		},
+		{
+			title: '通知类型',
+			dataIndex: 'type',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '短信',
+			dataIndex: 'dx',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '电话',
+			dataIndex: 'dh',
+			align: 'center',
+			ellipsis: true
+		},
+		{
+			title: '微信',
+			dataIndex: 'wx',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '邮件',
+			dataIndex: 'yj',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '状态',
+			dataIndex: 'zt',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		},
+		{
+			title: '故障原因',
+			dataIndex: 'gzyy',
+			align: 'center',
+			ellipsis: true,
+			sorter: true
+		}
+	]
+
+	const loadData = (parameter) => {
+		if (searchFormState.value.searchKey) {
+			searchFormState.value.startCreateTime = searchFormState.value.searchKey[0]
+			searchFormState.value.endCreateTime = searchFormState.value.searchKey[1]
+			delete searchFormState.value.searchKey
+		}
+
+		return jobApi.jobPage(Object.assign(parameter, searchFormState.value)).then((res) => {
+			// return res
+			const obj = {
+				current: 1,
+				pages: 1,
+				records: [
+					{
+						sctime: '2024-08-28 07:03:24',
+						fstime: '2024-08-28 09:03:42',
+						jsr: '周小杰',
+						dxcpde: '',
+						name: '-21度冰箱',
+						fsnr: '广州海关基数中心-[-20度冰箱]报警;温度超过上限:-7.7℃',
+						type: '短信报警',
+						dx: '13578945780',
+						dh: '/',
+						wx: '/',
+						yj: '/',
+						zt: '发送成功',
+						gzyy: ''
+					},
+					{
+						sctime: '2024-08-28 11:32:12',
+						fstime: '2024-08-28 11:52:42',
+						jsr: '周小杰',
+						dxcpde: '',
+						name: '-22度冰箱',
+						fsnr: '广州海关基数中心-[-20度冰箱]报警;温度超过上限:-7.7℃',
+						type: '短信报警',
+						dx: '13578945780',
+						dh: '/',
+						wx: '/',
+						yj: '/',
+						zt: '发送成功',
+						gzyy: ''
+					},
+					{
+						sctime: '2024-08-28 13:07:34',
+						fstime: '2024-08-28 13:10:12',
+						jsr: '周小杰',
+						dxcpde: '',
+						name: '-23度冰箱',
+						fsnr: '广州海关基数中心-[-20度冰箱]报警;温度超过上限:-7.7℃',
+						type: '短信报警',
+						dx: '13578945780',
+						dh: '/',
+						wx: '/',
+						yj: '/',
+						zt: '发送成功',
+						gzyy: ''
+					},
+					{
+						sctime: '2024-08-28 15:41:04',
+						fstime: '2024-08-28 15:55:51',
+						jsr: '周小杰',
+						dxcpde: '',
+						name: '-24度冰箱',
+						fsnr: '广州海关基数中心-[-20度冰箱]报警;温度超过上限:-7.7℃',
+						type: '短信报警',
+						dx: '13578945780',
+						dh: '/',
+						wx: '/',
+						yj: '/',
+						zt: '发送成功',
+						gzyy: ''
+					},
+					{
+						sctime: '2024-08-28 16:43:14',
+						fstime: '2024-08-28 16:57:32',
+						jsr: '周小杰',
+						dxcpde: '',
+						name: '-25度冰箱',
+						fsnr: '广州海关基数中心-[-20度冰箱]报警;温度超过上限:-7.7℃',
+						type: '短信报警',
+						dx: '13578945780',
+						dh: '/',
+						wx: '/',
+						yj: '/',
+						zt: '发送成功',
+						gzyy: ''
+					},
+					{
+						sctime: '2024-08-28 18:21:33',
+						fstime: '2024-08-28 18:33:12',
+						jsr: '周小杰',
+						dxcpde: '',
+						name: '-26度冰箱',
+						fsnr: '广州海关基数中心-[-20度冰箱]报警;温度超过上限:-7.7℃',
+						type: '短信报警',
+						dx: '13578945780',
+						dh: '/',
+						wx: '/',
+						yj: '/',
+						zt: '发送成功',
+						gzyy: ''
+					}
+				],
+				size: 10,
+				total: 6
+			}
+			return obj
+		})
+	}
+	// 重置
+	const reset = () => {
+		searchFormRef.value.resetFields()
+		tableRef.value.refresh(true)
+	}
+</script>
+
+<style lang="less" scoped>
+	.table_item {
+		padding: 15px 20px;
+		.table-head {
+			width: 100%;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+
+			.head-left {
+				display: flex;
+			}
+
+			.ant-btn {
+				margin-left: 10px;
+			}
+		}
+	}
+	:deep(.ant-table-pagination-right) {
+		justify-content: center !important;
+	}
+</style>