TowerStatus.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. <template>
  2. <div class="menu-content">
  3. <div class="gradient-text title">铁塔运行监测</div>
  4. <div class="data-box">
  5. <div v-for="(item, index) in analyzeData" :key="index" class="data-item">
  6. <div class="text1">{{ item.status_name }}</div>
  7. <div class="box-content">
  8. <div class="text2">{{ item.num }}</div>
  9. <i :class="'icon' + (index + 1)"></i>
  10. </div>
  11. </div>
  12. </div>
  13. <div class="card-header">
  14. <div class="title-box">各区县异常比例</div>
  15. </div>
  16. <Chart :option="chartOption1" style="width: 100%; height: 650px" />
  17. <div class="card-header">
  18. <div class="title-box">各区县告警类型分析</div>
  19. </div>
  20. <div class="table">
  21. <div class="table-header">
  22. <div class="td">区县</div>
  23. <div class="td td-cursor">
  24. <span>停电</span>
  25. <i
  26. :class="
  27. queryParams.sortName !== 'td' || (queryParams.sortName === 'td' && queryParams.sort === '')
  28. ? 'unSort-icon'
  29. : queryParams.sort === 'desc'
  30. ? 'desc-icon'
  31. : 'asc-icon'
  32. "
  33. @click="handleSort('td')"
  34. />
  35. </div>
  36. <div class="td td-cursor">
  37. <span>欠压</span>
  38. <i
  39. :class="
  40. queryParams.sortName !== 'qy' || (queryParams.sortName === 'qy' && queryParams.sort === '')
  41. ? 'unSort-icon'
  42. : queryParams.sort === 'desc'
  43. ? 'desc-icon'
  44. : 'asc-icon'
  45. "
  46. @click="handleSort('qy')"
  47. />
  48. </div>
  49. <div class="td td-cursor">
  50. <span>退服</span>
  51. <i
  52. :class="
  53. queryParams.sortName !== 'tf' || (queryParams.sortName === 'tf' && queryParams.sort === '')
  54. ? 'unSort-icon'
  55. : queryParams.sort === 'desc'
  56. ? 'desc-icon'
  57. : 'asc-icon'
  58. "
  59. @click="handleSort('tf')"
  60. />
  61. </div>
  62. <div class="td td-cursor">
  63. <span>离线</span>
  64. <i
  65. :class="
  66. queryParams.sortName !== 'lx' || (queryParams.sortName === 'lx' && queryParams.sort === '')
  67. ? 'unSort-icon'
  68. : queryParams.sort === 'desc'
  69. ? 'desc-icon'
  70. : 'asc-icon'
  71. "
  72. @click="handleSort('lx')"
  73. />
  74. </div>
  75. <div class="td td-cursor">
  76. <span>温度过高</span>
  77. <i
  78. :class="
  79. queryParams.sortName !== 'wdgg' || (queryParams.sortName === 'wdgg' && queryParams.sort === '')
  80. ? 'unSort-icon'
  81. : queryParams.sort === 'desc'
  82. ? 'desc-icon'
  83. : 'asc-icon'
  84. "
  85. @click="handleSort('wdgg')"
  86. />
  87. </div>
  88. <div class="td td-cursor">
  89. <span>烟雾</span>
  90. <i
  91. :class="
  92. queryParams.sortName !== 'yw' || (queryParams.sortName === 'yw' && queryParams.sort === '')
  93. ? 'unSort-icon'
  94. : queryParams.sort === 'desc'
  95. ? 'desc-icon'
  96. : 'asc-icon'
  97. "
  98. @click="handleSort('yw')"
  99. />
  100. </div>
  101. <div class="td td-cursor">
  102. <span>水浸</span>
  103. <i
  104. :class="
  105. queryParams.sortName !== 'sj' || (queryParams.sortName === 'sj' && queryParams.sort === '')
  106. ? 'unSort-icon'
  107. : queryParams.sort === 'desc'
  108. ? 'desc-icon'
  109. : 'asc-icon'
  110. "
  111. @click="handleSort('sj')"
  112. />
  113. </div>
  114. <div class="td td-cursor">
  115. <span>非法侵入</span>
  116. <i
  117. :class="
  118. queryParams.sortName !== 'ffqr' || (queryParams.sortName === 'ffqr' && queryParams.sort === '')
  119. ? 'unSort-icon'
  120. : queryParams.sort === 'desc'
  121. ? 'desc-icon'
  122. : 'asc-icon'
  123. "
  124. @click="handleSort('ffqr')"
  125. />
  126. </div>
  127. </div>
  128. <div class="table-content">
  129. <div v-for="(item, index) in rangeData" :key="index" class="tr">
  130. <div class="td">{{ item.area }}</div>
  131. <div class="td2">{{ item.td }}</div>
  132. <div class="td2">{{ item.qy }}</div>
  133. <div class="td2">{{ item.tf }}</div>
  134. <div class="td2">{{ item.lx }}</div>
  135. <div class="td2">{{ item.wdgg }}</div>
  136. <div class="td2">{{ item.yw }}</div>
  137. <div class="td2">{{ item.sj }}</div>
  138. <div class="td2">{{ item.ffjr }}</div>
  139. </div>
  140. </div>
  141. </div>
  142. </div>
  143. </template>
  144. <script lang="ts" setup>
  145. import { ref, reactive, onMounted } from 'vue';
  146. import { option8 } from './echartOptions';
  147. import { getTowerStatus, getTowerWarn, getTowerAbnormal } from '@/api/globalMap/TowerStatus';
  148. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  149. const { district_type } = toRefs<any>(proxy?.useDict('district_type'));
  150. // 各区县异常比例
  151. const chartOption1 = ref(option8);
  152. const fetchAbnormalRateData = async () => {
  153. getTowerAbnormal().then((res) => {
  154. const yAxisData = [];
  155. const data = [];
  156. const data2 = [];
  157. res.rows.forEach((item) => {
  158. yAxisData.push(item.area);
  159. data.push(item.num);
  160. data2.push(!!item.num ? item.num : null);
  161. });
  162. chartOption1.value.yAxis.data = yAxisData;
  163. chartOption1.value.series[0].data = data;
  164. chartOption1.value.series[1].data = data;
  165. });
  166. };
  167. // 各区县告警类型分析
  168. const queryParams = reactive({
  169. order_by: 'ffjr',
  170. sort: 'asc'
  171. });
  172. const rangeData = ref([]);
  173. // 获取告警类型分析数据的方法
  174. const townshipList = async () => {
  175. const data = {
  176. query: {
  177. order_by: queryParams.order_by,
  178. sort: queryParams.sort
  179. }
  180. };
  181. try {
  182. const response = await getTowerWarn(data);
  183. if (response.code === 0 && response.rows) {
  184. rangeData.value = response.rows;
  185. } else {
  186. console.error('获取告警类型分析数据失败:', response.msg);
  187. }
  188. } catch (error) {
  189. console.error('请求告警类型分析数据失败:', error);
  190. }
  191. };
  192. // 处理排序
  193. const handleSort = (type: string) => {
  194. if (type === queryParams.order_by) {
  195. queryParams.sort = queryParams.sort === 'asc' ? 'desc' : 'asc';
  196. } else {
  197. queryParams.order_by = type;
  198. queryParams.sort = 'asc'; // 默认设置为升序
  199. }
  200. townshipList(); // 重新获取数据
  201. };
  202. // 影响分析
  203. const analyzeData = ref([
  204. { status_name: '停电', num: '' },
  205. { status_name: '欠压', num: '' },
  206. { status_name: '退服', num: '' },
  207. { status_name: '离线', num: '' },
  208. { status_name: '温度过高', num: '' },
  209. { status_name: '烟雾', num: '' },
  210. { status_name: '水浸', num: '' },
  211. { status_name: '非法侵入', num: '' }
  212. ]);
  213. const getTower = () => {
  214. getTowerStatus().then((res) => {
  215. analyzeData.value = res.rows;
  216. });
  217. };
  218. onMounted(() => {
  219. getTower();
  220. townshipList();
  221. fetchAbnormalRateData();
  222. });
  223. </script>
  224. <style lang="scss" scoped>
  225. .menu-content {
  226. width: 1589px;
  227. height: 2071px;
  228. background: url('@/assets/images/map/rightMenu/rainMonitor/dialog.png') no-repeat;
  229. padding: 130px 50px 50px 50px;
  230. font-size: 36px;
  231. position: relative;
  232. .card-header {
  233. display: flex;
  234. justify-content: space-between;
  235. align-items: center;
  236. margin-top: 35px;
  237. .title-box {
  238. width: 100%;
  239. background-image: url('@/assets/images/map/rightMenu/rainMonitor/titleBox.png');
  240. background-repeat: no-repeat;
  241. background-size: 370px 35px;
  242. background-position: bottom left;
  243. font-size: 44px;
  244. color: #fff;
  245. padding-left: 50px;
  246. display: flex;
  247. align-items: center;
  248. .line {
  249. background-color: #dce2ec;
  250. width: 3px;
  251. height: 44px;
  252. margin: 0 30px;
  253. }
  254. .text2 {
  255. font-size: 44px;
  256. }
  257. .text3 {
  258. font-size: 38px;
  259. color: #a7ccdf;
  260. }
  261. }
  262. .btn-box {
  263. display: flex;
  264. align-items: center;
  265. .btn {
  266. width: 244px;
  267. height: 120px;
  268. background: url('@/assets/images/map/rightMenu/rainMonitor/btn.png') no-repeat;
  269. cursor: pointer;
  270. display: flex;
  271. align-items: center;
  272. justify-content: center;
  273. .more-icon {
  274. width: 47px;
  275. height: 43px;
  276. background: url('@/assets/images/map/rightMenu/rainMonitor/more.png') no-repeat;
  277. margin-right: 5px;
  278. }
  279. .export-icon {
  280. width: 43px;
  281. height: 45px;
  282. background: url('@/assets/images/map/rightMenu/rainMonitor/export.png') no-repeat;
  283. margin-right: 5px;
  284. }
  285. .btn-text {
  286. color: #edfaff;
  287. font-size: 32px;
  288. }
  289. }
  290. }
  291. }
  292. }
  293. .table {
  294. margin-top: 20px;
  295. margin-left: 20px;
  296. .table-header {
  297. width: 1490px;
  298. height: 88px;
  299. background: url('@/assets/images/common/header.png') no-repeat;
  300. display: flex;
  301. align-items: center;
  302. .td {
  303. color: #edfaff !important;
  304. }
  305. .td-cursor {
  306. cursor: pointer;
  307. }
  308. }
  309. .table-content {
  310. height: 500px;
  311. overflow-y: auto;
  312. }
  313. .tr {
  314. width: 1487px;
  315. height: 88px;
  316. background: url('@/assets/images/common/tr.png') no-repeat;
  317. display: flex;
  318. align-items: center;
  319. margin-top: 10px;
  320. .td {
  321. white-space: nowrap;
  322. overflow: hidden;
  323. text-overflow: ellipsis;
  324. }
  325. }
  326. .gradient-text2 {
  327. color: transparent !important;
  328. }
  329. .td,
  330. .td2 {
  331. font-size: 38px;
  332. display: flex;
  333. justify-content: center;
  334. align-items: center;
  335. flex: 1;
  336. &:nth-child(6),
  337. &:nth-child(9) {
  338. width: 193px;
  339. flex: unset;
  340. }
  341. }
  342. .td {
  343. color: #a7ccdf;
  344. }
  345. .td2 {
  346. color: #edfaff;
  347. font-family: BEBAS-1;
  348. }
  349. .down-icon {
  350. display: inline-block;
  351. width: 33px;
  352. height: 15px;
  353. background: url('@/assets/images/map/rightMenu/rainMonitor/down.png') no-repeat;
  354. cursor: pointer;
  355. margin-left: 8px;
  356. }
  357. .asc-icon {
  358. display: inline-block;
  359. width: 33px;
  360. height: 33px;
  361. background: url('@/assets/images/common/asc.png') no-repeat;
  362. cursor: pointer;
  363. margin-left: 8px;
  364. }
  365. .desc-icon {
  366. display: inline-block;
  367. width: 33px;
  368. height: 33px;
  369. background: url('@/assets/images/common/desc.png') no-repeat;
  370. cursor: pointer;
  371. margin-left: 8px;
  372. }
  373. .unSort-icon {
  374. display: inline-block;
  375. width: 33px;
  376. height: 32px;
  377. background: url('@/assets/images/common/unSort.png') no-repeat;
  378. background-size: 100% 100%;
  379. cursor: pointer;
  380. margin-left: 8px;
  381. }
  382. }
  383. .title {
  384. font-size: 60px;
  385. position: absolute;
  386. top: 30px;
  387. left: 160px;
  388. }
  389. .data-box {
  390. display: flex;
  391. flex-wrap: wrap;
  392. align-items: center;
  393. .data-item {
  394. width: 342px;
  395. height: 160px;
  396. background: url('@/assets/images/map/rightMenu/ironTower/boxBg.png') no-repeat;
  397. background-size: 100% 100%;
  398. color: #fff;
  399. display: flex;
  400. flex-direction: column;
  401. justify-content: center;
  402. font-size: 38px;
  403. margin-top: 30px;
  404. margin-right: 40px;
  405. padding: 0 30px;
  406. &:nth-child(4),
  407. &:nth-child(8) {
  408. margin-right: 0;
  409. }
  410. .text1 {
  411. color: #a7ccdf;
  412. margin-bottom: 10px;
  413. }
  414. .text2 {
  415. font-size: 48px;
  416. font-family: BEBAS-1;
  417. color: transparent;
  418. background-image: linear-gradient(to bottom, #ffffff 20%, #2b72d6 100%);
  419. -webkit-background-clip: text;
  420. background-clip: text;
  421. display: inline-block;
  422. }
  423. .box-content {
  424. display: flex;
  425. justify-content: space-between;
  426. align-items: center;
  427. }
  428. .icon1 {
  429. width: 51px;
  430. height: 69px;
  431. background: url('@/assets/images/map/rightMenu/ironTower/icon1.png') no-repeat;
  432. background-size: 100% 100%;
  433. display: inline-block;
  434. }
  435. .icon2 {
  436. width: 68px;
  437. height: 64px;
  438. background: url('@/assets/images/map/rightMenu/ironTower/icon2.png') no-repeat;
  439. background-size: 100% 100%;
  440. display: inline-block;
  441. }
  442. .icon3 {
  443. width: 73px;
  444. height: 72px;
  445. background: url('@/assets/images/map/rightMenu/ironTower/icon3.png') no-repeat;
  446. background-size: 100% 100%;
  447. display: inline-block;
  448. }
  449. .icon4 {
  450. width: 82px;
  451. height: 66px;
  452. background: url('@/assets/images/map/rightMenu/ironTower/icon4.png') no-repeat;
  453. background-size: 100% 100%;
  454. display: inline-block;
  455. }
  456. .icon5 {
  457. width: 49px;
  458. height: 71px;
  459. background: url('@/assets/images/map/rightMenu/ironTower/icon5.png') no-repeat;
  460. background-size: 100% 100%;
  461. display: inline-block;
  462. }
  463. .icon6 {
  464. width: 59px;
  465. height: 72px;
  466. background: url('@/assets/images/map/rightMenu/ironTower/icon6.png') no-repeat;
  467. background-size: 100% 100%;
  468. display: inline-block;
  469. }
  470. .icon7 {
  471. width: 73px;
  472. height: 73px;
  473. background: url('@/assets/images/map/rightMenu/ironTower/icon7.png') no-repeat;
  474. background-size: 100% 100%;
  475. display: inline-block;
  476. }
  477. .icon8 {
  478. width: 69px;
  479. height: 71px;
  480. background: url('@/assets/images/map/rightMenu/ironTower/icon8.png') no-repeat;
  481. background-size: 100% 100%;
  482. display: inline-block;
  483. }
  484. }
  485. }
  486. </style>