index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. <template>
  2. <div class="container">
  3. <div class="main">
  4. <div class="nav">
  5. <div class="nav-one">
  6. <img src="../assets/images/nav-one.png" alt="" />
  7. <div>
  8. <div class="nav-title">设备数量</div>
  9. <div class="nav-count" @click="goDevice">
  10. {{ topData.deviceNO }}
  11. </div>
  12. </div>
  13. </div>
  14. <div class="nav-two">
  15. <img src="../assets/images/nav-two.png" alt="" />
  16. <div>
  17. <div class="nav-title">WIFI数量</div>
  18. <div class="nav-count" @click="goWIFI">
  19. <div>
  20. <span class="eyicount">{{ topData.wifiNO }}</span
  21. ><span class="text">恶意数</span>
  22. </div>
  23. <div>
  24. <span class="allcount">{{ topData.totalWifiNO }}</span
  25. ><span class="text">总数</span>
  26. </div>
  27. </div>
  28. </div>
  29. </div>
  30. <div class="nav-three">
  31. <img src="../assets/images/nav-three.png" alt="" />
  32. <div>
  33. <div class="nav-title">蓝牙数量</div>
  34. <div class="nav-count" @click="goBluetooth">
  35. <div>
  36. <span class="eyicount">{{ topData.bluetoothNO }}</span
  37. ><span class="text">恶意数</span>
  38. </div>
  39. <div>
  40. <span class="allcount">{{ topData.totalBluetoothNO }}</span
  41. ><span class="text">总数</span>
  42. </div>
  43. </div>
  44. </div>
  45. </div>
  46. <!-- <div class="nav-four">
  47. <img src="../assets/images/nav-four.png" alt="" />
  48. <div>
  49. <div class="nav-title">场馆数量</div>
  50. <div class="nav-count" @click="goVenue">{{ topData.venueNO }}</div>
  51. </div>
  52. </div> -->
  53. </div>
  54. <div class="contbody" id="contbody">
  55. <!-- <div class="cont-left"> -->
  56. <!-- <img
  57. src="../assets/images/ditu.png"
  58. alt=""
  59. style="width: 100%; height: 690px"
  60. /> -->
  61. <!-- </div> -->
  62. <!-- <div class="chart-wrapper cont-left">
  63. <store-chart />
  64. </div> -->
  65. <!-- <div class="cont-right">
  66. <twin-chart :rightData="rightData" :wheight="wheight" />
  67. </div> -->
  68. <!-- cener成都市地区字符串,zoom缩放等级 -->
  69. <!-- ../assets/images/org-icon.png -->
  70. <!-- mapStyle="mapStyle" 地图样式 anchor="BMAP ANCHOR TOP RIGHT" 比例尺-->
  71. <baidu-map
  72. ak="sqxhrmvfnPaA2yS0gmceKfCrL8T3hhIV"
  73. :center="center"
  74. :zoom="zoom"
  75. :scroll-wheel-zoom="true"
  76. style="width: 100%; height: 100%"
  77. >
  78. <!-- 缩放 -->
  79. <bm-navigation
  80. anchor="BMAP_ANCHOR TOP_RIGHT"
  81. class="suofang"
  82. ></bm-navigation>
  83. <!-- 点位 -->
  84. <bm-marker
  85. @mouseover="infoWindowOpen(marker)"
  86. @click="infoWindowOpen(marker)"
  87. v-for="(marker, index) of topData.info"
  88. :key="index"
  89. :position="{ lng: marker.lng, lat: marker.lat }"
  90. :icon="{
  91. url: require('@/assets/images/org-icon.png'),
  92. size: { width: 150, height: 157 },
  93. }"
  94. @mouseout="infoWindowClose"
  95. >
  96. <!-- 弹框 -->
  97. <bm-info-window
  98. :show="selectedMarker == marker || show"
  99. @close="infoWindowClose"
  100. @open="infoWindowOpen(marker)"
  101. @mouseout="infoWindowClose"
  102. >
  103. <div class="tankuang">
  104. <div class="poptop" @click="goBluetooth">
  105. <div style="display: flex">
  106. <div class="pop-left">
  107. <img src="../assets/images/Bluetooth.png" alt="" />
  108. <div>蓝牙</div>
  109. </div>
  110. <div class="vertical-dashed-line"></div>
  111. </div>
  112. <div class="pop-right">
  113. <div>
  114. <span>总数</span><span>{{ marker.totalBluetooth }}</span>
  115. </div>
  116. <div>
  117. <span>恶意数</span
  118. ><span class="eyi">{{ marker.bluetooth }}</span>
  119. </div>
  120. </div>
  121. </div>
  122. <div class="popbottom" @click="goWIFI">
  123. <div style="display: flex">
  124. <div class="pop-left">
  125. <img src="../assets/images/WifiMedium.png" alt="" />
  126. <div>WIFI</div>
  127. </div>
  128. <div class="vertical-dashed-line"></div>
  129. </div>
  130. <div class="pop-right">
  131. <div>
  132. <span>总数</span><span>{{ marker.totalWifi }}</span>
  133. </div>
  134. <div>
  135. <span>恶意数</span
  136. ><span class="eyi">{{ marker.wifi }}</span>
  137. </div>
  138. </div>
  139. </div>
  140. </div>
  141. </bm-info-window>
  142. </bm-marker>
  143. <!-- 选择时间 -->
  144. <el-select
  145. v-model="selectedValue"
  146. placeholder="请选择"
  147. class="choice-time"
  148. @change="choiceTime"
  149. >
  150. <el-option
  151. v-for="item in dict.type.index_filter"
  152. :key="item.value"
  153. :label="item.label"
  154. :value="item.value"
  155. >
  156. </el-option>
  157. </el-select>
  158. <!-- 选择自定义时间 -->
  159. <el-date-picker
  160. v-model="drillDate"
  161. class="choice-time choice-mytime"
  162. value-format="yyyy-MM-dd HH:mm:ss"
  163. type="daterange"
  164. range-separator="-"
  165. start-placeholder="开始日期"
  166. end-placeholder="结束日期"
  167. :default-time="['00:00:00', '23:59:59']"
  168. @change="checkDrillDate"
  169. />
  170. <div class="real-signal">
  171. <div>
  172. <div class="title">实时信号</div>
  173. <div
  174. class="cont"
  175. @click="lookPosition(items)"
  176. v-for="(items, indexs) in realTimeData"
  177. :key="indexs"
  178. >
  179. <span class="positions"
  180. ><img src="../assets/images/MapPin.png" alt="" /><span
  181. >查看位置</span
  182. ></span
  183. >
  184. <span class="realname">{{ items.type }}</span>
  185. <span class="illegal">{{ items.state }}</span>
  186. </div>
  187. </div>
  188. </div>
  189. </baidu-map>
  190. <!-- <my-popup
  191. v-if="selectedMarker"
  192. :marker="selectedMarker"
  193. @close="selectedMarker = null"
  194. ></my-popup> -->
  195. </div>
  196. </div>
  197. </div>
  198. </template>
  199. <script>
  200. import { indexTop, indexInfo, realTimeInfo } from "@/api/system/index";
  201. import storeChart from "./dashboard/storeChart";
  202. import twinChart from "./dashboard/twinChart";
  203. import MyPopup from "./components/MyPopup.vue";
  204. import BmMarkers from "vue-baidu-map/components/overlays/Marker.vue";
  205. import { listData } from "@/api/system/dict/data";
  206. export default {
  207. name: "Dict",
  208. dicts: ["index_filter"],
  209. components: {
  210. storeChart,
  211. twinChart,
  212. MyPopup,
  213. BmMarkers,
  214. },
  215. data() {
  216. return {
  217. selectedValue: "1",
  218. drillDate: [], //自定义时间
  219. realTimeData: [], //实时数据
  220. show: false,
  221. //=======地图
  222. center: { lng: 104.064856, lat: 30.658876 }, // 成都的经纬度
  223. zoom: 12, // 地图缩放级别
  224. selectedMarker: null,
  225. //=======地图
  226. data: "sdff",
  227. topData: {},
  228. rightData: [],
  229. wheight: 0,
  230. start: "",
  231. end: "",
  232. };
  233. },
  234. created() {
  235. // console.log('first', this.dict.getDictValue())
  236. this.$nextTick(() => {
  237. this.wheight = document.getElementById("contbody").clientHeight;
  238. });
  239. // this.getList();
  240. // 头部数据
  241. this.getInfo();
  242. //实时信号
  243. this.realTimeInfo();
  244. setInterval(() => {
  245. this.getInfo();
  246. }, 5 * 60 * 1000);
  247. setInterval(() => {
  248. this.realTimeInfo();
  249. }, 1 * 60 * 1000);
  250. },
  251. methods: {
  252. //实时数据
  253. realTimeInfo() {
  254. realTimeInfo().then((res) => {
  255. this.realTimeData = res;
  256. });
  257. },
  258. lookPosition(items) {
  259. //查看位置
  260. this.center = { lng: items.lng, lat: items.lat };
  261. console.log(items, "22222");
  262. this.show = true;
  263. },
  264. //选择周,天。。。
  265. choiceTime(selectedValue) {
  266. if (this.selectedValue == 6 && this.drillDate.length == 0) {
  267. return this.$modal.msg("请选择自定义时间");
  268. } else {
  269. this.getInfo();
  270. }
  271. },
  272. //自定义时间
  273. checkDrillDate() {
  274. console.log("drillDate", this.drillDate);
  275. this.start = this.drillDate?this.drillDate[0]:"";
  276. this.end = this.drillDate?this.drillDate[1]:"";
  277. this.selectedValue=this.drillDate?"6":"1"
  278. this.$forceUpdate()
  279. this.getInfo();
  280. },
  281. //关闭点位
  282. infoWindowClose() {
  283. this.selectedMarker = null;
  284. this.show = false;
  285. this.$forceUpdate();
  286. },
  287. //点击得到点位信息
  288. infoWindowOpen(marker) {
  289. this.selectedMarker = marker;
  290. // this.show = true;
  291. },
  292. goDevice() {
  293. //去设备
  294. this.$router.push({ path: "/deviceInfo" });
  295. },
  296. goWIFI() {
  297. this.$router.push({ path: "/wifiInfo" });
  298. },
  299. goBluetooth() {
  300. this.$router.push({ path: "/bluetoothINfo" });
  301. },
  302. goVenue() {
  303. this.$router.push({ path: "/venueInfo" });
  304. },
  305. getList() {
  306. indexTop().then((response) => {
  307. this.rightData = response;
  308. });
  309. },
  310. getInfo() {
  311. //头部
  312. indexInfo({
  313. filter: this.selectedValue,
  314. start: this.start,
  315. end: this.end,
  316. }).then((response) => {
  317. this.topData = response;
  318. this.$modal.msgSuccess('加载成功')
  319. console.log("response", response);
  320. });
  321. },
  322. },
  323. };
  324. </script>
  325. <style lang="scss" scoped>
  326. .container {
  327. background-color: #f6f6f6 !important;
  328. height: 93vh;
  329. width: 100%;
  330. }
  331. .main {
  332. display: flex;
  333. flex-direction: column;
  334. margin: 0 32px 32px;
  335. overflow: hidden;
  336. height: 100%;
  337. }
  338. .nav {
  339. display: flex;
  340. justify-content: space-around;
  341. min-height: 160px;
  342. margin: 32px 0 24px;
  343. & > div {
  344. & > div {
  345. height: 80px;
  346. display: flex;
  347. flex-direction: column;
  348. justify-content: space-around;
  349. }
  350. flex: 1;
  351. border-radius: 4px;
  352. display: flex;
  353. align-items: center;
  354. margin-right: 24px;
  355. & > img {
  356. margin-right: 28px;
  357. margin-left: 32px;
  358. max-width: 80px;
  359. max-height: 80px;
  360. border-radius: 24px;
  361. }
  362. // @media (max-height: 1600px) {
  363. // & > img {
  364. // width: 40px;
  365. // height: 40px;
  366. // }
  367. // }
  368. @media (max-width: 1000px) {
  369. & > img {
  370. max-width: 60px;
  371. max-height: 60px;
  372. }
  373. & > div {
  374. height: 60px;
  375. }
  376. }
  377. }
  378. .nav-one {
  379. background: #c4eccc;
  380. color: #347140;
  381. }
  382. .nav-two {
  383. color: #713734;
  384. background: #fae6bb;
  385. }
  386. .nav-three {
  387. color: #344171;
  388. background: #d6e0ff;
  389. margin-right: 0;
  390. }
  391. .nav-four {
  392. color: #344171;
  393. margin-right: 0;
  394. background: #ffd6e4;
  395. }
  396. .nav-one,
  397. .nav-two,
  398. .nav-three,
  399. .nav-four {
  400. background-image: url("../assets/images/topImg.png");
  401. background-position: top right;
  402. background-repeat: no-repeat;
  403. background-size: 98px 100px;
  404. }
  405. .nav-count {
  406. cursor: pointer;
  407. font-size: 32px;
  408. font-weight: 600;
  409. color: #000;
  410. display: flex;
  411. margin-top: 8px;
  412. & > div {
  413. display: flex;
  414. flex-direction: column;
  415. }
  416. & > div:first-child {
  417. margin-right: 32px;
  418. }
  419. .eyicount {
  420. font-weight: 600;
  421. font-size: 32px;
  422. color: #ff3e01;
  423. }
  424. .allcount {
  425. font-weight: 600;
  426. font-size: 32px;
  427. }
  428. .text {
  429. color: #713734;
  430. font-size: 14px;
  431. }
  432. }
  433. .nav-title {
  434. font-size: 18px;
  435. }
  436. @media (max-width: 1000px) {
  437. .nav-count {
  438. font-size: 16px;
  439. }
  440. .nav-title {
  441. font-size: 14px;
  442. }
  443. }
  444. }
  445. .contbody {
  446. display: flex;
  447. width: 100%;
  448. flex-grow: 1;
  449. border-radius: 16px;
  450. margin-bottom: 32px;
  451. position: relative;
  452. .cont-left,
  453. .cont-right {
  454. background: #fff;
  455. border-radius: 16px;
  456. }
  457. .cont-left {
  458. flex: 1;
  459. margin-right: 24px;
  460. }
  461. .cont-right {
  462. width: 550px;
  463. }
  464. }
  465. .tankuang {
  466. width: 225px;
  467. height: 160px;
  468. margin-left: 10px;
  469. display: flex;
  470. flex-direction: column;
  471. justify-content: space-around;
  472. }
  473. .poptop,
  474. .popbottom {
  475. cursor: pointer;
  476. font-size: 14px;
  477. display: flex;
  478. align-items: center;
  479. // justify-content: space-between;
  480. .pop-left {
  481. color: #72838c;
  482. img {
  483. width: 32px;
  484. height: 32px;
  485. }
  486. margin-right: 20px;
  487. }
  488. .vertical-dashed-line {
  489. margin-top: 8px;
  490. border-left: 2px dashed #72838c;
  491. height: 40px; /* 虚线的高度 */
  492. }
  493. .pop-right {
  494. font-weight: 600;
  495. font-size: 14px;
  496. margin-left: 20px;
  497. & > div {
  498. display: flex;
  499. justify-content: space-around;
  500. & > span:last-child {
  501. font-size: 18px;
  502. margin-left: 20px;
  503. }
  504. .eyi {
  505. font-size: 19px;
  506. color: #ff3e01;
  507. }
  508. }
  509. }
  510. }
  511. // 弹框样式
  512. ::v-deep .BMap_top,
  513. ::v-deep .BMap_bottom {
  514. background: rgba(255, 255, 255, 0.8) !important;
  515. }
  516. ::v-deep .BMap_pop {
  517. > div:nth-child(7),
  518. > div:nth-child(5),
  519. > div:nth-child(1),
  520. > div:nth-child(3),
  521. > div:nth-child(4) {
  522. > div {
  523. background: rgba(255, 255, 255, 0.8) !important;
  524. }
  525. }
  526. > div:nth-child(8) {
  527. display: none;
  528. }
  529. }
  530. ::v-deep .BMap_pop .BMap_center,
  531. .choice-mytime,
  532. .choice-time,
  533. .real-signal {
  534. background: rgba(255, 255, 255, 0.8) !important;
  535. }
  536. ::v-deep .BMap_shadow,
  537. .BMap_shadow img,
  538. .BMap_shadow div {
  539. display: none;
  540. }
  541. ::v-deep .BMap_stdMpCtrl {
  542. inset: 24px auto auto 10px !important;
  543. }
  544. //选择时间
  545. .choice-time,
  546. .choice-mytime {
  547. border: none;
  548. box-sizing: content-box;
  549. position: absolute;
  550. cursor: pointer;
  551. left: 85px;
  552. top: 24px;
  553. z-index: 9;
  554. ::v-deep .el-input__inner {
  555. border: none;
  556. width: 90px;
  557. height: 38px;
  558. }
  559. }
  560. .choice-mytime {
  561. width: 244px;
  562. left: 184px;
  563. top: 24px;
  564. height: 33px !important;
  565. }
  566. ::v-deep .el-date-editor .el-range-input,
  567. ::v-deep .el-date-editor .el-range__icon {
  568. color: #459def !important;
  569. }
  570. //实时信号
  571. .real-signal {
  572. height: 360px;
  573. overflow-y: auto;
  574. width: 258px;
  575. right: 24px;
  576. top: 24px;
  577. position: absolute;
  578. z-index: 9;
  579. border-radius: 4px 4px 0px 0px;
  580. & > div {
  581. font-size: 14px;
  582. .title {
  583. position: sticky;
  584. top: 0;
  585. background-color: #fff;
  586. padding: 10px;
  587. color: #72838c;
  588. z-index: 99999;
  589. border-bottom: 1px solid #e5e6eb;
  590. }
  591. .cont {
  592. cursor: pointer;
  593. margin: 10px;
  594. display: flex;
  595. justify-content: space-between;
  596. align-items: center;
  597. .positions {
  598. color: #459def;
  599. img {
  600. width: 16px;
  601. height: 16px;
  602. vertical-align: middle;
  603. }
  604. & > span:last-child {
  605. margin-left: 3px;
  606. border-bottom: 1px solid #459def;
  607. }
  608. }
  609. // .realname{
  610. // }
  611. .illegal {
  612. color: #ff3e01;
  613. }
  614. }
  615. }
  616. }
  617. </style>