onlineAndHealth.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. <template>
  2. <div class="component_box" style="display: flex;" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
  3. <div ref="chart" style="width: 50%; height: 100%; "></div>
  4. <div class="health">
  5. <header class="header">
  6. <span>网点设备健康度检查</span>
  7. <!-- <h3><span>网点数:100</span></h3> -->
  8. <!-- <img src="img/end.png"></img> -->
  9. <!-- <span>已检查:90</span> -->
  10. </header>
  11. <main class="banklet_main">
  12. <!-- <img src="img/map.png" alt=""> -->
  13. <div class="item_box">
  14. <span>网点数</span>
  15. <div>
  16. <i></i>
  17. <h2>{{ healthSummary.total }}</h2>
  18. </div>
  19. </div>
  20. <div class="item_box">
  21. <span>已检</span>
  22. <div>
  23. <i></i>
  24. <h2>{{ healthSummary.checkedCount }}</h2>
  25. </div>
  26. </div>
  27. <div class="item_box">
  28. <span>90分以上</span>
  29. <div>
  30. <i></i>
  31. <h2>{{ healthSummary.over90Count }}</h2>
  32. </div>
  33. </div>
  34. <div class="item_box">
  35. <span>90及以下</span>
  36. <div>
  37. <i></i>
  38. <h2>{{ healthSummary.notover90Count }}</h2>
  39. </div>
  40. </div>
  41. </main>
  42. <header class="t_b_h_1">
  43. <span>网点健康度检查TOP3</span>
  44. </header>
  45. <main class="t_b_m_1" style="top:70%">
  46. <div v-for="(item, index) in healthRanking" :key="index">
  47. <i>
  48. <t>{{ index + 1 }}</t>
  49. </i> {{ item.orgName }} {{ parseFloat(item.score).toFixed(2) }}分
  50. </div>
  51. </main>
  52. </div>
  53. </div>
  54. </template>
  55. <script>
  56. import { deviceOnline, deviceHealth } from "@/api/iot/board";
  57. export default {
  58. props: {
  59. orgId: {
  60. type: String,
  61. isRequired: true,
  62. },
  63. },
  64. data() {
  65. return {
  66. chartData: {
  67. total: [],
  68. onLineCount: [],
  69. name: [],
  70. },
  71. healthSummary: {
  72. total: 0,
  73. checkedCount: 0,
  74. over90Count: 0,
  75. notover90Count: 0,
  76. },
  77. healthRanking: [],
  78. isMouseOver: false
  79. };
  80. },
  81. components: {},
  82. computed: {},
  83. watch: {
  84. orgId: {
  85. deep: true,
  86. handler(val) {
  87. this.resetTimer();
  88. this.getData();
  89. },
  90. },
  91. chartData: {
  92. deep: true,
  93. handler() {
  94. this.initMap();
  95. },
  96. },
  97. },
  98. created() {
  99. this.refreshTime = 1 * 10 * 1000;
  100. this.isMouseOver = false;
  101. },
  102. async mounted() {
  103. window.addEventListener("resize", this.windowResize);
  104. },
  105. beforeDestroy() {
  106. this.timer && clearInterval(this.timer);
  107. this.timer = null;
  108. window.removeEventListener("resize", this.windowResize);
  109. },
  110. methods: {
  111. handleMouseEnter() {
  112. this.isMouseOver = true;
  113. },
  114. handleMouseLeave() {
  115. this.isMouseOver = false;
  116. },
  117. async getData() {
  118. deviceOnline(this.orgId).then(r => {
  119. let data = r.data;
  120. let chartData = {
  121. total: [],
  122. onLineCount: [],
  123. name: [],
  124. };
  125. for (let item of data) {
  126. chartData.total.push(item.deviceCount);
  127. chartData.onLineCount.push(item.completedCount);
  128. // chartData.rate.push((item.completedRate * 100).toFixed(2));
  129. chartData.name.push(item.orgName);
  130. }
  131. this.chartData = chartData;
  132. });
  133. deviceHealth(this.orgId).then(r => {
  134. this.healthSummary = r.data.healthSummary;
  135. this.healthRanking = r.data.healthRanking
  136. })
  137. },
  138. windowResize() {
  139. this.myChart && this.myChart.resize();
  140. },
  141. initMap() {
  142. let c = this.$refs["chart"];
  143. // 基于准备好的dom,初始化echarts实例
  144. this.myChart = echarts.init(
  145. c
  146. // document.getElementById("commAlarmEvent_Chart")
  147. );
  148. // var data = [70, 34, 60, 78, 69];
  149. // var titlename = [
  150. // "监控主机",
  151. // "报警主机",
  152. // "动环主机",
  153. // "对讲主机",
  154. // "门禁主机",
  155. // ];
  156. // var valdata = [702, 406, 664, 793, 505];
  157. var myColor = ["#1089E7", "#F57474", "#56D0E3", "#F8B448"];
  158. option = {
  159. title: {
  160. text: "设备在线率",
  161. x: "center",
  162. textStyle: {
  163. color: "#FFF",
  164. },
  165. left: "6%",
  166. top: "10%",
  167. },
  168. //图标位置
  169. grid: {
  170. top: "20%",
  171. left: "32%",
  172. },
  173. xAxis: {
  174. show: false,
  175. },
  176. yAxis: [
  177. {
  178. show: true,
  179. data: this.chartData.name,
  180. inverse: true,
  181. axisLine: {
  182. show: false,
  183. },
  184. splitLine: {
  185. show: false,
  186. },
  187. axisTick: {
  188. show: false,
  189. },
  190. axisLabel: {
  191. color: "#fff",
  192. formatter: (value, index) => {
  193. return [`{lg|${index + 1}} ` + "{title|" + value + "} "].join(
  194. "\n"
  195. );
  196. },
  197. rich: {
  198. lg: {
  199. backgroundColor: "#339911",
  200. color: "#fff",
  201. borderRadius: 15,
  202. // padding: 5,
  203. align: "center",
  204. width: 15,
  205. height: 15,
  206. },
  207. },
  208. },
  209. },
  210. {
  211. show: true,
  212. inverse: true,
  213. data: this.chartData.total,
  214. axisLabel: {
  215. textStyle: {
  216. fontSize: 12,
  217. color: "#fff",
  218. },
  219. },
  220. axisLine: {
  221. show: false,
  222. },
  223. splitLine: {
  224. show: false,
  225. },
  226. axisTick: {
  227. show: false,
  228. },
  229. },
  230. ],
  231. series: [
  232. {
  233. name: "条",
  234. type: "bar",
  235. yAxisIndex: 0,
  236. data: this.chartData.onLineCount,
  237. barWidth: 10,
  238. itemStyle: {
  239. normal: {
  240. barBorderRadius: 20,
  241. color: function (params) {
  242. var num = myColor.length;
  243. return myColor[params.dataIndex % num];
  244. },
  245. },
  246. },
  247. label: {
  248. normal: {
  249. show: true,
  250. position: "inside",
  251. formatter: "{c}%",
  252. },
  253. },
  254. },
  255. {
  256. name: "框",
  257. type: "bar",
  258. yAxisIndex: 1,
  259. barGap: "-100%",
  260. data: [100, 100, 100, 100, 100],
  261. barWidth: 15,
  262. itemStyle: {
  263. normal: {
  264. color: "none",
  265. borderColor: "#00c1de",
  266. borderWidth: 3,
  267. barBorderRadius: 15,
  268. },
  269. },
  270. },
  271. ],
  272. };
  273. // 使用刚指定的配置项和数据显示图表。
  274. this.myChart.setOption(option);
  275. },
  276. resetTimer() {
  277. this.timer && clearInterval(this.timer);
  278. this.timer = setInterval(() => {
  279. if (this.isMouseOver) {
  280. return;
  281. }
  282. this.getData();
  283. }, this.refreshTime);
  284. },
  285. },
  286. };
  287. </script>
  288. <style scoped src="./../css/index.css"></style>
  289. <style lang="scss" scoped>
  290. .health {
  291. width: 50%;
  292. height: 100%;
  293. display: flex;
  294. flex-direction: column;
  295. padding: 0 3%;
  296. ::v-deep .header {
  297. color: #fff;
  298. width: 100%;
  299. height: 12%;
  300. font-size: 20px;
  301. }
  302. ::v-deep .banklet_main {
  303. height: 40%;
  304. width: 100%;
  305. }
  306. ::v-deep .item_box {
  307. border: 1px dotted #f0ff00;
  308. border-radius: 5px;
  309. margin-top: 5%;
  310. height: 45%;
  311. width: 45%;
  312. float: left;
  313. display: flex;
  314. flex-direction: column;
  315. font-size: 14px;
  316. }
  317. ::v-deep .item_box:nth-child(even) {
  318. margin-left: 10%;
  319. }
  320. ::v-deep .item_box>span:first-child {
  321. line-height: 20px;
  322. }
  323. ::v-deep .item_box>div:last-child {
  324. // display: block;
  325. width: 100%;
  326. height: calc(100% - 20px);
  327. display: flex;
  328. align-items: center;
  329. justify-content: center;
  330. position: relative;
  331. }
  332. ::v-deep .item_box>div:last-child>i {
  333. width: 16px;
  334. height: 16px;
  335. display: inline-block;
  336. position: absolute;
  337. left: 20%;
  338. }
  339. ::v-deep .item_box:first-child>div:last-child>i {
  340. background: url("../img/t.png") no-repeat;
  341. background-size: 100% 100%;
  342. }
  343. ::v-deep .item_box:nth-child(2)>div:last-child>i {
  344. background: url("../img/s.png") no-repeat;
  345. background-size: 100% 100%;
  346. }
  347. ::v-deep .item_box:nth-child(3)>div:last-child>i {
  348. background: url("../img/j.png") no-repeat;
  349. background-size: 100% 100%;
  350. }
  351. ::v-deep .item_box:nth-child(4)>div:last-child>i {
  352. background: url("../img/g.png") no-repeat;
  353. background-size: 100% 100%;
  354. }
  355. }
  356. .t_b_m img {
  357. position: absolute;
  358. left: 52%;
  359. top: 22%;
  360. border-top: 1px dotted #f0ff00;
  361. padding: 0 0.18rem;
  362. padding-top: 20px;
  363. width: 3.19rem;
  364. height: 1.67rem;
  365. }
  366. .t_b_h_1 {
  367. position: absolute;
  368. font-size: 0.16rem;
  369. left: 54%;
  370. width: 50%;
  371. height: 2.1rem;
  372. top: 60%;
  373. }
  374. .t_b_h_1 span {
  375. position: absolute;
  376. color: #fff;
  377. top: 10%;
  378. font-size: 20px;
  379. }
  380. .t_b_h_1 img {
  381. position: absolute;
  382. width: 0.53rem;
  383. height: 0.53rem;
  384. top: 6%;
  385. left: 24%;
  386. }
  387. .t_b_h_1 h3 {
  388. font-size: 0.36rem;
  389. color: #f0ff00;
  390. position: absolute;
  391. left: 55%;
  392. top: 8%;
  393. width: 1rem;
  394. }
  395. .t_b_h_1 h3 span {
  396. font-size: 0.2rem;
  397. position: absolute;
  398. left: 50%;
  399. top: 28%;
  400. color: #0072ff;
  401. }
  402. .t_b_m_1 {
  403. position: absolute;
  404. font-size: 0.16rem;
  405. left: 54%;
  406. width: 50%;
  407. height: 2.1rem;
  408. top: 70%;
  409. }
  410. .t_b_m_1 div {
  411. margin-top: 15px;
  412. height: 20px;
  413. color: white;
  414. font-size: 14px;
  415. }
  416. .t_b_m_1 div>i {
  417. background-color: #339911;
  418. font-family: 仿宋体;
  419. width: 19px;
  420. display: inline-block;
  421. border-radius: 9.5px;
  422. }
  423. .t_b_m_1 div>i>t {
  424. left: 3px;
  425. position: relative;
  426. }
  427. .t_b_box,
  428. .t_b_box1,
  429. .t_b_box2,
  430. .t_b_box3 {
  431. width: 35%;
  432. height: 10%;
  433. position: absolute;
  434. }
  435. .t_b_box {
  436. top: 25%;
  437. left: 56%;
  438. }
  439. .t_b_box span,
  440. .t_b_box1 span,
  441. .t_b_box2 span,
  442. .t_b_box3 span {
  443. font-size: 0.14rem;
  444. color: #fff;
  445. position: absolute;
  446. left: 10%;
  447. }
  448. .t_b_box i,
  449. .t_b_box1 i,
  450. .t_b_box2 i,
  451. .t_b_box3 i {
  452. width: 20px;
  453. height: 20px;
  454. position: absolute;
  455. top: 50%;
  456. left: 15%;
  457. }
  458. .t_b_box h2,
  459. .t_b_box1 h2,
  460. .t_b_box2 h2,
  461. .t_b_box3 h2 {
  462. font-size: 0.18rem;
  463. color: #fff;
  464. position: absolute;
  465. top: 30%;
  466. left: 40%;
  467. }
  468. .t_b_box1 {
  469. top: 25%;
  470. left: 78%;
  471. }
  472. .t_b_box2 {
  473. top: 45%;
  474. left: 56%;
  475. }
  476. .t_b_box3 {
  477. top: 45%;
  478. left: 78%;
  479. }
  480. </style>