index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. <template>
  2. <div class="app-container SiteDistribution" style="padding:0">
  3. <div class="top">
  4. <div class="statistics" v-if="mode == 1">
  5. <div class="item" v-for="(item, index) in statistics" :key="index">
  6. <img :src="item.img" alt="">
  7. <div class="text">
  8. <span :style="{ color: item.color }">{{ item.num }}</span>
  9. <span>{{ item.text }}</span>
  10. </div>
  11. </div>
  12. </div>
  13. <div class="query" v-if="mode == 2">
  14. <a-tree-select
  15. v-model:value="city"
  16. :tree-data="cityArray"
  17. placeholder="请选择城市"
  18. tree-default-expand-all
  19. class="citySelect"
  20. style="width:120px;margin-right:10px;"
  21. >
  22. </a-tree-select>
  23. <a-select
  24. v-model:value="siteSlect"
  25. placeholder=""
  26. :options="siteArray"
  27. @change="handleChange"
  28. class="state"
  29. >
  30. </a-select>
  31. <a-input-search
  32. v-model:value="siteName"
  33. placeholder="站点名称"
  34. enter-button
  35. @search="onSearch"
  36. class="siteName"
  37. />
  38. </div>
  39. <div class="modeSwitching">
  40. <div @click="switchMode(1)" :class="{ active: mode == 1 }">
  41. <img src="@/assets/svg/map.svg" alt="">
  42. </div>
  43. <div @click="switchMode(2)" :class="{ active: mode == 2 }">
  44. <img src="@/assets/svg/menu.svg" alt="">
  45. </div>
  46. </div>
  47. <div class="city">
  48. </div>
  49. </div>
  50. <div class="middle">
  51. <div id="map" ref="map" style="width:100%;height:100%;" v-if="mode == 1"></div>
  52. <div class="table" v-if="mode == 2">
  53. <el-table :data="tableData" border stripe :header-cell-style="headClass" height="71vh" style="overflow-y: auto;">
  54. <el-table-column
  55. fixed
  56. prop="platformAreaName"
  57. label="站点名称"
  58. width=""
  59. ></el-table-column>
  60. <el-table-column
  61. fixed
  62. prop="platformAreaName"
  63. label="分组名称"
  64. width=""
  65. ></el-table-column>
  66. <el-table-column
  67. fixed
  68. prop="platformAreaName"
  69. label="实时负荷"
  70. width=""
  71. ></el-table-column>
  72. <el-table-column
  73. fixed
  74. prop="platformAreaName"
  75. label="站点状态"
  76. width=""
  77. ></el-table-column>
  78. <el-table-column
  79. fixed
  80. prop="platformAreaName"
  81. label="设备总数"
  82. width=""
  83. ></el-table-column>
  84. <el-table-column
  85. fixed
  86. prop="platformAreaName"
  87. label="告警数"
  88. width=""
  89. ></el-table-column>
  90. <el-table-column
  91. fixed
  92. prop="platformAreaName"
  93. label="电话"
  94. width=""
  95. ></el-table-column>
  96. <el-table-column
  97. fixed
  98. prop="platformAreaName"
  99. label="地址"
  100. width=""
  101. ></el-table-column>
  102. </el-table>
  103. <div class="paginationBlock">
  104. <el-pagination
  105. @size-change="handleSizeChange"
  106. @current-change="handleCurrentChange"
  107. :current-page="currentPage"
  108. :page-sizes="[15, 20, 25, 30]"
  109. :page-size="pageSize"
  110. layout="total, sizes, prev, pager, next, jumper"
  111. :total="total"
  112. ></el-pagination>
  113. </div>
  114. </div>
  115. </div>
  116. <div class="bottom" v-if="mode == 1">
  117. <div class="itemWrap">
  118. <div class="item" @click="site(4)" :class="{ active: siteState.includes(4) }" v-if="siteState.includes(1)">
  119. <img src="@/assets/svg/name.svg" alt="">
  120. <p>名称</p>
  121. </div>
  122. <div class="item" @click="site(3)" :class="{ active: siteState.includes(3) }" v-if="siteState.includes(1)">
  123. <img src="@/assets/svg/wifi.svg" alt="">
  124. <p>在线</p>
  125. </div>
  126. <div class="item" @click="site(2)" :class="{ active: siteState.includes(2) }" v-if="siteState.includes(1)">
  127. <img src="@/assets/svg/alerm.svg" alt="">
  128. <p>告警</p>
  129. </div>
  130. </div>
  131. <div class="item" @click="site(1)" :class="{ active: siteState.includes(1) }">
  132. <img src="@/assets/svg/site.svg" alt="">
  133. <p>站点</p>
  134. </div>
  135. </div>
  136. </div>
  137. </template>
  138. <script setup>
  139. // import alarmTotal from './alarmTotal'
  140. // import { useStore } from 'vuex'
  141. // import { computed, defineComponent, onMounted, ref } from 'vue'
  142. // import * as api from '@/api/alarmManage/index'
  143. // import { ElMessage } from 'element-plus'
  144. // import { useRouter } from 'vue-router'
  145. import zhanDian from "@/assets/images/zhanDian.png";
  146. import liXian from "@/assets/images/liXian.png";
  147. import weiChuLi from "@/assets/images/weiChuLi.png";
  148. import sheBei from "@/assets/images/sheBei.png";
  149. import { initMap, markers, labelState } from "@/assets/js/baiduMap.js";
  150. import { ref,onMounted } from "vue";
  151. onMounted(() => {
  152. init()
  153. })
  154. const mode = ref(1)//1:列表模式 2:地图模式
  155. const siteState = ref([]) //true:站点显示 false:站点隐藏
  156. const statistics = ref([
  157. { num:1, img:zhanDian, text:'站点总数', color:'#2ACDDA'},
  158. { num:2, img:liXian, text:'离线站总数', color:'#AAA' },
  159. { num:3, img:weiChuLi, text:'未处理告警数', color:'#FFB00A' },
  160. { num:4, img:sheBei, text:'设备数', color:'#2FA6FF' }
  161. ])
  162. const markerArray = ref([
  163. { longitude:121.486647, latitude:31.220165, name:"公司名称",state:0,tatal:100,alert:4,tel:"13120222222",address:"公司地址"},
  164. { longitude:121.486647, latitude:31.010165, name:"公司名称2",state:1,tatal:10,alert:2,tel:"13120222222",address:"公司地址"},
  165. { longitude:121.486647, latitude:30.010165, name:"公司名称3",state:0,tatal:1,alert:0,tel:"13120222222",address:"公司地址"}
  166. ]) //点标记集
  167. const dian = ref([])
  168. // 表格数据
  169. const cityArray = ref([
  170. {
  171. value: '1',
  172. label: '上海',
  173. children: [
  174. {
  175. value: '11',
  176. label: '青浦',
  177. },
  178. {
  179. value: '12',
  180. label: '松江',
  181. },
  182. ]
  183. },
  184. {
  185. value: '2',
  186. label: '全部',
  187. },
  188. ])
  189. const city = ref(1)
  190. const siteSlect = ref("")
  191. const siteArray = ref([
  192. { value:"", label:"全部" },
  193. { value:"1", label:"在线" },
  194. { value:"0", label:"离线" },
  195. ])
  196. const siteName = ref("")
  197. const total = ref(100)
  198. const pageSize = ref(15)
  199. const currentPage = ref(1)
  200. const tableData = ref([
  201. { platformAreaName: "名称"},
  202. { platformAreaName: "名称"},
  203. { platformAreaName: "名称"},
  204. { platformAreaName: "名称"},
  205. { platformAreaName: "名称"},
  206. { platformAreaName: "名称"},
  207. { platformAreaName: "名称"},
  208. { platformAreaName: "名称"},
  209. { platformAreaName: "名称"},
  210. { platformAreaName: "名称"},
  211. { platformAreaName: "名称"},
  212. { platformAreaName: "名称"},
  213. { platformAreaName: "名称"},
  214. { platformAreaName: "名称"},
  215. { platformAreaName: "名称"},
  216. { platformAreaName: "名称"},
  217. { platformAreaName: "名称"},
  218. { platformAreaName: "名称"},
  219. { platformAreaName: "名称"},
  220. { platformAreaName: "名称"},
  221. { platformAreaName: "名称"},
  222. { platformAreaName: "名称"},
  223. { platformAreaName: "名称"},
  224. { platformAreaName: "名称"},
  225. // { platformAreaName: "名称"},
  226. // { platformAreaName: "名称"},
  227. // { platformAreaName: "名称"},
  228. // { platformAreaName: "名称"},
  229. // { platformAreaName: "名称"},
  230. // { platformAreaName: "名称"},
  231. ])
  232. //初始化
  233. function init(){
  234. initMap()
  235. site(1)
  236. }
  237. /**
  238. * 切换模式
  239. * @param {Number} val 1:列表模式 2:地图模式
  240. */
  241. function switchMode(val) {
  242. mode.value = val
  243. if(val == 1){
  244. setTimeout(() => {
  245. init()
  246. site(1)
  247. })
  248. }
  249. }
  250. /**
  251. * 站点隐、显控制
  252. */
  253. function site(val){
  254. //站点隐现其他项
  255. siteState.value = siteState.value.includes(val) ? siteState.value.filter(item => item!== val) : [...siteState.value, val]
  256. if(val == 1 || val == 2 || val == 3) {
  257. //站点隐现(全部/在线/告警)
  258. if(siteState.value.includes(1)){
  259. dian.value = []
  260. //站点在线并告警 / 所有站点
  261. if(siteState.value.includes(2) && siteState.value.includes(3) || !siteState.value.includes(2) && !siteState.value.includes(3)){
  262. markers(markerArray.value)
  263. }
  264. //告警设备隐现(离线)
  265. if(siteState.value.includes(2) && !siteState.value.includes(3)){
  266. for(let i=0;i<markerArray.value.length;i++){
  267. if(!markerArray.value[i].state){
  268. dian.value.push(markerArray.value[i])
  269. }
  270. }
  271. markers(dian.value)
  272. }
  273. //在线设备隐现
  274. if(!siteState.value.includes(2) && siteState.value.includes(3)){
  275. for(let i=0;i<markerArray.value.length;i++){
  276. if(markerArray.value[i].state){
  277. dian.value.push(markerArray.value[i])
  278. }
  279. }
  280. markers(dian.value)
  281. }
  282. }
  283. if(!siteState.value.includes(1)){
  284. markers()
  285. }
  286. }
  287. //文本标注隐现4
  288. if(siteState.value.includes(4)){
  289. if(siteState.value.includes(1)){
  290. labelState(dian.value.length == 0 ? markerArray.value : dian.value)
  291. }else{
  292. labelState()
  293. }
  294. }else{
  295. labelState()
  296. }
  297. }
  298. </script>
  299. <style lang="scss" scoped>
  300. .SiteDistribution{
  301. position: relative;
  302. overflow: hidden;
  303. .top{
  304. .statistics{
  305. position: absolute;
  306. z-index: 1;
  307. top:20px;
  308. left:20px;
  309. width:40%;
  310. height:78px;
  311. display: flex;
  312. flex-direction: row;
  313. .item{
  314. width:100%;
  315. height:100%;
  316. background: #fff;
  317. padding:14px 0 3% 3%;
  318. box-sizing: border-box;
  319. display: flex;
  320. flex-direction: row;
  321. img{
  322. vertical-align: middle;
  323. margin-right:10px;
  324. width:50px;
  325. height:50px;
  326. }
  327. >div{
  328. display: flex;
  329. flex-direction: column;
  330. color:#333;
  331. font-size: 14px;
  332. margin-top:2px;
  333. span:nth-child(1){
  334. font-weight: bold;
  335. font-size: 16px;
  336. margin-bottom:10px;
  337. }
  338. }
  339. }
  340. }
  341. .modeSwitching{
  342. position: absolute;
  343. z-index: 1;
  344. top:20px;
  345. right:20px;
  346. width: 68px;
  347. height: 32px;
  348. display: flex;
  349. border-radius: 2px;
  350. background: #fff;
  351. font-size: 22px;
  352. cursor: pointer;
  353. box-shadow: 0px 3px 7px 0px rgba(0,0,0,0.07);
  354. >div{
  355. width:50%;
  356. height:100%;
  357. line-height: 130%;;
  358. display: inline-block;
  359. background: none;
  360. text-align: center;
  361. img{
  362. width:16px;
  363. transform: translateX(80px);
  364. filter: drop-shadow(#333 -80px 1px 0px);
  365. }
  366. }
  367. .active{
  368. background: #48A4FF;
  369. img{
  370. width:16px;
  371. transform: translateX(80px);
  372. filter: drop-shadow(#fff -80px 1px 0px);
  373. }
  374. }
  375. }
  376. .query{
  377. position: absolute;
  378. right:100px;
  379. top:20px;
  380. z-index: 1;
  381. >div{
  382. display: inline-block;
  383. margin-right:10px;
  384. }
  385. .state{
  386. width:80px;
  387. }
  388. .siteName{
  389. width:200px;
  390. }
  391. }
  392. }
  393. .middle{
  394. width:100%;
  395. height:100%;
  396. position: absolute;
  397. z-index: 0;
  398. .table{
  399. padding:20px;
  400. margin-top:40px;
  401. }
  402. }
  403. .bottom{
  404. position: absolute;
  405. z-index: 1;
  406. bottom:20px;
  407. right:20px;
  408. .item{
  409. padding:4px 8px 2px;
  410. text-align: center;
  411. border-bottom:1px solid #eee;
  412. background: #fff;
  413. cursor: pointer;
  414. img{
  415. font-size: 14px;
  416. transform: translateX(80px);
  417. filter: drop-shadow(#333 -80px 1px 0px);
  418. }
  419. >p{
  420. font-size: 12px;
  421. color:#333;
  422. margin:6px 0 0px;
  423. }
  424. }
  425. .item:last-child(1){
  426. border-bottom:none;
  427. }
  428. .active{
  429. background: #48A4FF;
  430. img{
  431. transform: translateX(80px);
  432. filter: drop-shadow(#fff -80px 1px 0px);
  433. }
  434. p{
  435. color:#fff;
  436. }
  437. }
  438. }
  439. }
  440. </style>
  441. <style>
  442. .BMap_copCtrl,.anchorBL{
  443. display: none;
  444. }
  445. </style>
  446. <style lang="scss">
  447. .BMap_bubble_pop{
  448. width:270px !important;
  449. padding:0 !important;
  450. border-radius: 4px !important;
  451. box-shadow: 0px 3px 7px 0px rgba(0,0,0,0.07);
  452. margin-top:35px;
  453. margin-left:-26px;
  454. // background: linear-gradient(to bottom right, #fff, #fff);
  455. .BMap_bubble_center,.BMap_bubble_content,.boxs{
  456. width:270px !important;
  457. }
  458. .BMap_bubble_center{
  459. margin-top:-30px;
  460. .boxs{
  461. .title{
  462. font-size: 16px;
  463. line-height: 40px;
  464. padding-left:20px;
  465. }
  466. .content{
  467. padding:0 20px 4px;
  468. border-top: 1px solid #E9E9F3;
  469. >div{
  470. border-top: 1px solid #E9E9F3;
  471. height:40px;
  472. line-height: 40px;
  473. display: flex;
  474. justify-content: space-between;
  475. }
  476. >div:nth-child(1){
  477. border-top:none;
  478. }
  479. }
  480. }
  481. }
  482. .BMap_bubble_center:after{
  483. content: ""; /* 伪元素不包含内容 */
  484. position: absolute; /* 绝对定位相对于.arrow-down */
  485. top: 100%; /* 向下定位 */
  486. left: 50%; /* 水平居中定位 */
  487. width: 0; /* 必须设置为0,因为我们不显示宽度 */
  488. height: 0; /* 必须设置为0,因为我们不显示高度 */
  489. margin-left: -15px; /* 根据需要调整,这里是让箭头中心对齐 */
  490. border-left: 15px solid transparent; /* 左边框透明 */
  491. border-right: 15px solid transparent; /* 右边框透明 */
  492. border-top: 15px solid #fff; /* 上边框是三角形的颜色 */
  493. }
  494. .BMap_bubble_buttons{
  495. top:4px !important;
  496. >div:nth-child(2){
  497. >div{
  498. font-size: 26px !important;
  499. }
  500. }
  501. }
  502. >img{
  503. display: none;
  504. }
  505. }
  506. .shadow{
  507. display: none;
  508. }
  509. .BMap_bubble_buttons{
  510. /* >div:nth-child(2){
  511. width:100px;
  512. } */
  513. }
  514. .el-table__header-wrapper { position: sticky; width: 100%; top:0px; z-index: 2;color:#333 }
  515. </style>