Przeglądaj źródła

增加告警统计页面

yanglzh 7 miesięcy temu
rodzic
commit
c2c49ab137

+ 3 - 12
src/api/alarm/index.ts

@@ -23,22 +23,13 @@ export default {
     handle: (data: object) => post("/alarm/log/handle", data),
   },
   dashboard: {
-    getDeviceAlarmTop10: () => get("/alarm/log/getDeviceAlarmTop10"),
-    // 部门告警统计
-    getDeptAlarm: (params: object) => get("/alarm/log/getDeptAlarm", params),
-    // 今日告警信息
-    getCurrentDayInfo: () => get("/alarm/log/getCurrentDayInfo"),
-    // 最新告警
-    getAlarmNewList: () => get("/alarm/log/getAlarmNewList"),
-    // 告警统计
-    getAlarmStatistics: (params: object) => get("/alarm/log/getAlarmStatistics", params),
+    getAlarmLevel: (params: object) => get("/alarm/log/getAlarmLevel", params),
+    getTotalAlarmStatistics: () => get("/alarm/log/getTotalAlarmStatistics"),
     // 告警趋势统计
     getAnalyzeTrend: (params: object) => get("/alarm/log/getAnalyzeTrend", params),
     // 告警状态统计
     getAlarmStatus: (params: object) => get("/alarm/log/getAlarmStatus", params),
     // 告警类型统计
-    getAlarmType: (params: object) => get("/alarm/log/getAlarmType", params),
-    // 告警等级统计
-    getAlarmLevel: (params: object) => get("/alarm/log/getAlarmLevel", params),
+    getDeviceAlarmTop10: () => get("/alarm/log/getDeviceAlarmTop10"),
   },
 };

+ 1 - 1
src/utils/auth.ts

