index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="10" class="mb8">
  4. <el-col :span="16">
  5. <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="0">
  6. <el-form-item>
  7. <el-button type="primary" plain @click="timeSelect(0)">今天</el-button>
  8. <el-button type="primary" plain @click="timeSelect(3)">3天</el-button>
  9. <el-button type="primary" plain @click="timeSelect(7)">7天</el-button>
  10. <el-button type="primary" :plain="false" @click="timeSelect(30)">1月</el-button>
  11. </el-form-item>
  12. <el-form-item label="">
  13. <el-date-picker
  14. v-model="daterangeAlarmTime"
  15. value-format="YYYY-MM-DD"
  16. type="daterange"
  17. range-separator="-"
  18. start-placeholder="开始日期"
  19. end-placeholder="结束日期"
  20. ></el-date-picker>
  21. </el-form-item>
  22. <el-form-item label="" prop="objId" style="margin-right:10px">
  23. <el-select v-model="queryParams.objId" placeholder="请选择告警对象" style="width: 260px" clearable
  24. filterable remote reserve-keyword :remote-method="remoteMethod">
  25. <el-option
  26. v-for="dict in objList"
  27. :key="dict.objId"
  28. :label="dict.objName"
  29. :value="dict.objId"
  30. ></el-option>
  31. </el-select>
  32. </el-form-item>
  33. <el-form-item label="" prop="alarmLevel" style="margin-right:10px">
  34. <el-select v-model="queryParams.alarmType" placeholder="风险状态" clearable style="width:100px;">
  35. <el-option
  36. v-for="dict in alarm_type"
  37. :key="dict.value"
  38. :label="dict.label"
  39. :value="dict.value"
  40. />
  41. </el-select>
  42. </el-form-item>
  43. <el-form-item style="margin-right:10px">
  44. <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
  45. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  46. </el-form-item>
  47. </el-form>
  48. </el-col>
  49. </el-row>
  50. <el-row :gutter="10" class="mb8">
  51. <el-col :span="10">
  52. <el-card>
  53. <div ref="alarmLeft" style="height: 190px;"></div>
  54. </el-card>
  55. </el-col>
  56. <el-col :span="14" style="text-align: right">
  57. <el-card>
  58. <div ref="alarmRight" style="height: 190px;"></div>
  59. </el-card>
  60. </el-col>
  61. </el-row>
  62. <el-table ref="recordRef" v-loading="loading" :data="recordList" border :default-sort="defaultSort"
  63. @sort-change="handleSortChange">
  64. <!-- <el-table-column label="告警ID" align="left" prop="alarmId" width="80"/>-->
  65. <el-table-column label="风险对象" align="left" prop="objName" sortable="custom"
  66. :sort-orders="['descending', 'ascending']"/>
  67. <el-table-column label="风险指标" align="center" prop="metricsName"/>
  68. <el-table-column label="风险级别" align="center" prop="alarmLevel" sortable="custom"
  69. :sort-orders="['descending', 'ascending']">
  70. <template #default="scope">
  71. <dict-tag :options="alarm_level" :value="scope.row.alarmLevel"/>
  72. </template>
  73. </el-table-column>
  74. <el-table-column label="风险状态" align="center" prop="alarmType">
  75. <template #default="scope">
  76. <dict-tag :options="alarm_type" :value="scope.row.alarmType"/>
  77. </template>
  78. </el-table-column>
  79. <el-table-column label="风险值" align="center" prop="alarmValue" :formatter="rounding"/>
  80. <el-table-column label="事件时间" align="center" prop="alarmTime" width="220" sortable="custom"
  81. :sort-orders="['descending', 'ascending']">
  82. <template #default="scope">
  83. <span>{{ parseTime(scope.row.alarmTime, '{y}-{m}-{d} {h}:{mi}:{s}') }}</span>
  84. </template>
  85. </el-table-column>
  86. </el-table>
  87. <pagination
  88. v-show="total>0"
  89. :total="total"
  90. v-model:page="queryParams.pageNum"
  91. v-model:limit="queryParams.pageSize"
  92. @pagination="getList"
  93. />
  94. </div>
  95. </template>
  96. <script setup name="Record">
  97. import {getLevelSort, listHours, listRecord} from "@/api/alarm/record";
  98. import {listObj} from "@/api/obj/obj.js"
  99. import * as echarts from 'echarts'
  100. import moment from 'moment'
  101. const {proxy} = getCurrentInstance();
  102. const {alarm_level} = proxy.useDict('alarm_level');
  103. const {alarm_type} = proxy.useDict('alarm_type');
  104. const recordList = ref([]);
  105. const loading = ref(true);
  106. const showSearch = ref(true);
  107. const total = ref(0);
  108. const title = ref("");
  109. const daterangeAlarmTime = ref([]);
  110. const objList = ref([]);
  111. const alarmLeft = ref();
  112. const alarmRight = ref([]);
  113. const defaultSort = ref({prop: "alarmTime", order: "descending"});
  114. const data = reactive({
  115. form: {},
  116. queryParams: {
  117. pageNum: 1,
  118. pageSize: 10,
  119. objId: null,
  120. objMetricsId: null,
  121. alarmLevel: null,
  122. alarmTime: null,
  123. },
  124. rules: {}
  125. });
  126. const {queryParams, form, rules} = toRefs(data);
  127. function remoteMethod(keyword) {
  128. listObj({pageNum: 1, pageSize: 5, objName: keyword}).then(res => {
  129. objList.value = res.rows
  130. })
  131. }
  132. function left() {
  133. let myChart = echarts.init(alarmLeft.value);
  134. getLevelSort(queryParams.value).then(res => {
  135. console.log(res);
  136. const d_data = [];
  137. for (let i = 0; i < res.data.length; i++) {
  138. let d = {value: res.data[i].num, name: res.data[i].name}
  139. d_data.push(d);
  140. }
  141. let legend_style = {
  142. rich: {
  143. a: {
  144. fontFamily: 'PingFangSC-Regular, PingFang SC',
  145. color: '#4F5860',
  146. fontSize: 12
  147. },
  148. b: {
  149. fontFamily: 'Arial Black',
  150. color: '#4F5860',
  151. fontWeight: 600,
  152. fontSize: 12
  153. }
  154. }
  155. };
  156. let option = {
  157. tooltip: {
  158. trigger: 'item',
  159. formatter: '{a} <br/>{b}: {c} ({d}%)'
  160. },
  161. title: {
  162. show: true,
  163. text: '风险级别统计',
  164. textStyle: {
  165. fontFamily: 'PingFangSC-Regular, PingFang SC',
  166. align: 'center',
  167. color: '#515961',
  168. fontSize: 18,
  169. },
  170. },
  171. legend: [{
  172. icon: 'circle',
  173. zlevel: 1,
  174. top: '20%',
  175. right: '25%',
  176. itemWidth: 20,
  177. itemHeight: 20,
  178. itemGap: 20,
  179. orient: "vertical", // 图例列表的布局朝向。 'horizontal' 'vertical'
  180. textStyle: legend_style,
  181. data: d_data,
  182. formatter: view_legend,
  183. }
  184. ],
  185. series: [{
  186. name: '告警数量',
  187. type: 'pie',
  188. left: '-45%',
  189. radius: ['35%', '85%'],
  190. // color: color_list,
  191. label: {
  192. show: false,
  193. },
  194. data: d_data
  195. }]
  196. };
  197. myChart.setOption(option);
  198. function view_legend(name) {
  199. let x_data;
  200. let total = 0;
  201. for (let i in d_data) {
  202. total += d_data[i].value;
  203. if (d_data[i].name == name) {
  204. x_data = d_data[i];
  205. // console.log(d_data[i])
  206. }
  207. }
  208. let percent = (x_data.value * 100 / total).toFixed(2);
  209. return '{a|' + name + '} {b|' + percent + '%} {c|' + x_data.value + '}次';
  210. }
  211. })
  212. }
  213. function right() {
  214. let myChart = echarts.init(alarmRight.value);
  215. listHours(queryParams.value).then(res => {
  216. let yd=[];
  217. let xd=[];
  218. for (let i = 0; i < res.data.length; i++) {
  219. xd.push(res.data[i].hour);
  220. yd.push(res.data[i].num);
  221. }
  222. let ss = [];
  223. let xx = {
  224. // name: xd,
  225. type: 'line',
  226. data: yd,
  227. symbolSize: 1,
  228. symbol: 'circle',
  229. smooth: true,
  230. showSymbol: false,
  231. lineStyle: {
  232. width: 1,
  233. type: 'solid', //'dotted'虚线 'solid'实线
  234. },
  235. itemStyle: {
  236. normal: {
  237. color: '#FFB25C',
  238. borderColor: '#FFB25C'
  239. }
  240. }
  241. }
  242. ss.push(xx);
  243. let x_data = xd;
  244. let option = {
  245. backgroundColor: '#FFFFFF',
  246. dataZoom: {
  247. type: 'inside', // 内置型数据区域缩放组件
  248. start: 0, // 默认为0,表示从头开始
  249. end: 100 // 默认为100,表示直到末尾
  250. },
  251. title: {
  252. show: true,
  253. text: '告警趋势',
  254. // textStyle: {
  255. // fontFamily: 'PingFangSC-Regular, PingFang SC',
  256. // fontSize: 16,
  257. // fontWeight: 600,
  258. // color: '#848E98'
  259. // },
  260. left: 'left',
  261. // top: '3%'
  262. },
  263. legend: {
  264. icon: 'rect',
  265. top: '3%',
  266. right: '10%',
  267. itemWidth: 10,
  268. itemHeight: 10,
  269. itemGap: 20,
  270. textStyle: {
  271. fontFamily: 'PingFangSC-Regular, PingFang SC',
  272. color: '#848E98'
  273. }
  274. },
  275. tooltip: {
  276. trigger: 'axis',
  277. axisPointer: {
  278. label: {
  279. show: true,
  280. backgroundColor: '#fff',
  281. color: '#556677',
  282. borderColor: 'rgba(0,0,0,0)',
  283. shadowColor: 'rgba(0,0,0,0)',
  284. shadowOffsetY: 0
  285. },
  286. lineStyle: {
  287. width: 0
  288. }
  289. },
  290. backgroundColor: '#fff',
  291. textStyle: {
  292. color: '#5c6c7c'
  293. },
  294. padding: [10, 10],
  295. extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5)'
  296. },
  297. grid: {
  298. top: '18%'
  299. },
  300. xAxis: [{
  301. type: 'category',
  302. data: x_data,
  303. axisLine: {
  304. show: false,
  305. lineStyle: {
  306. color: '#000000'
  307. }
  308. },
  309. axisTick: {
  310. show: false
  311. },
  312. axisLabel: {
  313. interval: 'auto',
  314. rotate: 45,
  315. textStyle: {
  316. color: '#B7C3CE'
  317. },
  318. // 默认x轴字体大小
  319. fontSize: 12,
  320. // margin:文字到x轴的距离
  321. margin: 5,
  322. hideOverlap: true // 隐藏部分标签避免重叠
  323. }
  324. }],
  325. yAxis: [{
  326. type: 'value',
  327. axisTick: {
  328. show: false
  329. },
  330. axisLine: {
  331. show: false,
  332. },
  333. axisLabel: {
  334. fontSize: 12,
  335. textStyle: {
  336. color: '#B7C3CE'
  337. }
  338. },
  339. splitLine: {
  340. show: true,
  341. lineStyle: {
  342. type: "dashed"
  343. }
  344. }
  345. }],
  346. series: ss
  347. };
  348. myChart.setOption(option)
  349. });
  350. }
  351. /** 查询告警记录列表 */
  352. function getList() {
  353. loading.value = true;
  354. queryParams.value.params = {};
  355. if (null != daterangeAlarmTime && '' != daterangeAlarmTime) {
  356. queryParams.value.params["beginAlarmTime"] = daterangeAlarmTime.value[0];
  357. queryParams.value.params["endAlarmTime"] = daterangeAlarmTime.value[1];
  358. }
  359. if (queryParams.value.orderByColumn == null || queryParams.value.orderByColumn == '') {
  360. queryParams.value.orderByColumn = defaultSort.value.prop;
  361. queryParams.value.isAsc = defaultSort.value.order;
  362. }
  363. listRecord(queryParams.value).then(response => {
  364. recordList.value = response.rows;
  365. total.value = response.total;
  366. loading.value = false;
  367. left();
  368. right();
  369. });
  370. }
  371. function timeSelect(v) {
  372. let end = new Date();
  373. let start = new Date().setDate(end.getDate() - v);
  374. daterangeAlarmTime.value[0] = moment(start).format('YYYY-MM-DD');
  375. daterangeAlarmTime.value[1] = moment(end).format('YYYY-MM-DD');
  376. }
  377. /** 搜索按钮操作 */
  378. function handleQuery() {
  379. queryParams.value.pageNum = 1;
  380. getList();
  381. }
  382. /** 重置按钮操作 */
  383. function resetQuery() {
  384. daterangeAlarmTime.value = [];
  385. proxy.resetForm("queryRef");
  386. proxy.$refs["recordRef"].sort(defaultSort.value.prop, defaultSort.value.order);
  387. handleQuery();
  388. }
  389. /** 保留2位小数*/
  390. function rounding(row, column) {
  391. return parseFloat(row[column.property]).toFixed(2)
  392. }
  393. /** 排序触发事件 */
  394. function handleSortChange(column, prop, order) {
  395. queryParams.value.orderByColumn = column.prop;
  396. queryParams.value.isAsc = column.order;
  397. getList();
  398. }
  399. timeSelect(30);
  400. getList();
  401. </script>