dashboard.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. <template>
  2. <div class="home-container">
  3. <el-row :gutter="15" class="home-card-one mb15">
  4. <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6" v-for="(v, k) in homeOne" :key="k" :class="{ 'home-media home-media-lg': k > 1, 'home-media-sm': k === 1 }">
  5. <div class="home-card-top-part">
  6. <div class="top">
  7. <img :src="'/imgs/' + v.icoimg" class="icoimg">
  8. <div class="card-right">
  9. <span class="font30">{{ v.allnum }}</span>
  10. <div class="label">{{ v.num3 }}</div>
  11. </div>
  12. </div>
  13. <div class="divider"></div>
  14. <div class="card-bottom">
  15. <div class="flex" style="gap:10px">
  16. <img src="/@/assets/ok.svg" v-if="k < 2" alt="" class="icon">
  17. <img src="/@/assets/date.svg" v-else alt="" class="icon">
  18. <span class="info" :style="{ color: v.title1_bgcolor }">{{ v.title1 }}</span>
  19. <div class="num"> {{ v.num1 }}</div>
  20. </div>
  21. <div class="split"></div>
  22. <div class="flex" style="gap:10px">
  23. <img src="/@/assets/stop.svg" v-if="k < 2" alt="" class="icon">
  24. <img src="/@/assets/today.svg" v-else alt="" class="icon">
  25. <span class="info" :style="{ color: v.title2_bgcolor }">{{ v.title2 }}</span>
  26. <div class="num"> {{ v.num2 }}</div>
  27. </div>
  28. </div>
  29. </div>
  30. </el-col>
  31. </el-row>
  32. <el-row :gutter="15" class="home-card-two mb15">
  33. <el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16">
  34. <div class="home-card-item chart">
  35. <div style="height: 100%" ref="homeLineRef"></div>
  36. </div>
  37. </el-col>
  38. <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8" class="home-media">
  39. <div class="home-card-item chart">
  40. <div style="height: 100%" ref="homePieRef"></div>
  41. </div>
  42. </el-col>
  43. </el-row>
  44. <el-row :gutter="15" class="home-card-three">
  45. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  46. <div class="home-card-item" style="height: auto;">
  47. <div class="home-card-item-title">
  48. <span>告警信息列表</span>
  49. <el-button size="small" text type="primary" @click="toMore()">更多信息</el-button>
  50. </div>
  51. <el-table :data="tableData.data" style="width: 100%" v-loading="loading">
  52. <el-table-column label="ID" align="center" prop="id" width="100" v-col="'ID'" />
  53. <el-table-column label="告警类型" width="120" prop="type" align="center" show-overflow-tooltip v-col="'type'">
  54. <template #default="scope">
  55. <span v-if="scope.row.type == 1">规则告警</span>
  56. <span v-else>设备自主告警</span>
  57. </template>
  58. </el-table-column>
  59. <el-table-column label="规则级别" width="120" align="center" prop="alarmLevel.name" show-overflow-tooltip v-col="'alarmLevel'" />
  60. <el-table-column label="规则名称" prop="ruleName" show-overflow-tooltip v-col="'ruleName'" />
  61. <el-table-column label="产品标识" prop="productKey" show-overflow-tooltip v-col="'productKey'" />
  62. <el-table-column label="设备标识" prop="deviceKey" show-overflow-tooltip v-col="'deviceKey'" />
  63. <el-table-column prop="status" label="告警状态" width="100" align="center" v-col="'status'">
  64. <template #default="scope">
  65. <el-tag type="success" size="small" v-if="scope.row.status">已处理</el-tag>
  66. <el-tag type="info" size="small" v-else>未处理</el-tag>
  67. </template>
  68. </el-table-column>
  69. <el-table-column prop="createdAt" label="告警时间" align="center" width="170" v-col="'createdAt'"></el-table-column>
  70. <el-table-column label="操作" width="130" align="center" fixed="right" v-col="'handle'">
  71. <template #default="scope">
  72. <el-button v-auth="'detail'" size="small" text type="primary" @click="onOpenDetailDic(scope.row)">详情</el-button>
  73. <el-button v-auth="'edit'" size="small" text type="warning" @click="onOpenEditDic(scope.row)" v-if="scope.row.status == 0">处理</el-button>
  74. </template>
  75. </el-table-column>
  76. </el-table>
  77. </div>
  78. </el-col>
  79. </el-row>
  80. <EditDic ref="editDicRef" @dataList="getAlarmList" />
  81. <DetailDic ref="detailRef" @dataList="getAlarmList" />
  82. </div>
  83. </template>
  84. <script lang="ts">
  85. import { toRefs, reactive, defineComponent, onMounted, ref, watch, nextTick, onActivated, getCurrentInstance, onUnmounted } from 'vue';
  86. import * as echarts from 'echarts';
  87. import { useRouter, useRoute } from 'vue-router';
  88. import { useStore } from '/@/store/index';
  89. import api from '/@/api/datahub';
  90. import dayjs from 'dayjs';
  91. import EditDic from '../alarm/log/component/edit.vue';
  92. import DetailDic from '../alarm/log/component/detail.vue';
  93. let global: any = {
  94. homeChartOne: null,
  95. homeChartTwo: null,
  96. homeCharThree: null,
  97. dispose: [null, '', undefined]
  98. };
  99. export default defineComponent({
  100. name: 'home',
  101. components: { EditDic, DetailDic },
  102. setup() {
  103. // 页面是显示状态
  104. let isActice = true
  105. onUnmounted(() => {
  106. isActice = false
  107. })
  108. const { proxy } = getCurrentInstance() as any;
  109. const { alarm_type } = proxy.useDict('alarm_type');
  110. const alarmTypeMap: any = {}
  111. // 监听告警类型是否获取成功
  112. watch(() => alarm_type.value, (list) => {
  113. if (!list.length) return
  114. list.forEach((item: any) => {
  115. alarmTypeMap[item.value] = item.label
  116. });
  117. // 预警类型需要类型返回后才能请求
  118. getDeviceAlarmLevelCount()
  119. }, {
  120. immediate: true
  121. })
  122. const editDicRef = ref();
  123. const detailRef = ref();
  124. const homeLineRef = ref();
  125. const homePieRef = ref();
  126. const homeBarRef = ref();
  127. const store = useStore();
  128. const router = useRouter();
  129. const state = reactive({
  130. loading: false,
  131. tableData: {
  132. data: [],
  133. total: 0,
  134. loading: false,
  135. param: {
  136. pageNum: 1,
  137. pageSize: 20,
  138. status: '',
  139. dateRange: [],
  140. },
  141. },
  142. homeOne: [
  143. {
  144. allnum: 0,
  145. num1: 0,
  146. num2: 0,
  147. num3: '产品',
  148. num4: 'icon-zidingyibuju',
  149. color1: '#6690F9',
  150. color2: '--el-color-warning-lighter',
  151. color3: '--el-color-warning',
  152. icoimg: 'dashboard-icon1.svg',
  153. title1: '启用',
  154. title2: '停用',
  155. title1_bgcolor: '#3cd357',
  156. title2_bgcolor: '#FFBB73',
  157. },
  158. {
  159. allnum: 0,
  160. num1: 0,
  161. num2: 0,
  162. num3: '在线设备',
  163. num4: 'icon-putong',
  164. color1: '#FF6462',
  165. color2: '--next-color-primary-lighter',
  166. color3: '--el-color-primary',
  167. icoimg: 'dashboard-icon2.svg',
  168. title1: '启用',
  169. title2: '停用',
  170. title1_bgcolor: '#3cd357',
  171. title2_bgcolor: '#FFBB73',
  172. },
  173. {
  174. allnum: 0,
  175. num1: 0,
  176. num2: 0,
  177. num3: '设备消息',
  178. num4: 'icon-shidu',
  179. color1: '#6690F9',
  180. color2: '--el-color-success-lighter',
  181. color3: '--el-color-success',
  182. icoimg: 'dashboard-icon3.svg',
  183. title1: '本月',
  184. title2: '今日',
  185. title1_bgcolor: '#4285F4',
  186. title2_bgcolor: '#FFBB73',
  187. },
  188. {
  189. allnum: 0,
  190. num1: 0,
  191. num2: 0,
  192. num3: '设备告警',
  193. num4: 'icon-zaosheng',
  194. color1: '#6690F9',
  195. color2: '--el-color-warning-lighter',
  196. color3: '--el-color-warning',
  197. icoimg: 'dashboard-icon4.svg',
  198. title1: '本月',
  199. title2: '今日',
  200. title1_bgcolor: '#5ECCFF',
  201. title2_bgcolor: '#FFBB73',
  202. },
  203. ],
  204. myCharts: [],
  205. charts: {
  206. theme: '',
  207. bgColor: '',
  208. color: '#303133',
  209. },
  210. lineChartXAxisData: [],
  211. lineChartMsgTotalData: [],
  212. lineChartAlarmTotalData: [],
  213. pieChartLegend: [],
  214. pieChartLevel: [],
  215. pieChartData: []
  216. });
  217. // 折线图
  218. const initLineChart = () => {
  219. if (!global.dispose.some((b: any) => b === global.homeChartOne)) global.homeChartOne.dispose();
  220. global.homeChartOne = <any>echarts.init(homeLineRef.value, state.charts.theme);
  221. const option = {
  222. backgroundColor: state.charts.bgColor,
  223. title: {
  224. text: '设备消息',
  225. x: 5,
  226. textStyle: { fontSize: '15', color: state.charts.color },
  227. },
  228. grid: { top: 70, right: 20, bottom: 30, left: 50 },
  229. tooltip: { trigger: 'axis' },
  230. legend: { data: ['消息量', '预警量'], right: 0 },
  231. xAxis: {
  232. data: state.lineChartXAxisData
  233. },
  234. yAxis: [
  235. {
  236. type: 'value',
  237. name: '条数',
  238. splitLine: { show: true, lineStyle: { type: 'dashed', color: 'rgba(0, 0, 0, 0.03)' } },
  239. axisLabel: {
  240. margin: 2,
  241. formatter: function (value: any) {
  242. if (value >= 10000 && value < 10000000) {
  243. value = value / 10000 + "W";
  244. } else if (value >= 10000000) {
  245. value = value / 10000000 + "KW";
  246. }
  247. return value;
  248. }
  249. },
  250. },
  251. ],
  252. series: [
  253. {
  254. name: '消息量',
  255. type: 'line',
  256. symbolSize: 0,
  257. symbol: 'circle',
  258. smooth: true,
  259. data: state.lineChartMsgTotalData,
  260. lineStyle: { color: '#4285F4', width: 3 },
  261. itemStyle: { color: '#4285F4', borderColor: '#4285F4' },
  262. areaStyle: {
  263. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  264. { offset: 0, color: 'rgba(66, 133, 244, 0.3)' },
  265. { offset: 1, color: 'rgba(66, 133, 244, 0)' },
  266. ]),
  267. },
  268. },
  269. {
  270. name: '预警量',
  271. type: 'line',
  272. symbolSize: 6,
  273. symbol: 'circle',
  274. smooth: true,
  275. data: state.lineChartAlarmTotalData,
  276. lineStyle: { color: '#FBBB04', width: 3 },
  277. itemStyle: { color: '#FBBB04', borderColor: '#FBBB04' },
  278. areaStyle: {
  279. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  280. { offset: 0, color: 'rgba(251, 187, 4, 0.3)' },
  281. { offset: 1, color: 'rgba(251, 187, 4, 0)' },
  282. ]),
  283. },
  284. emphasis: {
  285. itemStyle: {
  286. color: {
  287. type: 'radial',
  288. x: 0.5,
  289. y: 0.5,
  290. r: 0.5,
  291. colorStops: [
  292. { offset: 0, color: '#9E87FF' },
  293. { offset: 0.4, color: '#9E87FF' },
  294. { offset: 0.5, color: '#fff' },
  295. { offset: 0.7, color: '#fff' },
  296. { offset: 0.8, color: '#fff' },
  297. { offset: 1, color: '#fff' },
  298. ],
  299. },
  300. borderColor: '#9E87FF',
  301. borderWidth: 2,
  302. },
  303. },
  304. },
  305. ],
  306. };
  307. (<any>global.homeChartOne).setOption(option);
  308. (<any>state.myCharts).push(global.homeChartOne);
  309. };
  310. // 饼图
  311. const initPieChart = () => {
  312. if (!global.dispose.some((b: any) => b === global.homeChartTwo)) global.homeChartTwo.dispose();
  313. global.homeChartTwo = <any>echarts.init(homePieRef.value, state.charts.theme);
  314. var getname = state.pieChartLegend;
  315. var getvalue = state.pieChartData;
  316. var data = [];
  317. for (var i = 0; i < getname.length; i++) {
  318. data.push({ name: getname[i], value: getvalue[i] });
  319. }
  320. const colorList = ['#FF0000', '#4285F4', '#FBBB04', '#34A853', '#669'];
  321. const color = state.pieChartLevel.map(level => colorList[level - 1])
  322. const option = {
  323. color,
  324. backgroundColor: state.charts.bgColor,
  325. title: {
  326. text: '预警类型',
  327. x: 5,
  328. textStyle: { fontSize: '15', color: state.charts.color },
  329. },
  330. // tooltip: { trigger: 'item', formatter: '{b} <br/> {c}%' },
  331. tooltip: { trigger: 'item' },
  332. graphic: {
  333. elements: [
  334. {
  335. type: 'image',
  336. z: -1,
  337. left: '16.5%',
  338. top: 'center',
  339. },
  340. ],
  341. },
  342. legend: {
  343. type: 'scroll',
  344. orient: 'vertical',
  345. right: '0%',
  346. left: '65%',
  347. top: 'center',
  348. itemWidth: 14,
  349. itemHeight: 14,
  350. data: getname,
  351. textStyle: {
  352. rich: {
  353. name: {
  354. fontSize: 14,
  355. fontWeight: 400,
  356. width: 200,
  357. height: 35,
  358. padding: [0, 0, 0, 60],
  359. color: state.charts.color,
  360. },
  361. rate: {
  362. fontSize: 15,
  363. fontWeight: 500,
  364. height: 35,
  365. width: 40,
  366. padding: [0, 0, 0, 30],
  367. color: state.charts.color,
  368. },
  369. },
  370. },
  371. },
  372. series: [
  373. {
  374. type: 'pie',
  375. radius: ['70', '90'],
  376. center: ['32%', '50%'],
  377. padAngle: 1,
  378. label: { show: false },
  379. labelLine: { show: false },
  380. data: data,
  381. },
  382. ],
  383. };
  384. (<any>global.homeChartTwo).setOption(option);
  385. (<any>state.myCharts).push(global.homeChartTwo);
  386. };
  387. // 批量设置 echarts resize
  388. const initEchartsResizeFun = () => {
  389. nextTick(() => {
  390. for (let i = 0; i < state.myCharts.length; i++) {
  391. setTimeout(() => {
  392. (<any>state.myCharts[i]).resize();
  393. }, i * 1000);
  394. }
  395. });
  396. };
  397. // 批量设置 echarts resize
  398. const initEchartsResize = () => {
  399. window.addEventListener('resize', initEchartsResizeFun);
  400. };
  401. // 定时获取设备,在线信息,告警数量更新
  402. const getOverviewData = () => {
  403. getProductCount()
  404. getDeviceDataTotalCount()
  405. getDeviceDataTotalCountMonth()
  406. getDeviceDataTotalCountDay()
  407. getDeviceOnlineOfflineCount()
  408. getDeviceAlarmLevelCountYear()
  409. getDeviceAlarmLevelCountMonth()
  410. getDeviceAlarmLevelCountDay()
  411. // 图形数据
  412. getDeviceDataCount()
  413. };
  414. // 普通数据3秒更新
  415. const intervalTimeLong = 3000
  416. function loopRquest(fun: Function, timeLong?: number) {
  417. setTimeout(() => {
  418. isActice && fun()
  419. }, timeLong || intervalTimeLong)
  420. }
  421. // 获取告警告警数量和消息数量绘图
  422. function getDeviceDataCount() {
  423. // 获取年度消息,年度告警数量
  424. Promise.all([api.iotManage.deviceDataCount('year'), api.iotManage.deviceAlertCountByYearMonth(dayjs().format('YYYY'))]).then(([msg, alarm]: any) => {
  425. const msgArr = msg?.data || []
  426. const alarmArr = alarm?.data || []
  427. // console.log(alarmArr)
  428. state.lineChartMsgTotalData = msgArr.map((item: any) => item.Value)
  429. state.lineChartXAxisData = msgArr.map((item: any) => item.Title)
  430. state.lineChartAlarmTotalData = alarmArr.map((item: any) => item.Value)
  431. }).finally(() => loopRquest(getDeviceDataCount, 60000))
  432. }
  433. // 获取告警告警数量和消息数量绘图
  434. function getDeviceAlarmLevelCount() {
  435. // 按告警级别统计 绘制饼图
  436. api.iotManage.deviceAlarmLevelCount('year', dayjs().format('YYYY')).then((res: any) => {
  437. const list = (res.data || []).sort((a: any, b: any) => b.Title - a.Title)
  438. state.pieChartLegend = list.map((item: any) => alarmTypeMap[item.Title])
  439. state.pieChartLevel = list.map((item: any) => item.Title)
  440. state.pieChartData = list.map((item: any) => item.Value)
  441. }).finally(() => loopRquest(getDeviceAlarmLevelCount, 60000))
  442. }
  443. // 产品数量
  444. function getProductCount() {
  445. api.iotManage.productCount().then((res: any) => {
  446. state.homeOne[0].allnum = res.total;
  447. state.homeOne[0].num1 = res.enable
  448. state.homeOne[0].num2 = res.disable
  449. }).finally(() => loopRquest(getProductCount))
  450. }
  451. // 设备数据总数
  452. function getDeviceDataTotalCount() {
  453. api.iotManage.deviceDataTotalCount('year').then((res: any) => {
  454. state.homeOne[2].allnum = res.number;
  455. }).finally(() => loopRquest(getDeviceDataTotalCount))
  456. }
  457. // 设备数据总数-月
  458. function getDeviceDataTotalCountMonth() {
  459. api.iotManage.deviceDataTotalCount('month').then((res: any) => {
  460. state.homeOne[2].num1 = res.number;
  461. }).finally(() => loopRquest(getDeviceDataTotalCountMonth))
  462. }
  463. // 设备数据总数-月
  464. function getDeviceDataTotalCountDay() {
  465. api.iotManage.deviceDataTotalCount('day').then((res: any) => {
  466. state.homeOne[2].num2 = res.number;
  467. }).finally(() => loopRquest(getDeviceDataTotalCountDay))
  468. }
  469. // 设备数量
  470. function getDeviceOnlineOfflineCount() {
  471. api.iotManage.deviceOnlineOfflineCount().then((res: any) => {
  472. state.homeOne[1].allnum = res.online;
  473. state.homeOne[1].num1 = res.total - res.disable
  474. state.homeOne[1].num2 = res.disable
  475. }).finally(() => loopRquest(getDeviceOnlineOfflineCount))
  476. }
  477. // 告警数量-年
  478. function getDeviceAlarmLevelCountYear() {
  479. api.iotManage.deviceAlarmLevelCount('year', dayjs().format('YYYY')).then((res: any) => {
  480. const list = (res.data || [])
  481. const total = list.reduce((a: any, b: any) => a + b.Value, 0)
  482. state.homeOne[3].allnum = total;
  483. }).finally(() => loopRquest(getDeviceAlarmLevelCountYear))
  484. }
  485. // 告警数量-月
  486. function getDeviceAlarmLevelCountMonth() {
  487. api.iotManage.deviceAlarmLevelCount('month', dayjs().format('M')).then((res: any) => {
  488. const total = (res.data || []).reduce((a: any, b: any) => a + b.Value, 0)
  489. state.homeOne[3].num1 = total;
  490. }).finally(() => loopRquest(getDeviceAlarmLevelCountMonth))
  491. }
  492. // 告警数量-日
  493. function getDeviceAlarmLevelCountDay() {
  494. api.iotManage.deviceAlarmLevelCount('day', dayjs().format('D')).then((res: any) => {
  495. const total = (res.data || []).reduce((a: any, b: any) => a + b.Value, 0)
  496. state.homeOne[3].num2 = total;
  497. }).finally(() => loopRquest(getDeviceAlarmLevelCountDay))
  498. }
  499. const getAlarmList = () => {
  500. api.iotManage.getAlarmList(state.tableData.param).then((res: any) => {
  501. state.tableData.data = res.list;
  502. state.tableData.total = res.Total;
  503. })
  504. }
  505. //打开详情页
  506. const onOpenDetailDic = (row: any) => {
  507. detailRef.value.openDialog(row);
  508. };
  509. // 打开修改产品弹窗
  510. const onOpenEditDic = (row: any) => {
  511. editDicRef.value.openDialog(row);
  512. };
  513. // 告警信息-更多信息
  514. const toMore = () => {
  515. router.push({ path: '/iotmanager/alarm/log' });
  516. };
  517. // 页面加载时
  518. onMounted(() => {
  519. initEchartsResize();
  520. getOverviewData();
  521. getAlarmList();
  522. });
  523. // 由于页面缓存原因,keep-alive
  524. onActivated(() => {
  525. initEchartsResizeFun();
  526. });
  527. // 监听 vuex 中的 tagsview 开启全屏变化,重新 resize 图表,防止不出现/大小不变等
  528. watch(
  529. () => store.state.tagsViewRoutes.isTagsViewCurrenFull,
  530. () => {
  531. initEchartsResizeFun();
  532. }
  533. );
  534. watch(
  535. () => state.lineChartAlarmTotalData,
  536. () => {
  537. initLineChart();
  538. }
  539. );
  540. watch(
  541. () => state.pieChartData,
  542. () => {
  543. initPieChart();
  544. }
  545. );
  546. // 监听 vuex 中是否开启深色主题
  547. watch(
  548. () => store.state.themeConfig.themeConfig.isIsDark,
  549. (isIsDark) => {
  550. nextTick(() => {
  551. state.charts.theme = isIsDark ? 'dark' : '';
  552. state.charts.bgColor = isIsDark ? 'transparent' : '';
  553. state.charts.color = isIsDark ? '#dadada' : '#303133';
  554. setTimeout(() => {
  555. initLineChart();
  556. }, 500);
  557. setTimeout(() => {
  558. initPieChart();
  559. }, 700);
  560. });
  561. },
  562. {
  563. deep: true,
  564. immediate: true,
  565. }
  566. );
  567. watch(
  568. () => state.lineChartMsgTotalData,
  569. () => {
  570. initLineChart();
  571. }
  572. );
  573. return {
  574. homeLineRef,
  575. homePieRef,
  576. homeBarRef,
  577. detailRef,
  578. editDicRef,
  579. toMore,
  580. onOpenEditDic,
  581. getAlarmList,
  582. onOpenDetailDic,
  583. getOverviewData,
  584. ...toRefs(state),
  585. };
  586. },
  587. });
  588. </script>
  589. <style scoped lang="scss">
  590. $homeNavLengh: 8;
  591. .home-card-top-part {
  592. background-color: var(--el-color-white);
  593. border-radius: 8px;
  594. padding: 20px 20px;
  595. .top {
  596. display: flex;
  597. justify-content: space-around;
  598. overflow: hidden;
  599. align-items: center;
  600. }
  601. .icoimg {
  602. width: 54px !important;
  603. height: 54px !important;
  604. margin-right: 12px;
  605. }
  606. .label {
  607. font-size: 14px;
  608. font-weight: 500;
  609. }
  610. .divider {
  611. border-top: 1px solid var(--el-border-color-light);
  612. margin: 12px 0 15px;
  613. }
  614. .card-right {
  615. flex: 1;
  616. display: flex;
  617. flex-direction: column;
  618. justify-content: space-between;
  619. white-space: nowrap;
  620. line-height: 1;
  621. height: 54px;
  622. .font30 {
  623. color: #4285F4;
  624. font-weight: bold;
  625. font-size: 30px;
  626. }
  627. }
  628. .card-bottom {
  629. font-size: 12px;
  630. display: flex;
  631. align-items: center;
  632. justify-content: space-around;
  633. gap: 12px;
  634. white-space: nowrap;
  635. .split {
  636. border-right: 1px solid var(--el-border-color-light);
  637. height: 20px;
  638. }
  639. .icon {
  640. width: 17px;
  641. height: 17px;
  642. }
  643. .info {
  644. font-size: 12px;
  645. font-weight: 500;
  646. }
  647. }
  648. }
  649. .home-container {
  650. overflow: hidden;
  651. .home-card-one,
  652. .home-card-two,
  653. .home-card-three {
  654. .icoimg {
  655. width: 75px;
  656. height: 75px;
  657. }
  658. .title_status {
  659. width: 7px;
  660. height: 7px;
  661. background: #c1bbbb;
  662. border-radius: 50px;
  663. margin-right: 5px;
  664. }
  665. .home-card-item,
  666. .home-card-top {
  667. width: 100%;
  668. height: 130px;
  669. border-radius: 8px;
  670. transition: all ease 0.3s;
  671. padding: 10px 20px;
  672. overflow: hidden;
  673. background: var(--el-color-white);
  674. color: var(--el-text-color-primary);
  675. // border: 1px solid var(--next-border-color-light);
  676. &:hover {
  677. // box-shadow: 0 2px 12px var(--next-color-dark-hover);
  678. transition: all ease 0.3s;
  679. }
  680. &-icon {
  681. width: 70px;
  682. height: 70px;
  683. border-radius: 100%;
  684. flex-shrink: 1;
  685. i {
  686. color: var(--el-text-color-placeholder);
  687. }
  688. }
  689. &-title {
  690. font-size: 15px;
  691. font-weight: bold;
  692. height: 30px;
  693. }
  694. }
  695. }
  696. .home-card-three {
  697. .home-card-item-title {
  698. display: flex;
  699. justify-content: space-between;
  700. // span:nth-child(2) {
  701. // color: #409eff;
  702. // }
  703. }
  704. }
  705. .home-card-one {
  706. @for $i from 0 through 3 {
  707. .home-one-animation#{$i} {
  708. opacity: 0;
  709. animation-name: error-num;
  710. animation-duration: 0.5s;
  711. animation-fill-mode: forwards;
  712. animation-delay: calc($i/10) + s;
  713. }
  714. }
  715. }
  716. .home-card-two,
  717. .home-card-three {
  718. .home-card-item {
  719. height: 300px;
  720. }
  721. .home-card-top {
  722. height: 250px;
  723. .box-card {
  724. padding: 15px 20px 20px 10px;
  725. p {
  726. margin-bottom: 10px;
  727. }
  728. &-item {
  729. margin-bottom: 10px;
  730. }
  731. }
  732. }
  733. .home-card-item,
  734. .home-card-top {
  735. width: 100%;
  736. overflow: hidden;
  737. .home-monitor {
  738. height: 100%;
  739. .flex-warp-item {
  740. width: 25%;
  741. height: 111px;
  742. display: flex;
  743. .flex-warp-item-box {
  744. margin: auto;
  745. text-align: center;
  746. color: var(--el-text-color-primary);
  747. display: flex;
  748. border-radius: 5px;
  749. background: var(--next-bg-color);
  750. cursor: pointer;
  751. transition: all 0.3s ease;
  752. &:hover {
  753. background: var(--el-color-primary-light-9);
  754. transition: all 0.3s ease;
  755. }
  756. }
  757. @for $i from 0 through $homeNavLengh {
  758. .home-animation#{$i} {
  759. opacity: 0;
  760. animation-name: error-num;
  761. animation-duration: 0.5s;
  762. animation-fill-mode: forwards;
  763. animation-delay: calc($i/10) + s;
  764. }
  765. }
  766. }
  767. }
  768. }
  769. }
  770. .text-info {
  771. color: #23c6c8;
  772. }
  773. .text-danger {
  774. color: #ed5565;
  775. }
  776. .git-res {
  777. margin-top: 20px;
  778. }
  779. .git-res .el-link {
  780. margin-right: 30px;
  781. }
  782. ul,
  783. li {
  784. padding: 0;
  785. margin: 0;
  786. list-style: none
  787. }
  788. .product {
  789. margin-top: 50px;
  790. h3 {
  791. margin-bottom: 15px;
  792. }
  793. }
  794. .product li {
  795. margin-bottom: 20px;
  796. float: left;
  797. width: 150px;
  798. }
  799. .box-card.xx {
  800. margin-top: 20px;
  801. }
  802. }
  803. .home-card-item.chart {
  804. padding: 10px !important;
  805. }
  806. </style>