@@ -35,7 +35,7 @@ export function setSystemInfo(data: any) {
 }
 
 export function getSystemInfo() {
-  return JSON.parse(localStorage.sysinfo)
+  return JSON.parse(localStorage.sysinfo || '{}')
 }
 
 export function setTenantInfo(data?: any) {

+ 447 - 0
src/views/iot/alarm/dashboard/copy.vue

@@ -0,0 +1,447 @@
+<template>
+	<div class="page">
+		<div class="flex-row" style="gap: 12px">
+			<el-card shadow="nover">
+				<div class="title flex-row">
+					<div class="">
+						今日告警 <el-tag size="small">{{ todayCount.currentDayCount }}</el-tag>
+					</div>
+					<div>
+						本月告警 <el-tag size="small">{{ todayCount.currentMonthCount }}</el-tag>
+					</div>
+				</div>
+				<VueUiXy v-if="dataset?.length" :config="config" :dataset="dataset" />
+				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
+			</el-card>
+			<el-card shadow="nover">
+				<div class="title">告警设备top10</div>
+				<VueUiXy v-if="dataset2?.length" :config="config2" :dataset="dataset2" />
+				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
+			</el-card>
+			<el-card shadow="nover">
+				<div class="title">最新告警</div>
+				<el-table class="flex1" :data="alarmNewList" border style="width: 100%" size="small">
+					<el-table-column prop="createdAt" label="告警日期" width="140" align="center" />
+					<el-table-column prop="status" :formatter="(row:any) => (row.status ? '已处理' : '未处理')" label="告警状态" width="70" align="center" />
+					<el-table-column prop="level" label="告警等级" :formatter="(row:any) => typeFormat(row.level)" width="100" align="center" />
+					<el-table-column prop="ruleName" label="告警说明" show-overflow-tooltip aign="center" />
+				</el-table>
+			</el-card>
+		</div>
+		<div class="flex-row" style="gap: 12px">
+			<el-card shadow="nover">
+				<div class="title">
+					告警统计
+					<el-date-picker
+						v-model="dateRange"
+						type="daterange"
+						range-separator="至"
+						start-placeholder="开始日期"
+						end-placeholder="结束日期"
+						@change="getAlarmStatistics"
+						format="YYYY-MM-DD"
+						value-format="YYYY-MM-DD"
+						size="small"
+						style="max-width: 200px"
+						:clearable="false"
+						:disabledDate="disabledDate"
+					/>
+				</div>
+				<VueUiXy v-if="dataset4?.length" :config="config4" :dataset="dataset4" />
+				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
+			</el-card>
+			<el-card shadow="nover">
+				<div class="title">告警增长趋势</div>
+				<VueUiXy v-if="dataset5?.length" :config="config5" :dataset="dataset5" />
+				<VueUiSkeleton v-else :config="{ type: 'donut' }" />
+			</el-card>
+			<el-card shadow="nover">
+				<div class="title">
+					部门告警分析
+					<el-date-picker
+						v-model="deptAlarmDate"
+						type="daterange"
+						range-separator="至"
+						start-placeholder="开始日期"
+						end-placeholder="结束日期"
+						@change="getDeptAlarm"
+						format="YYYY-MM-DD"
+						value-format="YYYY-MM-DD"
+						size="small"
+						style="max-width: 200px"
+						:clearable="false"
+						:disabledDate="disabledDate"
+					/>
+				</div>
+				<VueUiXy v-if="dataset6?.length" :config="config6" :dataset="dataset6" />
+				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
+			</el-card>
+		</div>
+		<div class="flex-row" style="gap: 12px">
+			<el-card shadow="nover">
+				<div class="title">
+					告警状态
+					<el-date-picker
+						v-model="alarmStatusDate"
+						type="daterange"
+						range-separator="至"
+						start-placeholder="开始日期"
+						end-placeholder="结束日期"
+						@change="getAlarmStatus"
+						format="YYYY-MM-DD"
+						value-format="YYYY-MM-DD"
+						size="small"
+						style="max-width: 200px"
+						:clearable="false"
+						:disabledDate="disabledDate"
+					/>
+				</div>
+				<VueUiDonut v-if="dataset7?.length" :config="config7" :dataset="dataset7" />
+				<VueUiSkeleton v-else :config="{ type: 'donut' }" />
+			</el-card>
+			<el-card shadow="nover">
+				<div class="title">
+					告警等级
+					<el-date-picker
+						v-model="alarmLevelDate"
+						type="daterange"
+						range-separator="至"
+						start-placeholder="开始日期"
+						end-placeholder="结束日期"
+						format="YYYY-MM-DD"
+						value-format="YYYY-MM-DD"
+						@change="getAlarmLevel"
+						size="small"
+						style="max-width: 200px"
+						:clearable="false"
+						:disabledDate="disabledDate"
+					/>
+				</div>
+				<VueUiXy v-if="dataset9?.length" :config="config9" :dataset="dataset9" />
+				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
+			</el-card>
+			<el-card shadow="nover">
+				<div class="title">
+					告警类型
+					<el-date-picker
+						v-model="alarmTypeDate"
+						type="daterange"
+						range-separator="至"
+						start-placeholder="开始日期"
+						end-placeholder="结束日期"
+						format="YYYY-MM-DD"
+						value-format="YYYY-MM-DD"
+						@change="getAlarmType"
+						size="small"
+						style="max-width: 200px"
+						:clearable="false"
+						:disabledDate="disabledDate"
+					/>
+				</div>
+				<VueUiDonut v-if="dataset8?.length" :config="config8" :dataset="dataset8" />
+				<VueUiSkeleton v-else :config="{ type: 'donut' }" />
+			</el-card>
+		</div>
+	</div>
+</template>
+
+<script lang="ts" setup>
+import { unref, reactive, getCurrentInstance, ref } from 'vue'
+import { VueUiXy, VueUiDonut, VueUiSkeleton } from 'vue-data-ui'
+import 'vue-data-ui/style.css'
+import { getBarData, getPieSmallData } from '/@/utils/dataUiOptions'
+import api from '/@/api/alarm'
+import { useThemeChange } from '/@/hooks/useCommon'
+import dayjs from 'dayjs'
+
+const { proxy } = getCurrentInstance() as any
+const { alarm_type } = proxy.useDict('alarm_type')
+
+const disabledDate = (time: any) => time.getTime() > Date.now()
+
+function typeFormat(type: string) {
+	return proxy.selectDictLabel(unref(alarm_type), type)
+}
+
+const config = ref<any>({})
+const config2 = ref<any>({})
+const config4 = ref<any>({})
+const config5 = ref<any>({})
+const config6 = ref<any>({})
+const config7 = ref<any>({})
+const config8 = ref<any>({})
+const config9 = ref<any>({})
+const dataset = ref<any[]>([])
+const dataset2 = ref<any[]>([])
+const dataset4 = ref<any[]>([])
+const dataset5 = ref<any[]>([])
+const dataset6 = ref<any[]>([])
+const dataset7 = ref<any[]>([])
+const dataset8 = ref<any[]>([])
+const dataset9 = ref<any[]>([])
+
+// 监听暗黑模式变化,将 vue-data-ui 的 config 传进来,就能自动更新主题
+useThemeChange([config, config2, config4, config5, config6, config7, config8, config9])
+
+const todayCount = reactive({
+	currentDayCount: '-',
+	currentMonthCount: '-',
+})
+
+const alarmNewList = ref<any[]>([])
+
+const defaultDateRange = [dayjs().subtract(7, 'day').format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')]
+const dateRange = ref([...defaultDateRange])
+const analyzeTrendDate = ref(dayjs().format('YYYY-MM'))
+const deptAlarmDate = ref([...defaultDateRange])
+const alarmStatusDate = ref([...defaultDateRange])
+const alarmTypeDate = ref([...defaultDateRange])
+const alarmLevelDate = ref([...defaultDateRange])
+
+getData()
+
+function getData() {
+	// 今日告警信息
+	api.dashboard.getCurrentDayInfo().then((res: any) => {
+		const list = res?.data.alarmList || []
+		todayCount.currentDayCount = res?.data?.currentDayCount
+		todayCount.currentMonthCount = res?.data?.currentMonthCount
+
+		const chartData = getBarData({
+			xAxis: list.map((item: any) => item.alarmDate),
+			legend: ['今日告警'],
+			datas: [list.map((item: any) => item.alarmCount)],
+			width: 300,
+			height: 300,
+			colors: ['#4B79F2'],
+			modulo: 3,
+			responsive: true,
+		})
+		config.value = chartData.config
+		dataset.value = chartData.dataset
+	})
+	// 最新告警
+	api.dashboard.getAlarmNewList().then((res: any) => {
+		alarmNewList.value = res || []
+	})
+	// 告警统计
+	getAlarmStatistics()
+	// 告警趋势统计
+	getAnalyzeTrend()
+	// 部门告警统计
+	getDeptAlarm()
+	// 告警状态统计
+	getAlarmStatus()
+	// 告警类型统计
+	getAlarmType()
+	// 告警等级统计
+	getAlarmLevel()
+	// 告警设备top10
+	api.dashboard.getDeviceAlarmTop10().then((res: any) => {
+		const list = res || []
+		const chartData = getBarData({
+			xAxis: list.map((item: any) => item.deviceName),
+			legend: ['告警设备top10'],
+			datas: [list.map((item: any) => item.alarmCount)],
+			colors: ['#FF7D5C'],
+			responsive: true,
+		})
+		config2.value = chartData.config
+		dataset2.value = chartData.dataset
+	})
+}
+
+function getAlarmStatistics() {
+	api.dashboard
+		.getAlarmStatistics({
+			startDate: dateRange.value[0],
+			endDate: dateRange.value[1],
+		})
+		.then((res: any) => {
+			const list = res || []
+			const chartData = getBarData({
+				xAxis: list.map((item: any) => item.alarmDate),
+				legend: ['告警统计'],
+				datas: [list.map((item: any) => item.alarmCount || 0)],
+				modulo: 3,
+				colors: ['#5AD8A6'],
+				responsive: true,
+			})
+			config4.value = chartData.config
+			dataset4.value = chartData.dataset
+		})
+}
+
+function getAnalyzeTrend() {
+	api.dashboard
+		.getAnalyzeTrend({
+			searchMonth: analyzeTrendDate.value,
+		})
+		.then((res: any) => {
+			const list = res || []
+			const chartData = getBarData({
+				xAxis: list.map((item: any) => item.month),
+				legend: ['部门告警'],
+				datas: [list.map((item: any) => item.alarmCount)],
+				modulo: 5,
+				colors: ['#FFB64D'],
+				responsive: true,
+			})
+			config5.value = chartData.config
+			dataset5.value = chartData.dataset
+		})
+}
+
+function getDeptAlarm() {
+	api.dashboard
+		.getDeptAlarm({
+			startDate: deptAlarmDate.value[0],
+			endDate: deptAlarmDate.value[1],
+		})
+		.then((res: any) => {
+			const list = res || []
+			const chartData = getBarData({
+				xAxis: list.map((item: any) => item.deptName),
+				legend: ['部门告警'],
+				datas: [list.map((item: any) => item.alarmCount)],
+				modulo: 5,
+				colors: ['#5B8FF9'],
+				responsive: true,
+			})
+			config6.value = chartData.config
+			dataset6.value = chartData.dataset
+		})
+}
+
+function getAlarmStatus() {
+	api.dashboard
+		.getAlarmStatus({
+			startDate: alarmStatusDate.value[0],
+			endDate: alarmStatusDate.value[1],
+		})
+		.then((res: any) => {
+			const list = res || []
+			const chartData = getPieSmallData({
+				legend: list.map((item: any) => (item.status === '1' ? '已处理' : '未处理')),
+				datas: list.map((item: any) => [item.alarmCount]),
+				colors: ['#5AD8A6', '#E86452'],
+				responsive: true,
+			})
+			config7.value = chartData.config
+			dataset7.value = chartData.dataset
+		})
+}
+
+function getAlarmType() {
+	api.dashboard
+		.getAlarmType({
+			startDate: alarmTypeDate.value[0],
+			endDate: alarmTypeDate.value[1],
+		})
+		.then((res: any) => {
+			const list = res || []
+			const chartData = getPieSmallData({
+				legend: list.map((item: any) => (item.alarmType === '1' ? '规则告警' : '自助上报告警')),
+				datas: list.map((item: any) => [item.alarmCount]),
+				colors: ['#7453E5', '#FFB64D'],
+				responsive: true,
+			})
+			config8.value = chartData.config
+			dataset8.value = chartData.dataset
+		})
+}
+
+function getAlarmLevel() {
+	api.dashboard
+		.getAlarmLevel({
+			startDate: alarmLevelDate.value[0],
+			endDate: alarmLevelDate.value[1],
+		})
+		.then((res: any) => {
+			const list = res || []
+			const chartData = getBarData({
+				xAxis: list.map((item: any) => item.levelName),
+				legend: ['告警等级'],
+				datas: [list.map((item: any) => item.alarmCount)],
+				modulo: 3,
+				colors: ['#269A99'],
+				responsive: true,
+			})
+			config9.value = chartData.config
+			dataset9.value = chartData.dataset
+		})
+}
+</script>
+
+<style scoped lang="scss">
+.page {
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	gap: 12px;
+
+	.vue-ui-skeleton {
+		height: 100%;
+
+		& ::v-deep > svg {
+			height: 100%;
+		}
+	}
+
+	.title {
+		font-size: 14px;
+		color: #333;
+		font-weight: 500;
+		line-height: 1;
+		height: 24px;
+		min-height: 24px;
+		margin-bottom: 6px;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+	}
+
+	.flex-row {
+		flex: 1;
+
+		.el-card {
+			height: 100%;
+			flex: 1;
+			// overflow: hidden;
+			box-sizing: border-box;
+
+			& ::v-deep .el-card__body {
+				padding: 1.5vh 1vw;
+				// gap: 10px;
+				height: 100%;
+				display: flex;
+				flex-direction: column;
+				justify-content: space-between;
+				// overflow: hidden;
+
+				.vue-ui-xy,
+				.vue-ui-donut,
+				.vue-ui-skeleton {
+					// flex: 1 !important;
+					height: calc(100% - 30px) !important;
+					// overflow: auto;
+					// display: flex;
+					// flex-direction: column;
+					// justify-content: center;
+					// align-items: center;
+					&-svg {
+						height: 100%;
+					}
+					.vue-data-ui-fulscreen--off {
+						height: 100%;
+					}
+				}
+
+				.vue-ui-skeleton {
+					overflow: hidden;
+				}
+			}
+		}
+	}
+}
+</style>

+ 403 - 388
src/views/iot/alarm/dashboard/index.vue

@@ -1,447 +1,462 @@
 <template>
-	<div class="page">
-		<div class="flex-row" style="gap: 12px">
-			<el-card shadow="nover">
-				<div class="title flex-row">
-					<div class="">
-						今日告警 <el-tag size="small">{{ todayCount.currentDayCount }}</el-tag>
-					</div>
-					<div>
-						本月告警 <el-tag size="small">{{ todayCount.currentMonthCount }}</el-tag>
+	<div class="home-container">
+		<el-row :gutter="15" class="home-card-one mb15">
+			<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6" v-for="(v, k) in homeOne" :key="k">
+				<div class="home-card-top-part">
+					<div class="top">
+						<img :src="'/imgs/' + v.icoimg" class="icoimg" />
+						<div class="card-right">
+							<span class="font30">{{ v.allnum }}</span>
+							<div class="label">{{ v.num3 }}</div>
+						</div>
 					</div>
 				</div>
-				<VueUiXy v-if="dataset?.length" :config="config" :dataset="dataset" />
-				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
-			</el-card>
-			<el-card shadow="nover">
-				<div class="title">告警设备top10</div>
-				<VueUiXy v-if="dataset2?.length" :config="config2" :dataset="dataset2" />
-				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
-			</el-card>
-			<el-card shadow="nover">
-				<div class="title">最新告警</div>
-				<el-table class="flex1" :data="alarmNewList" border style="width: 100%" size="small">
-					<el-table-column prop="createdAt" label="告警日期" width="140" align="center" />
-					<el-table-column prop="status" :formatter="(row:any) => (row.status ? '已处理' : '未处理')" label="告警状态" width="70" align="center" />
-					<el-table-column prop="level" label="告警等级" :formatter="(row:any) => typeFormat(row.level)" width="100" align="center" />
-					<el-table-column prop="ruleName" label="告警说明" show-overflow-tooltip aign="center" />
-				</el-table>
-			</el-card>
+			</el-col>
+		</el-row>
+		<div class="chart-wrapper">
+			<div class="chart-item" style="flex: 1">
+				<div class="chart-title">告警级别分布</div>
+				<Chart height="300px" ref="chart1"></Chart>
+			</div>
+			<div class="chart-item" style="flex: 1.5">
+				<div class="chart-title">告警趋势</div>
+				<Chart height="300px" ref="chart2"></Chart>
+			</div>
 		</div>
-		<div class="flex-row" style="gap: 12px">
-			<el-card shadow="nover">
-				<div class="title">
-					告警统计
-					<el-date-picker
-						v-model="dateRange"
-						type="daterange"
-						range-separator="至"
-						start-placeholder="开始日期"
-						end-placeholder="结束日期"
-						@change="getAlarmStatistics"
-						format="YYYY-MM-DD"
-						value-format="YYYY-MM-DD"
-						size="small"
-						style="max-width: 200px"
-						:clearable="false"
-						:disabledDate="disabledDate"
-					/>
-				</div>
-				<VueUiXy v-if="dataset4?.length" :config="config4" :dataset="dataset4" />
-				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
-			</el-card>
-			<el-card shadow="nover">
-				<div class="title">告警增长趋势</div>
-				<VueUiXy v-if="dataset5?.length" :config="config5" :dataset="dataset5" />
-				<VueUiSkeleton v-else :config="{ type: 'donut' }" />
-			</el-card>
-			<el-card shadow="nover">
-				<div class="title">
-					部门告警分析
-					<el-date-picker
-						v-model="deptAlarmDate"
-						type="daterange"
-						range-separator="至"
-						start-placeholder="开始日期"
-						end-placeholder="结束日期"
-						@change="getDeptAlarm"
-						format="YYYY-MM-DD"
-						value-format="YYYY-MM-DD"
-						size="small"
-						style="max-width: 200px"
-						:clearable="false"
-						:disabledDate="disabledDate"
-					/>
-				</div>
-				<VueUiXy v-if="dataset6?.length" :config="config6" :dataset="dataset6" />
-				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
-			</el-card>
-		</div>
-		<div class="flex-row" style="gap: 12px">
-			<el-card shadow="nover">
-				<div class="title">
-					告警状态
-					<el-date-picker
-						v-model="alarmStatusDate"
-						type="daterange"
-						range-separator="至"
-						start-placeholder="开始日期"
-						end-placeholder="结束日期"
-						@change="getAlarmStatus"
-						format="YYYY-MM-DD"
-						value-format="YYYY-MM-DD"
-						size="small"
-						style="max-width: 200px"
-						:clearable="false"
-						:disabledDate="disabledDate"
-					/>
-				</div>
-				<VueUiDonut v-if="dataset7?.length" :config="config7" :dataset="dataset7" />
-				<VueUiSkeleton v-else :config="{ type: 'donut' }" />
-			</el-card>
-			<el-card shadow="nover">
-				<div class="title">
-					告警等级
-					<el-date-picker
-						v-model="alarmLevelDate"
-						type="daterange"
-						range-separator="至"
-						start-placeholder="开始日期"
-						end-placeholder="结束日期"
-						format="YYYY-MM-DD"
-						value-format="YYYY-MM-DD"
-						@change="getAlarmLevel"
-						size="small"
-						style="max-width: 200px"
-						:clearable="false"
-						:disabledDate="disabledDate"
-					/>
-				</div>
-				<VueUiXy v-if="dataset9?.length" :config="config9" :dataset="dataset9" />
-				<VueUiSkeleton v-else :config="{ type: 'bar' }" />
-			</el-card>
-			<el-card shadow="nover">
-				<div class="title">
-					告警类型
-					<el-date-picker
-						v-model="alarmTypeDate"
-						type="daterange"
-						range-separator="至"
-						start-placeholder="开始日期"
-						end-placeholder="结束日期"
-						format="YYYY-MM-DD"
-						value-format="YYYY-MM-DD"
-						@change="getAlarmType"
-						size="small"
-						style="max-width: 200px"
-						:clearable="false"
-						:disabledDate="disabledDate"
-					/>
-				</div>
-				<VueUiDonut v-if="dataset8?.length" :config="config8" :dataset="dataset8" />
-				<VueUiSkeleton v-else :config="{ type: 'donut' }" />
-			</el-card>
+		<div class="chart-wrapper">
+			<div class="chart-item" style="flex: 1">
+				<div class="chart-title">处理状态</div>
+				<Chart height="300px" ref="chart3"></Chart>
+			</div>
+			<div class="chart-item" style="flex: 1.5">
+				<div class="chart-title">设备告警TOP10</div>
+				<Chart height="300px" ref="chart4"></Chart>
+			</div>
 		</div>
+		<AlarmList></AlarmList>
 	</div>
 </template>
 
 <script lang="ts" setup>
-import { unref, reactive, getCurrentInstance, ref } from 'vue'
-import { VueUiXy, VueUiDonut, VueUiSkeleton } from 'vue-data-ui'
+import { toRefs, reactive, onMounted, ref, watch, nextTick, onActivated, getCurrentInstance, onUnmounted } from 'vue'
 import 'vue-data-ui/style.css'
-import { getBarData, getPieSmallData } from '/@/utils/dataUiOptions'
 import api from '/@/api/alarm'
+import AlarmList from '/@/views/iot/alarm/list/index.vue'
 import { useThemeChange } from '/@/hooks/useCommon'
+import Chart from '/@/components/chart/index.vue'
+import { getLineOption } from '/@/components/chart/options'
 import dayjs from 'dayjs'
 
+const chart1 = ref()
+const chart2 = ref()
+const chart3 = ref()
+const chart4 = ref()
+
 const { proxy } = getCurrentInstance() as any
 const { alarm_type } = proxy.useDict('alarm_type')
+const alarmTypeMap: any = {}
 
-const disabledDate = (time: any) => time.getTime() > Date.now()
-
-function typeFormat(type: string) {
-	return proxy.selectDictLabel(unref(alarm_type), type)
-}
-
-const config = ref<any>({})
-const config2 = ref<any>({})
-const config4 = ref<any>({})
-const config5 = ref<any>({})
-const config6 = ref<any>({})
-const config7 = ref<any>({})
-const config8 = ref<any>({})
-const config9 = ref<any>({})
-const dataset = ref<any[]>([])
-const dataset2 = ref<any[]>([])
-const dataset4 = ref<any[]>([])
-const dataset5 = ref<any[]>([])
-const dataset6 = ref<any[]>([])
-const dataset7 = ref<any[]>([])
-const dataset8 = ref<any[]>([])
-const dataset9 = ref<any[]>([])
-
-// 监听暗黑模式变化,将 vue-data-ui 的 config 传进来,就能自动更新主题
-useThemeChange([config, config2, config4, config5, config6, config7, config8, config9])
-
-const todayCount = reactive({
-	currentDayCount: '-',
-	currentMonthCount: '-',
-})
-
-const alarmNewList = ref<any[]>([])
-
-const defaultDateRange = [dayjs().subtract(7, 'day').format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')]
-const dateRange = ref([...defaultDateRange])
-const analyzeTrendDate = ref(dayjs().format('YYYY-MM'))
-const deptAlarmDate = ref([...defaultDateRange])
-const alarmStatusDate = ref([...defaultDateRange])
-const alarmTypeDate = ref([...defaultDateRange])
-const alarmLevelDate = ref([...defaultDateRange])
-
-getData()
-
-function getData() {
-	// 今日告警信息
-	api.dashboard.getCurrentDayInfo().then((res: any) => {
-		const list = res?.data.alarmList || []
-		todayCount.currentDayCount = res?.data?.currentDayCount
-		todayCount.currentMonthCount = res?.data?.currentMonthCount
-
-		const chartData = getBarData({
-			xAxis: list.map((item: any) => item.alarmDate),
-			legend: ['今日告警'],
-			datas: [list.map((item: any) => item.alarmCount)],
-			width: 300,
-			height: 300,
-			colors: ['#4B79F2'],
-			modulo: 3,
-			responsive: true,
-		})
-		config.value = chartData.config
-		dataset.value = chartData.dataset
-	})
-	// 最新告警
-	api.dashboard.getAlarmNewList().then((res: any) => {
-		alarmNewList.value = res || []
-	})
-	// 告警统计
-	getAlarmStatistics()
-	// 告警趋势统计
-	getAnalyzeTrend()
-	// 部门告警统计
-	getDeptAlarm()
-	// 告警状态统计
-	getAlarmStatus()
-	// 告警类型统计
-	getAlarmType()
-	// 告警等级统计
-	getAlarmLevel()
-	// 告警设备top10
-	api.dashboard.getDeviceAlarmTop10().then((res: any) => {
-		const list = res || []
-		const chartData = getBarData({
-			xAxis: list.map((item: any) => item.deviceName),
-			legend: ['告警设备top10'],
-			datas: [list.map((item: any) => item.alarmCount)],
-			colors: ['#FF7D5C'],
-			responsive: true,
-		})
-		config2.value = chartData.config
-		dataset2.value = chartData.dataset
-	})
-}
-
-function getAlarmStatistics() {
-	api.dashboard
-		.getAlarmStatistics({
-			startDate: dateRange.value[0],
-			endDate: dateRange.value[1],
+// 监听告警类型是否获取成功
+watch(
+	() => alarm_type.value,
+	(list) => {
+		if (!list.length) return
+		list.forEach((item: any) => {
+			alarmTypeMap[item.value] = item.label
 		})
-		.then((res: any) => {
-			const list = res || []
-			const chartData = getBarData({
-				xAxis: list.map((item: any) => item.alarmDate),
-				legend: ['告警统计'],
-				datas: [list.map((item: any) => item.alarmCount || 0)],
-				modulo: 3,
-				colors: ['#5AD8A6'],
-				responsive: true,
-			})
-			config4.value = chartData.config
-			dataset4.value = chartData.dataset
-		})
-}
+	},
+	{
+		immediate: true,
+	}
+)
 
-function getAnalyzeTrend() {
-	api.dashboard
-		.getAnalyzeTrend({
-			searchMonth: analyzeTrendDate.value,
-		})
-		.then((res: any) => {
-			const list = res || []
-			const chartData = getBarData({
-				xAxis: list.map((item: any) => item.month),
-				legend: ['部门告警'],
-				datas: [list.map((item: any) => item.alarmCount)],
-				modulo: 5,
-				colors: ['#FFB64D'],
-				responsive: true,
-			})
-			config5.value = chartData.config
-			dataset5.value = chartData.dataset
-		})
-}
+const homeOne = reactive([
+	{
+		allnum: 0,
+		num3: '告警总数',
+		icoimg: 'dashboard-icon1.svg',
+	},
+	{
+		allnum: 0,
+		num3: '已关闭告警数',
+		icoimg: 'dashboard-icon2.svg',
+	},
+	{
+		allnum: 0,
+		num3: '未关闭告警数',
+		icoimg: 'dashboard-icon3.svg',
+	},
+	{
+		allnum: 0,
+		num3: '平均处理时长MTTR',
+		icoimg: 'dashboard-icon4.svg',
+	},
+])
 
-function getDeptAlarm() {
+const getOverviewData = () => {
+	// 顶部统计数据
+	api.dashboard.getTotalAlarmStatistics().then((res: any) => {
+		homeOne[0].allnum = res.alarmTotalCount
+		homeOne[1].allnum = res.closeAlarmCount
+		homeOne[2].allnum = res.unCloseAlarmCount
+		homeOne[3].allnum = res.averageDealTime
+	})
+	// 告警级别分布
 	api.dashboard
-		.getDeptAlarm({
-			startDate: deptAlarmDate.value[0],
-			endDate: deptAlarmDate.value[1],
+		.getAlarmLevel({
+			searchType: null,
+			startDate: dayjs().startOf('month').format('YYYY-MM-DD'),
+			endDate: dayjs().endOf('month').format('YYYY-MM-DD'),
 		})
 		.then((res: any) => {
-			const list = res || []
-			const chartData = getBarData({
-				xAxis: list.map((item: any) => item.deptName),
-				legend: ['部门告警'],
-				datas: [list.map((item: any) => item.alarmCount)],
-				modulo: 5,
-				colors: ['#5B8FF9'],
-				responsive: true,
-			})
-			config6.value = chartData.config
-			dataset6.value = chartData.dataset
+			const resData = res || [
+				{
+					alarmCount: 2548,
+					alarmLevel: '1',
+					levelName: '超紧急',
+				},
+				{
+					alarmCount: 0,
+					alarmLevel: '2',
+					levelName: '紧急',
+				},
+				{
+					alarmCount: 0,
+					alarmLevel: '3',
+					levelName: '严重',
+				},
+				{
+					alarmCount: 0,
+					alarmLevel: '4',
+					levelName: '一般',
+				},
+				{
+					alarmCount: 0,
+					alarmLevel: '5',
+					levelName: '提醒',
+				},
+			]
+			console.log(resData)
 		})
-}
-
-function getAlarmStatus() {
+	// 告警趋势 intervalType 统计间隔:1小时 2天 3月
+	api.dashboard.getAnalyzeTrend({ intervalType: 2 }).then((res: any) => {
+		const resData = res || []
+		console.log(resData)
+	})
+	// 处理状态
 	api.dashboard
 		.getAlarmStatus({
-			startDate: alarmStatusDate.value[0],
-			endDate: alarmStatusDate.value[1],
+			startDate: dayjs().startOf('month').format('YYYY-MM-DD'),
+			endDate: dayjs().endOf('month').format('YYYY-MM-DD'),
 		})
 		.then((res: any) => {
-			const list = res || []
-			const chartData = getPieSmallData({
-				legend: list.map((item: any) => (item.status === '1' ? '已处理' : '未处理')),
-				datas: list.map((item: any) => [item.alarmCount]),
-				colors: ['#5AD8A6', '#E86452'],
-				responsive: true,
-			})
-			config7.value = chartData.config
-			dataset7.value = chartData.dataset
+			const resData = res || [
+				{
+					alarmCount: 4,
+					status: '1',
+				},
+				{
+					alarmCount: 2544,
+					status: '0',
+				},
+				{
+					alarmCount: 0,
+					status: '2',
+				},
+			]
+			console.log(resData)
 		})
-}
-
-function getAlarmType() {
-	api.dashboard
-		.getAlarmType({
-			startDate: alarmTypeDate.value[0],
-			endDate: alarmTypeDate.value[1],
-		})
-		.then((res: any) => {
-			const list = res || []
-			const chartData = getPieSmallData({
-				legend: list.map((item: any) => (item.alarmType === '1' ? '规则告警' : '自助上报告警')),
-				datas: list.map((item: any) => [item.alarmCount]),
-				colors: ['#7453E5', '#FFB64D'],
-				responsive: true,
-			})
-			config8.value = chartData.config
-			dataset8.value = chartData.dataset
+	api.dashboard.getDeviceAlarmTop10().then((res: any) => {
+		const list = res || []
+		const chartData = getLineOption({
+			datas: [list.map((item: any) => item.alarmCount)],
+			xAxis: list.map((item: any) => item.deviceName),
+			legend: ['告警设备top10'],
 		})
+		chart4.value.draw(chartData)
+	})
 }
 
-function getAlarmLevel() {
-	api.dashboard
-		.getAlarmLevel({
-			startDate: alarmLevelDate.value[0],
-			endDate: alarmLevelDate.value[1],
-		})
-		.then((res: any) => {
-			const list = res || []
-			const chartData = getBarData({
-				xAxis: list.map((item: any) => item.levelName),
-				legend: ['告警等级'],
-				datas: [list.map((item: any) => item.alarmCount)],
-				modulo: 3,
-				colors: ['#269A99'],
-				responsive: true,
-			})
-			config9.value = chartData.config
-			dataset9.value = chartData.dataset
-		})
-}
+// 页面加载时
+onMounted(() => {
+	getOverviewData()
+})
 </script>
 
 <style scoped lang="scss">
-.page {
+$homeNavLengh: 8;
+
+.chart-wrapper {
 	display: flex;
-	flex-direction: column;
 	justify-content: space-between;
-	gap: 12px;
+	align-items: stretch;
+	gap: 16px;
 
-	.vue-ui-skeleton {
-		height: 100%;
+	.chart-item {
+		background-color: var(--el-color-white);
+		padding: 12px 15px;
+		border-radius: 8px;
+		margin-bottom: 16px;
+		flex: 1;
+		min-width: 200px;
+	}
 
-		& ::v-deep > svg {
-			height: 100%;
-		}
+	.chart-title {
+		font-size: 15px;
+		font-weight: bold;
+		padding-left: 5px;
 	}
+}
+
+.home-card-top-part {
+	background-color: var(--el-color-white);
+	border-radius: 8px;
+	padding: 20px 20px;
 
-	.title {
+	.top {
+		display: flex;
+		justify-content: space-around;
+		overflow: hidden;
+		align-items: center;
+	}
+
+	.icoimg {
+		width: 54px !important;
+		height: 54px !important;
+		margin-right: 12px;
+	}
+
+	.label {
 		font-size: 14px;
-		color: #333;
 		font-weight: 500;
+	}
+
+	.divider {
+		border-top: 1px solid var(--el-border-color-light);
+		margin: 12px 0 15px;
+	}
+
+	.card-right {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		white-space: nowrap;
 		line-height: 1;
-		height: 24px;
-		min-height: 24px;
-		margin-bottom: 6px;
+		height: 54px;
+
+		.font30 {
+			color: #4285f4;
+			font-weight: bold;
+			font-size: 30px;
+		}
+	}
+
+	.card-bottom {
+		font-size: 12px;
 		display: flex;
 		align-items: center;
-		justify-content: space-between;
+		justify-content: space-around;
+		gap: 12px;
+		white-space: nowrap;
+
+		.split {
+			border-right: 1px solid var(--el-border-color-light);
+			height: 20px;
+		}
+
+		.icon {
+			width: 17px;
+			height: 17px;
+		}
+
+		.info {
+			font-size: 12px;
+			font-weight: 500;
+		}
 	}
+}
 
-	.flex-row {
-		flex: 1;
+.home-container {
+	overflow: hidden;
 
-		.el-card {
-			height: 100%;
-			flex: 1;
-			// overflow: hidden;
-			box-sizing: border-box;
+	.home-card-one,
+	.home-card-two,
+	.home-card-three {
+		.icoimg {
+			width: 75px;
+			height: 75px;
+		}
+
+		.title_status {
+			width: 7px;
+			height: 7px;
+			background: #c1bbbb;
+			border-radius: 50px;
+			margin-right: 5px;
+		}
+
+		.home-card-item,
+		.home-card-top {
+			width: 100%;
+			border-radius: 8px;
+			transition: all ease 0.3s;
+			padding: 10px 20px;
+			overflow: hidden;
+			background: var(--el-color-white);
+			color: var(--el-text-color-primary);
+
+			// border: 1px solid var(--next-border-color-light);
+			&:hover {
+				// box-shadow: 0 2px 12px var(--next-color-dark-hover);
+				transition: all ease 0.3s;
+			}
+
+			&-icon {
+				width: 70px;
+				height: 70px;
+				border-radius: 100%;
+				flex-shrink: 1;
+
+				i {
+					color: var(--el-text-color-placeholder);
+				}
+			}
 
-			& ::v-deep .el-card__body {
-				padding: 1.5vh 1vw;
-				// gap: 10px;
+			&-title {
+				font-size: 15px;
+				font-weight: bold;
+				height: 30px;
+			}
+		}
+	}
+
+	.home-card-three {
+		.home-card-item-title {
+			display: flex;
+			justify-content: space-between;
+			// span:nth-child(2) {
+			// 	color: #409eff;
+			// }
+		}
+	}
+
+	.home-card-one {
+		@for $i from 0 through 3 {
+			.home-one-animation#{$i} {
+				opacity: 0;
+				animation-name: error-num;
+				animation-duration: 0.5s;
+				animation-fill-mode: forwards;
+				animation-delay: calc($i/10) + s;
+			}
+		}
+	}
+
+	.home-card-two,
+	.home-card-three {
+		.home-card-top {
+			height: 250px;
+
+			.box-card {
+				padding: 15px 20px 20px 10px;
+
+				p {
+					margin-bottom: 10px;
+				}
+
+				&-item {
+					margin-bottom: 10px;
+				}
+			}
+		}
+
+		.home-card-item,
+		.home-card-top {
+			width: 100%;
+			overflow: hidden;
+
+			.home-monitor {
 				height: 100%;
-				display: flex;
-				flex-direction: column;
-				justify-content: space-between;
-				// overflow: hidden;
-
-				.vue-ui-xy,
-				.vue-ui-donut,
-				.vue-ui-skeleton {
-					// flex: 1 !important;
-					height: calc(100% - 30px) !important;
-					// overflow: auto;
-					// display: flex;
-					// flex-direction: column;
-					// justify-content: center;
-					// align-items: center;
-					&-svg {
-						height: 100%;
-					}
-					.vue-data-ui-fulscreen--off {
-						height: 100%;
+
+				.flex-warp-item {
+					width: 25%;
+					height: 111px;
+					display: flex;
+
+					.flex-warp-item-box {
+						margin: auto;
+						text-align: center;
+						color: var(--el-text-color-primary);
+						display: flex;
+						border-radius: 5px;
+						background: var(--next-bg-color);
+						cursor: pointer;
+						transition: all 0.3s ease;
+
+						&:hover {
+							background: var(--el-color-primary-light-9);
+							transition: all 0.3s ease;
+						}
 					}
-				}
 
-				.vue-ui-skeleton {
-					overflow: hidden;
+					@for $i from 0 through $homeNavLengh {
+						.home-animation#{$i} {
+							opacity: 0;
+							animation-name: error-num;
+							animation-duration: 0.5s;
+							animation-fill-mode: forwards;
+							animation-delay: calc($i/10) + s;
+						}
+					}
 				}
 			}
 		}
 	}
+
+	.text-info {
+		color: #23c6c8;
+	}
+
+	.text-danger {
+		color: #ed5565;
+	}
+
+	.git-res {
+		margin-top: 20px;
+	}
+
+	.git-res .el-link {
+		margin-right: 30px;
+	}
+
+	ul,
+	li {
+		padding: 0;
+		margin: 0;
+		list-style: none;
+	}
+
+	.product {
+		margin-top: 50px;
+
+		h3 {
+			margin-bottom: 15px;
+		}
+	}
+
+	.product li {
+		margin-bottom: 20px;
+		float: left;
+		width: 150px;
+	}
+
+	.box-card.xx {
+		margin-top: 20px;
+	}
+}
+
+.home-card-item.chart {
+	padding: 10px !important;
 }
 </style>

+ 1 - 1
src/views/iot/noticeservices/log/index.vue

@@ -2,7 +2,7 @@
 	<div class="page">
 		<el-card shadow="nover">
 			<el-form :model="tableData.param" ref="queryRef" inline label-width="68px">
-				<el-form-item label="创建时间" prop="dateRange">
+				<el-form-item label="发送时间" prop="dateRange">
 					<el-date-picker v-model="tableData.param.dateRange" style="width: 240px" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
 				</el-form-item>
 				<el-form-item>