SentryPage.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. <!--
  2. *@description: 哨兵基础页
  3. *@author: yh Fu
  4. *@date: 2025-08-29 11:16:01
  5. *@version: V1.0.5
  6. -->
  7. <template>
  8. <div class="visual-con hz_body">
  9. <div class="s_header">
  10. <div class="head_btn">
  11. <div @click="jumpTo('/SentryCockpit',0)" :class="routerIdx == 0 ? 'on' : ''">
  12. <i>驾驶舱</i>
  13. </div>
  14. <div @click="jumpTo('/SenEquipmentCenter',1)" :class="routerIdx == 1 ? 'on' : ''">
  15. <i>设备中心</i>
  16. </div>
  17. </div>
  18. <div class="header_tit"><i>{{title}}</i></div>
  19. <div class="head_btn">
  20. <div @click="jumpTo('/SenEventCenter',2)" :class="routerIdx == 2 ? 'on' : ''">
  21. <i>事件中心</i>
  22. </div>
  23. <div @click="jumpTo('/useCenter',3)" :class="routerIdx == 3 ? 'on' : ''">
  24. <i>用户中心</i>
  25. </div>
  26. </div>
  27. <div class="head_tx">
  28. <span><img src="../assets/images/sentinel/hz_tx.png" /></span>
  29. </div>
  30. </div>
  31. <div class="visual-body">
  32. <!--主体-->
  33. <router-view>
  34. </router-view>
  35. <!-- 哨兵详情弹窗 -->
  36. <div class="tk_div" v-show="isDetailVisible">
  37. <div class="tk1 tk_bor" style="width: 371px;height: 310px;">
  38. <h1>
  39. <span :title="detailInfo.deviceName || '--'" style="display: inline-block;overflow: hidden;width: 62%;text-overflow: ellipsis;">{{ detailInfo.deviceName || '--' }}</span>
  40. <i class="el-icon el-icon-close" style="margin-left: 5%;cursor: pointer;" @click="closeDetail"></i>
  41. <i>{{ detailInfo.workingStatus == '0' ? '在线' : '离线' }}</i>
  42. </h1>
  43. <p>设备名称:{{ detailInfo.deviceName || '--' }}</p>
  44. <p>设备类型:{{ detailInfo.deviceTypeText || '--' }}</p>
  45. <p>设备监测指标:{{ detailInfo.threshold || '--' }}</p>
  46. <p>品牌:{{ detailInfo.brand || '--' }}</p>
  47. <p>所在街道:{{ detailInfo.address || '--' }}</p>
  48. <p>历史数值:<a @click="toggleDisplay(detailInfo.deviceCode)">详情</a></p>
  49. </div>
  50. <div class="tk2 tk_bor" v-if="isVisible" style="position: absolute;width: 466px;height: 455px;left: 98%;">
  51. <h1>哨兵详情</h1>
  52. <div id="sbxqChart" ref="MyChart"></div>
  53. </div>
  54. </div>
  55. <!-- 地图 -->
  56. <supermap ref="supermap" style="width: 100%;height: 100vh;" @preview="preview">
  57. </supermap>
  58. </div>
  59. </div>
  60. </template>
  61. <script>
  62. import Cookies from 'js-cookie'
  63. import supermap from '@/components/supermap-2.5d' //超图
  64. import {
  65. getUserProfile
  66. } from "@/api/system/user";
  67. import '../assets/styles/hz_body.css';
  68. import {
  69. selectConfigKey
  70. } from "@/api/system/config";
  71. import {
  72. selectByDeviceId,
  73. selectDailyThreshold
  74. } from "@/api/sentinel"
  75. let echarts = require("echarts");
  76. export default {
  77. name: 'MyChart',
  78. components: {
  79. supermap
  80. },
  81. metaInfo() {
  82. return {
  83. title: '四平市智慧哨兵监管平台',
  84. meta: [{
  85. charset: "utf-8"
  86. },
  87. {
  88. name: "viewport",
  89. content: "width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
  90. }
  91. ]
  92. }
  93. },
  94. data() {
  95. return {
  96. title: '四平市智慧哨兵监管平台',
  97. routerIdx:0, // 当前导航索引
  98. detailInfo:{}, // 设备详情信息
  99. isVisible: false, // 初始时设置为false,不显示内容
  100. isDetailVisible:false, // 设备弹窗显隐flag
  101. }
  102. },
  103. created() {
  104. },
  105. mounted() {
  106. // 初始定向到驾驶舱
  107. this.$router.push({
  108. path:'/SentryCockpit'
  109. })
  110. // 初始化地图数据
  111. this.getSuperMapUrl();
  112. setTimeout(() => {
  113. this.title = '四平市智慧哨兵监管平台'
  114. }, 1000);
  115. },
  116. methods:{
  117. closeDetail(){
  118. this.isDetailVisible = false
  119. this.isVisible = false
  120. },
  121. preview(e){
  122. selectByDeviceId({id:e.id}).then(res => {
  123. this.detailInfo = res.data
  124. this.isDetailVisible = true
  125. })
  126. },
  127. toggleDisplay(deviceCode) {
  128. this.isVisible = !this.isVisible; // 点击按钮时切换isVisible的值
  129. if(this.isVisible){
  130. selectDailyThreshold(deviceCode).then(res => {
  131. this.initChart(res.data)
  132. })
  133. }
  134. },
  135. jumpTo(path,idx){
  136. if(this.routerIdx == idx) return;
  137. // 重置哨兵详情态
  138. this.isDetailVisible = false
  139. this.isVisible = false
  140. // 地图清点
  141. this.$refs.supermap.clearM();
  142. this.routerIdx = idx
  143. this.$router.push({
  144. path
  145. })
  146. },
  147. initChart(data){
  148. // 基于准备好的dom,初始化echarts实例
  149. const myChart = echarts.init(document.getElementById('sbxqChart'))
  150. let xdata = data.time //x轴
  151. let dataArr = data.value //value
  152. let dashedArr = data.threshold
  153. let titleName = "阈值";
  154. let titleNames = "实际值";
  155. let option = {
  156. backgroundColor: "rgba(25,44,59,.4)",
  157. grid: {
  158. left: "5%",
  159. bottom: "10%",
  160. top: "18%",
  161. containLabel: true,
  162. },
  163. tooltip: {
  164. trigger: "axis",
  165. axisPointer: {
  166. type: "shadow",
  167. },
  168. },
  169. legend: {
  170. show: true,
  171. x: "center",
  172. y: 20,
  173. textStyle: {
  174. color: "#fff", // 图例文字颜色
  175. fontSize: 16,
  176. },
  177. },
  178. xAxis: {
  179. type: "category",
  180. boundaryGap: false,
  181. data: xdata,
  182. axisLabel: {
  183. show: true,
  184. textStyle: {
  185. color: "#fff",
  186. },
  187. },
  188. axisLine: {
  189. lineStyle: {
  190. color: "transparent",
  191. width: 2, //这里是为了突出显示加上的
  192. },
  193. },
  194. },
  195. "dataZoom": [
  196. {
  197. "show": true,
  198. "height": 12,
  199. "xAxisIndex": [
  200. 0
  201. ],
  202. "bottom": "8%",
  203. "start": 0,
  204. "end": 50,
  205. "handleIcon": "path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z",
  206. "handleSize": "110%",
  207. "handleStyle": {
  208. "color": "#d3dee5"
  209. },
  210. "textStyle": {
  211. "color": "#fff"
  212. },
  213. "borderColor": "#90979c"
  214. },
  215. {
  216. "type": "inside",
  217. "show": true,
  218. "height": 15,
  219. "start": 1,
  220. "end": 35
  221. }
  222. ],
  223. yAxis: [
  224. {
  225. type: "value",
  226. name: "(%vol)",
  227. nameTextStyle: {
  228. color: "#fff",
  229. },
  230. axisLabel: {
  231. formatter: "{value}",
  232. textStyle: {
  233. color: "#fff",
  234. },
  235. },
  236. axisLine: {
  237. lineStyle: {
  238. color: "transparent",
  239. width: 2, //这里是为了突出显示加上的
  240. },
  241. },
  242. axisTick: {
  243. show: false,
  244. },
  245. splitLine: {
  246. show: true,
  247. lineStyle: {
  248. color: "#11366e",
  249. },
  250. },
  251. },
  252. ],
  253. series: [
  254. {
  255. name: titleName,
  256. type: "line",
  257. smooth: true,
  258. symbol: "none",
  259. itemStyle: {
  260. normal: {
  261. lineStyle: {
  262. type: "dashed",
  263. },
  264. color: "#01F699", //拐点的颜色
  265. borderColor: "#01F699", //拐点边框的颜色
  266. },
  267. },
  268. data: dashedArr,
  269. },
  270. {
  271. name: titleNames,
  272. type: "line",
  273. stack: "总量",
  274. smooth: true, //平滑曲线显示
  275. symbol: "circle", //标记的图形为实心圆
  276. symbolSize: 8,
  277. itemStyle: {
  278. normal: {
  279. color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
  280. {
  281. offset: 0,
  282. color: "rgba(3,191,255,1)",
  283. },
  284. {
  285. offset: 1,
  286. color: "rgba(18,93,236,1)",
  287. },
  288. ]),
  289. areaStyle: {
  290. color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
  291. {
  292. offset: 0,
  293. color: "rgba(3,191,255,.3)",
  294. },
  295. {
  296. offset: 1,
  297. color: "rgba(18,93,236,.3)",
  298. },
  299. ]),
  300. },
  301. },
  302. },
  303. data: dataArr,
  304. },
  305. ],
  306. };
  307. myChart.setOption(option);
  308. },
  309. getSuperMapUrl() {
  310. getUserProfile().then(response => {
  311. let mapDeptId = response.mapDeptId
  312. let num = 0;
  313. if (mapDeptId == "365") {
  314. num = 0;
  315. } else if (mapDeptId == "369") {
  316. num = 1;
  317. } else if (mapDeptId == "371") {
  318. num = 2;
  319. } else if (mapDeptId == "373") {
  320. num = 3;
  321. } else if (mapDeptId == "372") {
  322. num = 4;
  323. } else if (mapDeptId == "370") {
  324. num = 5;
  325. }
  326. this.$refs.supermap.removeAllviewer(mapDeptId, -1);
  327. });
  328. },
  329. }
  330. }
  331. </script>
  332. <style rel="stylesheet/scss" lang="scss">
  333. .visual-con .el-input__inner {
  334. border: 1px solid #3bb8a4;
  335. background-color: rgba(20, 107, 115, 0.3);
  336. color: #fff;
  337. }
  338. .hz_body {
  339. position: relative;
  340. }
  341. i,
  342. b,
  343. u {
  344. font-style: normal;
  345. text-decoration: none;
  346. }
  347. /*//头部通用*/
  348. .s_header {
  349. width: 100%;
  350. height: 110px;
  351. position: absolute;
  352. top: 0px;
  353. left: 0px;
  354. z-index: 99;
  355. display: flex;
  356. flex-direction: row;
  357. justify-content: space-around;
  358. background: url("../assets/images/sentinel/hz_header.png") no-repeat center;
  359. background-size: contain;
  360. }
  361. .s_header .header_tit {
  362. display: block;
  363. width: 1000px;
  364. height: 109px;
  365. line-height: 65px;
  366. text-align: center;
  367. }
  368. .s_header .header_tit i {
  369. font-family: 'ysbth';
  370. font-size: 40px;
  371. /*text-shadow: 3px 5.196px 0px rgba(17, 20, 22, 0.22);*/
  372. letter-spacing: 4px;
  373. background: linear-gradient(180deg, #fff 0%, #b0d3f1 100%);
  374. -webkit-background-clip: text;
  375. color: transparent;
  376. mix-blend-mode: screen;
  377. /*text-shadow: 3px 5px 0px rgba(17, 20, 22, 0.22);*/
  378. display: block;
  379. text-align: center;
  380. }
  381. .s_header .head_btn {
  382. width: 316px;
  383. }
  384. .s_header .head_tx {
  385. display: block;
  386. position: absolute;
  387. right: 20px;
  388. }
  389. .s_header .head_btn div {
  390. display: inline-block;
  391. background: url("../assets/images/sentinel/hz_btnbg.png") no-repeat center;
  392. width: 138px;
  393. margin: 0px 10px;
  394. height: 29px;
  395. line-height: 29px;
  396. text-align: center;
  397. transition: all 0.3s;
  398. }
  399. .s_header .head_btn div i {
  400. display: block;
  401. font-family: 'ysbth';
  402. font-size: 20px;
  403. background: linear-gradient(180deg, #95dded 60%, #fff 40%);
  404. -webkit-background-clip: text;
  405. color: transparent;
  406. mix-blend-mode: screen;
  407. /*text-shadow: 3px 5px 0px rgba(17, 20, 22, 0.22);*/
  408. display: block;
  409. text-align: center;
  410. }
  411. .s_header .head_btn div.on,
  412. .s_header .head_btn div:hover {
  413. background: url("../assets/images/sentinel/hz_btnbg_on.png") no-repeat center;
  414. box-shadow: none;
  415. filter: brightness(170%);
  416. }
  417. .con_left {
  418. position: absolute;
  419. z-index: 99;
  420. left: 30px;
  421. top: 100px;
  422. width: 320px;
  423. background: rgba(0, 0, 0, 0.55);
  424. padding: 0px 10px 20px 10px !important;
  425. }
  426. .con_right {
  427. position: absolute;
  428. z-index: 99;
  429. right: 30px;
  430. top: 100px;
  431. width: 320px;
  432. background: rgba(0, 0, 0, 0.55);
  433. padding: 0px 10px 20px 10px !important;
  434. .list_tit {
  435. background: url("../assets/images/sentinel/hz_list_tit.png") no-repeat center;
  436. background-size: 100% 100%;
  437. height: 44px;
  438. line-height: 44px;
  439. padding-left: 20px;
  440. font-family: 'ysbth';
  441. font-size: 20px;
  442. color: #fff;
  443. margin-bottom: 10px;
  444. }
  445. }
  446. .con_left_js {
  447. width: 400px !important;
  448. }
  449. .con_left .list_tit {
  450. background: url("../assets/images/sentinel/hz_list_tit.png") no-repeat center;
  451. background-size: 100% 100%;
  452. height: 44px;
  453. line-height: 44px;
  454. padding-left: 20px;
  455. font-family: 'ysbth';
  456. font-size: 20px;
  457. color: #fff;
  458. margin-bottom: 10px;
  459. }
  460. .con_left .el-select {
  461. width: 100%;
  462. margin-bottom: 8px;
  463. }
  464. .el-select-dropdown {
  465. border: 1px solid #3bb7a3;
  466. background-color: #0c3038;
  467. }
  468. .el-select-dropdown__item {
  469. color: #b0d3f1;
  470. }
  471. .el-select-dropdown__item.hover,
  472. .con_left .el-select-dropdown__item:hover {
  473. background-color: #0a4c5c;
  474. }
  475. .el-select-dropdown__item.selected {
  476. color: #3bb7a3;
  477. }
  478. .el-input__inner {
  479. color: #b0d3f1;
  480. height: 35px;
  481. line-height: 35px;
  482. }
  483. .el-input__icon {
  484. line-height: 35px;
  485. color: #5bf9e0;
  486. }
  487. .sp_list {
  488. margin-top: 10px !important;
  489. }
  490. .sp_list dt {
  491. background: linear-gradient(to right, rgba(40, 115, 124, 0.68), rgba(38, 75, 80, 0.68));
  492. height: 38px;
  493. line-height: 38px;
  494. margin-bottom: 5px;
  495. }
  496. .sp_list dd {
  497. display: flex;
  498. flex-direction: row;
  499. cursor: pointer;
  500. transition: all 0.3s;
  501. }
  502. .sp_list dd:hover {
  503. filter: brightness(170%) hue-rotate(-20deg);
  504. }
  505. .sp_list dd:nth-child(odd) {
  506. background: linear-gradient(to right, rgba(40, 115, 124, 0.68), rgba(38, 75, 80, 0.68));
  507. height: 38px;
  508. line-height: 38px;
  509. margin-bottom: 5px;
  510. }
  511. .sp_list dd:nth-child(even) {
  512. background: linear-gradient(to right, rgba(40, 115, 124, 0.38), rgba(38, 75, 80, 0.38));
  513. height: 38px;
  514. line-height: 38px;
  515. margin-bottom: 5px;
  516. }
  517. .sp_list span {
  518. display: inline-block;
  519. text-align: left;
  520. font-size: 14px;
  521. color: #acdfe5;
  522. height: 38px;
  523. line-height: 38px;
  524. }
  525. .sp_list span.dt1 {
  526. width: 60px;
  527. background: url("../assets/images/sentinel/hz_list_j.png") no-repeat left;
  528. padding-left: 15px;
  529. }
  530. .sp_list span.dt2 {
  531. width: 200px;
  532. text-align: left;
  533. }
  534. .sp_list span.dt3 {
  535. width: 40px;
  536. text-align: center;
  537. line-height: 38px;
  538. position: relative;
  539. }
  540. .sp_list span.dt3 img {
  541. display: inline-block;
  542. position: absolute;
  543. top: 10px;
  544. left: 11px;
  545. }
  546. .el-pagination {
  547. width: 100%;
  548. margin-top: 20px !important;
  549. }
  550. .el-pagination.is-background .btn-next,
  551. .el-pagination.is-background .btn-prev,
  552. .el-pagination.is-background .el-pager li {
  553. margin: 0 2px;
  554. background-color: unset !important;
  555. color: #47c5b0;
  556. min-width: 26px;
  557. }
  558. .el-pagination.is-background .el-pager li:not(.disabled).active {
  559. background-color: #47c5b0 !important;
  560. color: #FFF;
  561. }
  562. .el-pagination.is-background .el-pager li:not(.disabled):hover {
  563. background-color: #47c5b0 !important;
  564. color: #FFF;
  565. }
  566. .el-pager li:hover {
  567. background-color: #47c5b0 !important;
  568. color: #FFF;
  569. }
  570. .hei_scroll {
  571. overflow-y: scroll;
  572. }
  573. .hei_scroll::-webkit-scrollbar {
  574. width: 0px;
  575. height: 0px;
  576. }
  577. .hei56 {
  578. height: 56vh;
  579. }
  580. .qydw1 {
  581. position: absolute;
  582. top: 60%;
  583. left: 40%;
  584. display: block;
  585. width: 54px;
  586. height: 77px;
  587. }
  588. .qydw2 {
  589. position: absolute;
  590. top: 50%;
  591. left: 70%;
  592. display: block;
  593. width: 54px;
  594. height: 77px;
  595. }
  596. .qydw3 {
  597. position: absolute;
  598. top: 40%;
  599. left: 80%;
  600. display: block;
  601. width: 54px;
  602. height: 77px;
  603. }
  604. .tk_div {
  605. position: absolute;
  606. top: 24%;
  607. left: 32.2%;
  608. z-index: 98;
  609. display: flex;
  610. flex-direction: row;
  611. }
  612. .tk_bor {
  613. padding: 15px !important;
  614. border: 3px solid #28727e;
  615. box-shadow: 0px 0px 24px #28727e;
  616. background: rgba(0, 0, 0, 0.39);
  617. }
  618. .info-list {
  619. display: flex;
  620. flex-wrap: wrap;
  621. margin-bottom: 20px !important;
  622. p {
  623. width: 50%;
  624. padding-left: 20px;
  625. background: url("../assets/images/sentinel/hz_k.png") no-repeat left;
  626. background-size: 12px;
  627. font-size: 14px;
  628. color: #fff;
  629. line-height: 60px;
  630. }
  631. }
  632. .tk_bor h1 {
  633. display: flex;
  634. align-items: center;
  635. justify-content: space-between;
  636. padding-left: 20px;
  637. background: url("../assets/images/sentinel/hz_k.png") no-repeat left;
  638. font-size: 18px;
  639. color: #e0e5fa;
  640. font-weight: bold;
  641. height: 38px;
  642. line-height: 38px;
  643. }
  644. .tk_bor h1 i {
  645. display: inline-block;
  646. float: right;
  647. background: #3bad96;
  648. padding: 0px 10px;
  649. color: #fff;
  650. font-size: 16px;
  651. height: 30px;
  652. line-height: 30px;
  653. position: relative;
  654. border-radius: 4px;
  655. }
  656. .tk_bor h1 i::after {
  657. display: block;
  658. content: '';
  659. border-bottom: 9px solid transparent;
  660. border-right: 9px solid #3bad96;
  661. border-top: 9px solid transparent;
  662. position: absolute;
  663. left: -8px;
  664. top: 8px;
  665. }
  666. .tk_bor p {
  667. padding-left: 20px;
  668. background: url("../assets/images/sentinel/hz_k.png") no-repeat left;
  669. background-size: 12px;
  670. font-size: 16px;
  671. color: #fff;
  672. line-height: 35px;
  673. }
  674. .tk_bor p a {
  675. color: #6bf5f2;
  676. text-underline-offset: 0.4em;
  677. text-decoration: underline;
  678. }
  679. .tk_bor p a:hover {
  680. color: #6bf5f2;
  681. text-underline-offset: 0.4em;
  682. text-decoration: underline;
  683. cursor: pointer;
  684. }
  685. .tk_bor .icon{
  686. display: flex;
  687. align-items: center;
  688. float: right;
  689. img{
  690. margin-left: 10px;
  691. }
  692. }
  693. .tk1 {
  694. position: relative;
  695. margin-right: 20px !important;
  696. }
  697. .tk1::after {
  698. display: block;
  699. content: '';
  700. background: url("../assets/images/sentinel/hz_down.png") no-repeat left;
  701. width: 46px;
  702. height: 40px;
  703. position: absolute;
  704. bottom: -40px;
  705. left: 50%;
  706. transform: translateX(-50%);
  707. }
  708. #sbxqChart {
  709. width: 100%;
  710. height: 91%;
  711. }
  712. //图表设备分析
  713. .sb_fx {
  714. width: 100%;
  715. height: 300px;
  716. }
  717. .yh_fx {
  718. width: 100%;
  719. height: 260px;
  720. }
  721. .sj_fx {
  722. width: 100%;
  723. height: 280px;
  724. }
  725. </style>
  726. <style rel="stylesheet/scss" lang="scss" scoped>
  727. @import '@/assets/styles/base.scss';
  728. </style>