index.vue 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693
  1. <template>
  2. <div ref="homepage" :class="skinMode === 'light' ? 'light-overview' : 'dark-overview'">
  3. <!-- 顶部路由 -->
  4. <div class="menu">
  5. <div class="home" @click="$emit('update:modelNum', 0)">
  6. <!-- <div class="downright"></div> -->
  7. <div class="home-box">
  8. <img src="@/assets/imgs/logo.png" alt />
  9. <!-- <span>{{plazas.length>0?formatter(plazaId,plazas):'--'}}</span> -->
  10. <span>万达集团管理说明书</span>
  11. </div>
  12. </div>
  13. <div class="home-right">
  14. <span style="color: #8d9399">
  15. <span class="span3">{{ times }}</span>
  16. <img @click="changeSkin" @mouseenter="showSwitchTip = true" @mouseleave="delayToHideTip" src="../../assets/images/icons/switch.png">
  17. <div class="tip" v-show="showSwitchTip" @mouseenter="cancelHideTip" @mouseleave="showSwitchTip = false" >
  18. {{skinMode === 'light' ? '切换驾驶舱':'切换集团首页'}}
  19. </div>
  20. </span>
  21. </div>
  22. </div>
  23. <!-- 面包屑 -->
  24. <nav class="navigation">
  25. <section class="crumbs">
  26. <span>{{ currentZoneData.cname }}</span>
  27. <span
  28. v-for="(item, index) in crumbsHtml"
  29. :key="index"
  30. @click="navgateFromCrumbs(item[1], index)"
  31. >
  32. {{ item[0] }}
  33. <em v-if="index !== crumbsHtml.length - 1">></em>
  34. </span>
  35. </section>
  36. <section>
  37. <TreeSelect
  38. class="special-my-tree-select"
  39. ref="treeSelect"
  40. width="240"
  41. :hideClear="true"
  42. :isReadOnly="false"
  43. :caption="'管理分区:'"
  44. :data="regulateDistrictData"
  45. :placeholder="placeholder"
  46. :disabled="false"
  47. v-model="selectedZone"
  48. @change="selectProjectItem"
  49. />
  50. </section>
  51. </nav>
  52. <main class="container">
  53. <section class="system-general dot-background">
  54. <div class="system-main-title">
  55. <h4 class="section-title">系统概况</h4>
  56. </div>
  57. <div class="system-list">
  58. <ul>
  59. <li
  60. @click="getInfoOfProject(item)"
  61. :class="['system-item', item.selected ? 'selected' : '']"
  62. v-for="(item, index) in systemList"
  63. :key="index"
  64. >
  65. <div class="system-name">
  66. <img :src="imgSrc(item.smsxt)" />
  67. <span>{{ item.smsxtname.replace("系统", "") }}</span>
  68. </div>
  69. <section
  70. v-if="item.assetTypeList.length"
  71. class="system-equipments-container"
  72. >
  73. <div
  74. class="more"
  75. @click.stop.capture="expandRestItems(item, index)"
  76. v-if="item.hasArrow"
  77. :style="{
  78. transform: item.expand ? 'rotate(0)' : 'rotate(180deg)',
  79. }"
  80. >
  81. <img v-if="item.showColor" src="../../assets/images/icons/arrow.png" />
  82. <img v-else src="../../assets/images/icons/grey.png" />
  83. </div>
  84. <div class="system-equipments">
  85. <div
  86. class="number"
  87. v-for="(equip, index) in item.assetTypeList"
  88. :key="index"
  89. >
  90. <div class="title">
  91. <P
  92. :style="{
  93. width:
  94. equip.category_name.length > 6 ? '10rem' : 'auto',
  95. }"
  96. :title="equip.category_name"
  97. >{{ equip.category_name }}</P
  98. >
  99. <span
  100. @click.stop.capture="openMaskPanel(item)"
  101. :style="{
  102. right: equip.category_name.length > 6 ? '0' : '-1rem',
  103. }"
  104. v-if="equip.is_exception_num"
  105. >{{ equip.is_exception_num }}</span
  106. >
  107. </div>
  108. <p>
  109. <span class="amount">{{ equip.asset_num }}</span
  110. ><span>{{
  111. equip.category_name === "屋面logo"
  112. ? "个"
  113. : equip.category_name === "玻璃护栏"
  114. ? "段"
  115. : "台"
  116. }}</span>
  117. </p>
  118. </div>
  119. </div>
  120. <section
  121. class="system-equipments"
  122. v-show="item.expand && item.restAssetTypeList.length"
  123. style="margin-top: 0.4rem"
  124. >
  125. <div
  126. class="number"
  127. v-for="(equip, index) in item.restAssetTypeList"
  128. :key="index"
  129. >
  130. <div class="title">
  131. <P :title="equip.category_name">{{
  132. equip.category_name
  133. }}</P>
  134. <span
  135. @click.stop.capture="openMaskPanel(item)"
  136. :style="{
  137. right: equip.category_name.length > 6 ? '0' : '-1rem',
  138. }"
  139. v-if="equip.is_exception_num"
  140. >{{ equip.is_exception_num }}</span
  141. >
  142. </div>
  143. <p>
  144. <span class="amount">{{ equip.asset_num }}</span
  145. ><span>{{
  146. equip.category_name === "屋面logo"
  147. ? "个"
  148. : equip.category_name === "玻璃护栏"
  149. ? "段"
  150. : "台"
  151. }}</span>
  152. </p>
  153. </div>
  154. </section>
  155. </section>
  156. <div v-else style="width: 65%; text-align: center">暂无数据</div>
  157. </li>
  158. </ul>
  159. </div>
  160. </section>
  161. <section class="map-box">
  162. <section class="cards-list">
  163. <div class="card dot-background" @click="navToManageNumber">
  164. <div class="card-title">
  165. <p>上线管理说明书广场数量</p>
  166. </div>
  167. <div class="describe">
  168. <span style="margin-right: 20px"
  169. >上线数量 <strong>{{ plazaInfoCount.upwcCount }}</strong></span
  170. >
  171. </div>
  172. </div>
  173. <div class="card dot-background" @click="navToIntroduceUpdate">
  174. <div class="card-title">
  175. <p>当月说明书更新数量</p>
  176. </div>
  177. <div class="describe">
  178. <div style="margin-right: 20px">
  179. 更新广场数量
  180. <strong>{{ plazaInfoCount.rptChangeCount }}</strong>
  181. </div>
  182. <div>
  183. 更新事项数量<strong>{{
  184. plazaInfoCount.zhsxChangeCount
  185. }}</strong>
  186. </div>
  187. </div>
  188. </div>
  189. </section>
  190. <section class="map-container" id="map-container">
  191. <div id="map"></div>
  192. <div class="legend">
  193. <div
  194. class="legend-bar"
  195. v-for="(bar, index) in legendList"
  196. :key="index"
  197. >
  198. <span :style="{ background: bar.color }"></span>
  199. <em>{{ bar.num }}</em>
  200. </div>
  201. </div>
  202. </section>
  203. </section>
  204. <section class="ratio-list">
  205. <section
  206. class="block dot-background"
  207. :style="panelStyle(item)"
  208. v-for="(item, index) in maintainList"
  209. :key="index"
  210. >
  211. <h4 class="section-title" @click="toggerPanel(item)" @mouseover="showToolTip(index, item.title)" @mouseout="hideToolTip(index, item.title)" >
  212. {{ item.title}}
  213. <img v-show="skinMode==='light'" src="../../assets/images/icons/notice.png" />
  214. <img v-show="skinMode==='dark'" src="../../assets/images/icons/alert.png" />
  215. </h4>
  216. <transition name="selectDownUpExtendTop">
  217. <div class="tool-tip" v-if="item.showToolTip">
  218. <h5 style="font-weight: bold">{{ item.title + "比值" }}</h5>
  219. <p>
  220. {{
  221. item.title === "专维"
  222. ? "逾期未完成/即将逾期/本年总任务"
  223. : "即将逾期/当月总任务"
  224. }}
  225. </p>
  226. <div
  227. class="tip-triangle"
  228. :style="{
  229. left: item.title === '第三方检测' ? '12.5rem' : '7.8rem',
  230. }"
  231. ></div>
  232. </div>
  233. </transition>
  234. <div
  235. class="list"
  236. :style="{ overflow: item.expand == 1 ? 'auto' : 'hidden' }"
  237. >
  238. <ul>
  239. <li v-for="(option, index) in item.data" :key="index">
  240. <div class="ratio">
  241. <span>{{ option.cname }}</span>
  242. <span v-if="item.title === '专维'">
  243. <span
  244. >{{
  245. option.rptGlsmsStatistics.overdue_unfinished
  246. }}
  247. /</span
  248. >
  249. <span>{{ option.rptGlsmsStatistics.due_num }} /</span>
  250. <span>{{ option.rptGlsmsStatistics.total }}</span>
  251. </span>
  252. <span v-else>
  253. <span>{{ option.rptGlsmsStatistics.due_num }} /</span>
  254. <span>{{ option.rptGlsmsStatistics.total }}</span>
  255. </span>
  256. </div>
  257. <div class="bar">
  258. <div
  259. class="inner-bar"
  260. :style="barStyle(option.rptGlsmsStatistics, item.title)"
  261. ></div>
  262. </div>
  263. </li>
  264. </ul>
  265. <div class="arrow" v-show="item.expand !== 2" :style="{ transform: item.expand === 1 ? 'rotate(180deg)' : 'rotate(0deg)'}" @click="toggerPanel(item)" >
  266. <img src="../../assets/images/icons/arrow_d_u.png" />
  267. </div>
  268. </div>
  269. </section>
  270. </section>
  271. </main>
  272. <el-dialog
  273. :visible.sync="dialogVisible"
  274. width="80%"
  275. :custom-class="'my-dialog'"
  276. >
  277. <div class="shut-download">
  278. <span class="download" @click="downloadExcel">下载</span>
  279. <span class="shut" @click="shutMaskPanel">x</span>
  280. </div>
  281. <div class="table-content">
  282. <div class="table-title">
  283. {{ currentSelectedSys.smsxtname }}
  284. </div>
  285. <div class="table-tabs">
  286. <Tabs
  287. type="card"
  288. :data="tabData"
  289. v-model="activeName"
  290. @change="tabChange"
  291. ></Tabs>
  292. </div>
  293. <div class="table-select">
  294. <!-- v-model="selectedZone" -->
  295. <TreeSelect
  296. v-if="testTree"
  297. class="special-my-tree-select"
  298. ref="treeSelect"
  299. width="240"
  300. :hideClear="true"
  301. :isReadOnly="false"
  302. :caption="'管理分区:'"
  303. v-model="selectedDialogZone"
  304. :data="dialogDistrictData"
  305. @change="selectDialogProject"
  306. />
  307. </div>
  308. <section>
  309. <table class="table-report">
  310. <thead>
  311. <tr>
  312. <th width="10%">序号</th>
  313. <th width="20%">中心</th>
  314. <th width="20%">区域</th>
  315. <th width="20%">广场名称</th>
  316. <th width="30%">异常原因</th>
  317. </tr>
  318. </thead>
  319. <tbody>
  320. <tr>
  321. <td>汇总:</td>
  322. <td>{{ centerTotal }}</td>
  323. <td>{{ zoneTotal }}</td>
  324. <td>{{ projectTotal }}</td>
  325. <td></td>
  326. </tr>
  327. <tr v-for="(td, index) in exceptionData" :key="index">
  328. <td>{{ (currentPage - 1) * pageSize + index + 1}}</td>
  329. <td>{{ td.center }}</td>
  330. <td>{{ td.zone }}</td>
  331. <td>{{ td.name }}</td>
  332. <td>{{ td.reason }}</td>
  333. </tr>
  334. </tbody>
  335. </table>
  336. <table id="tableReport" class="table-report" v-show="false">
  337. <thead>
  338. <tr>
  339. <th width="10%">序号</th>
  340. <th width="20%">中心</th>
  341. <th width="20%">区域</th>
  342. <th width="20%">广场名称</th>
  343. <th width="30%">异常原因</th>
  344. </tr>
  345. </thead>
  346. <tbody>
  347. <tr v-for="(td, index) in storeExceptionData" :key="index">
  348. <td>{{ index + 1 }}</td>
  349. <td>{{ td.center }}</td>
  350. <td>{{ td.zone }}</td>
  351. <td>{{ td.name }}</td>
  352. <td>{{ td.reason }}</td>
  353. </tr>
  354. </tbody>
  355. </table>
  356. <Pagination
  357. v-show="pageCount > 9"
  358. :pageCount="pageCount"
  359. style="float: right; margin-top: 20px"
  360. :page="currentPage"
  361. :pageSize="pageSize"
  362. :pageCountShow="true"
  363. @change="currentChangeHandle"
  364. />
  365. </section>
  366. <div class="empty-text" v-show="!pageCount">暂无数据</div>
  367. </div>
  368. </el-dialog>
  369. </div>
  370. </template>
  371. <script>
  372. let myMaps = null;
  373. import { Loading, Dialog } from "element-ui";
  374. import { Tabs } from "meri-design";
  375. import { login } from "@/api/login";
  376. import {
  377. getPlazaInfoCount,
  378. querySystemCard,
  379. getCardList,
  380. queryEventStatus,
  381. getExceptionNum,
  382. } from "@/api/homePage";
  383. import { formatTime } from "@/utils/format.js";
  384. import { mapGetters } from "vuex";
  385. import { sortBy, cloneDeep } from "lodash";
  386. import moment from "moment";
  387. import L from "leaflet";
  388. import "leaflet-contextmenu";
  389. export default {
  390. data() {
  391. return {
  392. tipTimer:null,
  393. showSwitchTip:false,
  394. mapLayer:null,
  395. skinMode:'light',
  396. zoneTotal: 0,
  397. centerTotal: 0,
  398. projectTotal: 0,
  399. pageCount: 0,
  400. pageSize: 10,
  401. currentPage: 1,
  402. exceptionSum: 0,
  403. tabData: [],
  404. dialogBoxKey: 1,
  405. dialogVisible: false,
  406. testTree: true,
  407. exceptionData: [],
  408. storeExceptionData: [],
  409. activeName: "",
  410. systemExceptionData: {},
  411. showMask: false, // 控制遮罩层的显示隐藏
  412. placeholder: "全部",
  413. crumbsHtml: [], // 导航数据
  414. zoneNames: {
  415. // 各个中心对应的拼音名称
  416. 东北: "dongbei",
  417. 西北: "xibei",
  418. 华北: "huabei",
  419. 华中: "huazhong",
  420. 华东: "huadong",
  421. 中南: "zhongnan",
  422. 西南: "xinan",
  423. 华南: "huanan",
  424. 东南: "dongnan",
  425. 其他: "Other",
  426. },
  427. provinceCities: {
  428. // 各个区域的的中心坐标 缩放级别
  429. 青岛: { center: [36.06667, 120.33333], zoom: 8 },
  430. 北京: { center: [39.604882122321174, 116.43660987308282], zoom: 8 },
  431. 天津: { center: [39.130593, 117.260892], zoom: 7 },
  432. 济南: { center: [36.4, 117.0], zoom: 7 },
  433. 上海: { center: [31.090574094954192, 121.46299249603001], zoom: 10 },
  434. 南京: { center: [32.05, 118.78333], zoom: 7 },
  435. 无锡: { center: [31.57, 120.3], zoom: 9 },
  436. 厦门: { center: [24.46667, 118.1], zoom: 9 },
  437. 宁波: { center: [29.52, 121.33], zoom: 8 },
  438. 杭州: { center: [30.323100460201648, 120.50270908851112], zoom: 9 },
  439. 福州: { center: [26.05, 119.18], zoom: 8 },
  440. 合肥: { center: [31.52, 117.17], zoom: 7 },
  441. 长沙: { center: [28.12, 112.59], zoom: 8 },
  442. 南昌: { center: [28.4, 115.55], zoom: 8 },
  443. 大连: { center: [39.98974718404572, 122.66034125625548], zoom: 8 },
  444. 沈阳: { center: [41.72213058512578, 122.93479223528372], zoom: 8 },
  445. 长春: { center: [42.88033923363183, 127.02188147691707], zoom: 8 },
  446. 东莞: { center: [23.644524198573688, 114.83844948916203], zoom: 8 },
  447. 南宁: { center: [22.48, 108.19], zoom: 7 },
  448. 广州: { center: [22.755920681486405, 112.01244459124548], zoom: 7 },
  449. 深圳: { center: [22.755920681486405, 112.01244459124548], zoom: 7 },
  450. 太原: { center: [37.54, 112.33], zoom: 7 },
  451. 武汉: { center: [31.147006308556566, 112.97898510653813], zoom: 7 },
  452. 郑州: { center: [34.46, 113.4], zoom: 7 },
  453. 哈尔滨: { center: [46.800059446787316, 128.40505022926592], zoom: 7 },
  454. 乌鲁木齐: { center: [43.45, 87.36], zoom: 8 },
  455. 呼和浩特: { center: [45.182036837015886, 116.82329020199336], zoom: 5 },
  456. 西安: { center: [36.08462129606931, 109.4527754086213], zoom: 7 },
  457. 兰州: { center: [36.08462129606931, 103.4527754086213], zoom: 7 },
  458. 银川: { center: [38.108627664321276, 102.36578196225639], zoom: 7 },
  459. 成都: { center: [30.24957724046765, 103.4647651330231], zoom: 7 },
  460. 昆明: { center: [25.903703303407667, 105.10972266685498], zoom: 8 },
  461. 重庆: { center: [29.35, 106.33], zoom: 8 },
  462. },
  463. zoneCenter: {
  464. // 各个区域的中心坐标
  465. dongbei: [43.161614, 124.396818], // 取自 东北运营中心 长春区域 四平万达广场
  466. xibei: [37.999781, 106.197518], // 西北 银川区域 吴忠万达广场 zoom 5
  467. huabei: [39.019075, 117.686953], // 华北中心 天津区域 天津塘沽万达广场
  468. huazhong: [33.999249, 113.872131], // 华中 郑州 许昌万达广场
  469. huadong: [31.477565, 119.923391], // 华东 南京 泰州
  470. zhongnan: [28.860875644389676, 114.55131767165491],
  471. huanan: [22.635788, 110.17923], // 华南 南宁 玉林万达广场
  472. dongnan: [26.657907, 119.545678], //东南 福州 宁德万达广场
  473. xinan: [28.749998, 104.648788], // 西南 成都 宜宾万达广场
  474. },
  475. legendList: [
  476. // 地图图例数据
  477. { color: "#F54E45", num: "≥200" },
  478. { color: "#F58300", num: "100-200" },
  479. { color: "#FFBA6B", num: "50-99" },
  480. { color: "#0091FF", num: "10-49" },
  481. { color: "#82C7FC", num: "1-9" },
  482. { color: "#EEEEEE", num: "0" },
  483. ],
  484. plazaInfoCount: {},
  485. systemList: [], // 系统列表数据
  486. currentZoneData: {}, // 当前分区
  487. currentDistrictData: [], //当前管理分区数据
  488. currentSelectedSys: {}, // 当前所选择的系统
  489. currentSysId: "", // 当前系统ID
  490. regulateDistrictData: [], // 分区数据
  491. dialogDistrictData: [], // 弹窗分区数据
  492. currentDialogCcode: "",
  493. currentDialogLevel: "",
  494. currentDialogTab: "",
  495. maintainList: [], // 专维 维保 第三方检测 数据
  496. barColors: {
  497. // // 专维 维保 第三方检测 颜色
  498. 0: "linear-gradient(to right, #369CF7 , #025BAA)", // 蓝色
  499. 1: "linear-gradient(to right, #F58300 , #F58300)", // 黄色
  500. 2: "linear-gradient(to right, rgba(32,100,96,0.6) , rgba(32,100,96))", // 红色
  501. },
  502. selectedZone: "",
  503. selectedDialogZone: "",
  504. loadingInstance: null,
  505. };
  506. },
  507. computed: {
  508. ...mapGetters(["plazas", "plazaId", "accessLevel"]),
  509. },
  510. watch: {},
  511. components: { Tabs, Dialog },
  512. created() {
  513. this.currentTime();
  514. },
  515. mounted() {
  516. this.getFrameworkTreeData();
  517. window.addEventListener("resize", this.reinitalMap, false);
  518. },
  519. methods: {
  520. delayToHideTip() {
  521. this.tipTimer = setTimeout(() => {
  522. this.showSwitchTip = false
  523. }, 500);
  524. },
  525. cancelHideTip(){
  526. clearTimeout(this.tipTimer);
  527. },
  528. /**
  529. *@description 切换皮肤
  530. */
  531. changeSkin() {
  532. const vm = this
  533. const mapDom = document.querySelector("#map")
  534. const icons = mapDom.querySelectorAll(".my-leaflet-div-icon")
  535. this.$nextTick(()=>{
  536. if (this.skinMode === 'light') {
  537. this.skinMode = 'dark'
  538. icons.forEach(dom => {
  539. dom.style.color = "#FFF"
  540. })
  541. } else {
  542. this.skinMode = 'light'
  543. icons.forEach(dom => {
  544. dom.style.color = "#333"
  545. })
  546. }
  547. if (this.mapLayer) {
  548. this.mapLayer.setStyle({
  549. weight: 1,
  550. color: vm.skinMode === "light" ? "#B3D2FF" :"#56a3c2",
  551. fillColor: vm.skinMode === "light" ? "#DEECFF" : "#21285c",
  552. fillOpacity: vm.skinMode === "light" ? 0.2 : 1
  553. })
  554. }
  555. })
  556. },
  557. downloadExcel() {
  558. let tableContent = document.querySelector("#tableReport").outerHTML;
  559. let blob = new Blob([tableContent], {
  560. type: "text/plain; charset=utf-8",
  561. });
  562. blob = new Blob([String.fromCharCode(0xfeff), blob], { type: blob.type });
  563. let link = window.URL.createObjectURL(blob);
  564. let a = document.createElement("a");
  565. a.download = "异常数据表格.xls";
  566. a.href = link;
  567. document.body.appendChild(a);
  568. a.click();
  569. document.body.removeChild(a);
  570. },
  571. shutMaskPanel() {
  572. this.dialogVisible = false;
  573. },
  574. currentChangeHandle(page) {
  575. this.currentPage = page.newPage;
  576. this.exceptionData = this.storeExceptionData.slice(
  577. (page.newPage - 1) * this.pageSize,
  578. page.newPage * this.pageSize
  579. );
  580. },
  581. selectDialogProject(id, district) {
  582. let { ccode, level } = district;
  583. this.currentDialogCcode = ccode;
  584. this.currentDialogLevel = level;
  585. this.fetchExceptionNum(
  586. this.currentSysId,
  587. this.currentDialogTab,
  588. ccode,
  589. level
  590. );
  591. },
  592. tabChange(tab) {
  593. this.currentDialogTab = tab.id;
  594. this.fetchExceptionNum(
  595. this.currentSysId,
  596. tab.id,
  597. this.selectedDialogZone,
  598. this.currentDialogLevel
  599. );
  600. },
  601. fetchExceptionNum(smsxt, categoryCode, ccode, level) {
  602. let params = { getParams: { smsxt, categoryCode, ccode, level } };
  603. getExceptionNum(params).then((res) => {
  604. if (res.result === "success") {
  605. let vm = this;
  606. let flattenArr = [];
  607. this.centerTotal = 0;
  608. this.zoneTotal = 0;
  609. this.projectTotal = 0;
  610. recursionData(res.data);
  611. let finalHandledArr = [];
  612. flattenArr.forEach((item) => {
  613. let path = item.path.split("/");
  614. item.classExList.forEach((each) => {
  615. let obj = {};
  616. obj.center = path[0];
  617. obj.zone = path[1];
  618. obj.name = item.name;
  619. obj.reason = each.description;
  620. finalHandledArr.push(obj);
  621. });
  622. });
  623. this.storeExceptionData = cloneDeep(finalHandledArr);
  624. this.exceptionData = this.storeExceptionData.slice(0, this.pageSize);
  625. this.currentPage = 1;
  626. this.pageCount = finalHandledArr.length;
  627. function recursionData(data, parent) {
  628. data.forEach((item, index) => {
  629. let level = item.level;
  630. if (level === 2) {
  631. vm.centerTotal++;
  632. } else if (level === 3) {
  633. vm.zoneTotal++;
  634. } else if (level === 0) {
  635. vm.projectTotal++;
  636. }
  637. item.name = item.cname;
  638. item.id = item.ccode;
  639. if (level === 0) {
  640. flattenArr.push(item);
  641. }
  642. if (parent) {
  643. item.path = parent + "/" + item.cname;
  644. }
  645. let children = item.children;
  646. if (Array.isArray(children) && children.length) {
  647. recursionData(
  648. children,
  649. level == 1 ? "" : item.path ? item.path : item.cname
  650. );
  651. }
  652. });
  653. }
  654. }
  655. });
  656. },
  657. expandRestItems(item, index) {
  658. this.systemList.forEach((eq) => {
  659. if (eq.smsxt !== item.smsxt) {
  660. eq.expand = false;
  661. }
  662. eq.selected = false;
  663. });
  664. item.selected = true;
  665. item.expand = !item.expand;
  666. },
  667. showToolTip(index) {
  668. this.maintainList.forEach((item) => {
  669. item.showToolTip = false;
  670. });
  671. this.maintainList[index].showToolTip = true;
  672. },
  673. hideToolTip(index) {
  674. this.maintainList[index].showToolTip = false;
  675. },
  676. reinitalMap() {
  677. if (myMaps) {
  678. myMaps.invalidateSize(true);
  679. }
  680. },
  681. imgSrc(code) {
  682. return require("../../assets/images/icons/" + code + ".png");
  683. },
  684. /**
  685. * 跳转到 当月说明书更新项目数量
  686. */
  687. navToIntroduceUpdate() {
  688. // this.$router.push({path:''})
  689. },
  690. /**
  691. * 跳转到 上线管理说明书数量
  692. */
  693. navToManageNumber() {
  694. // this.$router.push({path:''})
  695. },
  696. /**
  697. * 跳转到 当月重点关注事项项目数量
  698. */
  699. navToFocusItems() {
  700. // this.$router.push({path:''})
  701. },
  702. /**
  703. * @Description 根据数据创建导航路径
  704. * @Param data 当前点击的项
  705. */
  706. createNavpathByData(data) {
  707. if (data.path) {
  708. let pathArr = data.path.split("/");
  709. let newArr = [];
  710. pathArr.forEach((item) => {
  711. newArr.push(item.split("&"));
  712. });
  713. this.crumbsHtml = newArr;
  714. if (data.level === 1) {
  715. this.currentZoneData = data;
  716. this.crumbsHtml = [];
  717. } else if (data.level === 0) {
  718. this.crumbsHtml.pop();
  719. this.currentZoneData = this.getDataByCityCcode(data.cparentcode);
  720. } else {
  721. this.currentZoneData = data;
  722. }
  723. } else {
  724. this.crumbsHtml = [];
  725. this.currentZoneData = this.regulateDistrictData[0];
  726. }
  727. },
  728. /**
  729. * @Description 通过导航进行导航
  730. * @Param id 所选区域的id
  731. * @Param index 点击项的序号
  732. */
  733. navgateFromCrumbs(id, index) {
  734. let data = this.getDataByCityCcode(id); // 根据
  735. if (!data) return;
  736. let level = data.level; //1集团 2中心 3区域 0广场
  737. if (level === this.regulateDistrictData[0].level) {
  738. this.selectedZone = "";
  739. }
  740. this.currentLevel = level;
  741. this.currentZoneData = data;
  742. this.getEventStatusData(level, data.ccode);
  743. this.queryPlazaInfoCount(data.ccode, data.level, data.cid);
  744. this.getSystemList(data.ccode, data.level);
  745. if (level === 1) {
  746. this.pantGroupMap(data, this.currentSysId);
  747. } else if (level === 2) {
  748. this.pantZonesMap(data, this.currentSysId);
  749. } else {
  750. this.pantProjectsMap(data, this.currentSysId);
  751. }
  752. if (level === 1) {
  753. this.crumbsHtml = "";
  754. } else {
  755. this.crumbsHtml = this.crumbsHtml.splice(0, index + 1);
  756. }
  757. },
  758. /**
  759. * @Description 分区树 点击选择分区
  760. * @Param ids 返回选中项的id
  761. * @Param data 返回选中项的数据
  762. */
  763. selectProjectItem(ids) {
  764. let data = this.getDataByCityCcode(ids);
  765. if (data.level !== 0) {
  766. // level=0时 plazaId必填
  767. this.currentLevel = data.level;
  768. this.queryPlazaInfoCount(data.ccode, data.level);
  769. this.getEventStatusData(this.currentLevel, data.ccode);
  770. this.getSystemList(data.ccode, data.level);
  771. } else {
  772. let parentNode = this.getDataByCityCcode(data.cparentcode);
  773. this.currentLevel = parentNode.level;
  774. this.selectedZone = parentNode.ccode;
  775. this.queryPlazaInfoCount(parentNode.ccode, parentNode.level);
  776. this.getEventStatusData(parentNode.level, parentNode.ccode);
  777. this.getSystemList(parentNode.ccode, parentNode.level);
  778. this.pantProjectsMap(parentNode, this.currentSysId);
  779. }
  780. this.createNavpathByData(data);
  781. let level = data.level; // //1集团 2中心 3区域 0广场
  782. if (level === 1) {
  783. this.pantGroupMap(data, this.currentSysId);
  784. } else if (level === 2) {
  785. this.pantZonesMap(data, this.currentSysId);
  786. } else if (level === 3) {
  787. this.pantProjectsMap(data, this.currentSysId);
  788. } else {
  789. // 点击项为广场时 直接跳转到详情页 地图不用响应
  790. let pathData = { fromGroup: "true" };
  791. let routeData = this.$router.resolve({
  792. name: "/home/homePage",
  793. });
  794. window.open(routeData.href, "_blank");
  795. window.__fromGroupPage = {
  796. level: 0,
  797. plazaName: data.cname,
  798. plazaId: data.ccode,
  799. };
  800. this.$store.commit("SETPLAZENAME", data.cname);
  801. localStorage.setItem("PLAZAID", data.ccode);
  802. }
  803. },
  804. /**
  805. * @Description 查询项目信息统计数量
  806. * @Param ccode 管理分区编码 必填
  807. * @Param level 1集团 2中心 3区域 0广场 必填
  808. * @Param plazaId level=0时 必填
  809. */
  810. queryPlazaInfoCount(ccode, level, plazaId) {
  811. let params = {};
  812. if (level === 0) {
  813. params = { getParams: { ccode, level } };
  814. } else {
  815. params = { getParams: { ccode, level, plazaId } };
  816. }
  817. getPlazaInfoCount(params).then((res) => {
  818. if (res.result === "success") {
  819. if (res.data) {
  820. this.plazaInfoCount = res.data;
  821. }
  822. }
  823. });
  824. },
  825. /**
  826. * @Description 根据指定id 查找数据
  827. * @Param id 要查找数据的id
  828. */
  829. getDataByCityCcode(id) {
  830. return recursionFindData(this.currentDistrictData, id);
  831. let target = null;
  832. function recursionFindData(data, id) {
  833. data.forEach((item) => {
  834. if (item.ccode === id) {
  835. target = item;
  836. } else {
  837. if (item.children && item.children.length) {
  838. recursionFindData(item.children, id);
  839. }
  840. }
  841. });
  842. if (target) {
  843. return target;
  844. }
  845. }
  846. },
  847. /**
  848. * @Description 获取分区树数据
  849. * @method param empty
  850. */
  851. getFrameworkTreeData() {
  852. login({
  853. returnTree: true,
  854. }).then((res) => {
  855. if (res.result === "success") {
  856. recursionData(res.treeData);
  857. let data = res.treeData[0];
  858. let level = data.level;
  859. this.currentZoneData = data;
  860. this.currentLevel = level; // 初始化的时候判断是哪一级 //1集团 2中心 3区域 0广场
  861. data.open = true; // 默认展开第一级
  862. this.regulateDistrictData = [data];
  863. this.dialogDistrictData = cloneDeep(this.regulateDistrictData);
  864. let firstNode = this.dialogDistrictData[0];
  865. this.selectedDialogZone = firstNode.ccode;
  866. this.selectedZone = firstNode.ccode;
  867. this.currentDialogCcode = firstNode.ccode;
  868. this.currentDialogLevel = firstNode.level;
  869. this.currentDistrictData = res.treeData;
  870. this.getSystemList(data.ccode, level).then((res) => {
  871. this.initMap();
  872. });
  873. this.getEventStatusData(level, data.ccode);
  874. if (level === 0) {
  875. // level=0时 plazaId必填
  876. this.queryPlazaInfoCount(data.ccode, level, data.ccode);
  877. } else {
  878. this.queryPlazaInfoCount(data.ccode, level);
  879. }
  880. }
  881. function recursionData(data, parent) {
  882. data.forEach((item) => {
  883. item.name = item.cname;
  884. item.id = item.ccode;
  885. if (parent) {
  886. item.path = parent + "/" + (item.cname + "&" + item.ccode);
  887. }
  888. let children = item.children;
  889. if (Array.isArray(children) && children.length) {
  890. recursionData(
  891. children,
  892. item.path ? item.path : item.cname + "&" + item.ccode
  893. );
  894. }
  895. });
  896. }
  897. });
  898. },
  899. /**
  900. * @Description 展开 维保 第三方检测 专维
  901. * @Param item 展开的某一项
  902. */
  903. toggerPanel(item) {
  904. // expand 0 初始状态 1 展开状态 2 隐藏状态
  905. if (item.expand === 0 || item.expand === 2) {
  906. item.expand = 1; // 展开
  907. this.maintainList.forEach((option) => {
  908. if (option.title !== item.title) {
  909. option.expand = 2; // 隐藏
  910. }
  911. });
  912. } else {
  913. this.maintainList.forEach((option) => {
  914. option.expand = 0; // 回到初始状态
  915. });
  916. }
  917. },
  918. /**
  919. * @Description 计算 维保/第三方检测/专维 三个模块的高度
  920. * @Param item 数据中的每一项
  921. */
  922. panelStyle(item) {
  923. // expand 0 初始状态 1 展开状态 2 隐藏状态
  924. if (item.expand === 0) {
  925. return { height: `calc((100% - 2rem) / 3)` };
  926. } else if (item.expand === 1) {
  927. return { height: "calc(100% - 11.2rem)" };
  928. } else {
  929. return { height: "4.6rem" };
  930. }
  931. },
  932. /**
  933. *@Description 根据数据计算维保/第三方检测/专维各自颜色条的长度 维保、第三方检测是用即将逾期数据判断;专维是如果有逾期未完成直接标红,如果没有,按照即将逾期的数量显示颜色
  934. *@Param item 某一项的数据
  935. *@Param title 标题
  936. */
  937. barStyle(item, title) {
  938. let bg = "";
  939. // let type = this.selectColorByNum(item.due_num, item.total)
  940. let ratio = 0;
  941. if (title === "专维") {
  942. item.overdue_unfinished = item.overdue_unfinished || 0;
  943. if (item.overdue_unfinished > 0 || item.due_num > 0) {
  944. bg = this.skinMode ==='light' ? "linear-gradient(to right, #F54E45 , #F54E45)" : 'linear-gradient(to right, #DE944D , #F58300)';
  945. }
  946. // else {
  947. // bg = this.barColors[type]
  948. // }
  949. ratio = ((item.overdue_unfinished + item.due_num) / item.total) * 100;
  950. } else {
  951. if (item.due_num > 0) {
  952. bg = this.skinMode ==='light' ? "linear-gradient(to right, #F54E45 , #F54E45)" : 'linear-gradient(to right, #DE944D , #F58300)';
  953. }
  954. // bg = this.barColors[type]
  955. ratio = (item.due_num / item.total) * 100;
  956. }
  957. return {
  958. width: ratio + "%",
  959. backgroundImage: bg,
  960. };
  961. },
  962. /**
  963. * @Description 根据数据来返 维保/第三方检测/专维 三个模块中显示条的颜色
  964. * @Param num 即将逾期数 / 逾期未完成数
  965. * @Param total 总数
  966. */
  967. selectColorByNum(num, total) {
  968. let devide = num / total;
  969. if ((num > 1 && num <= 24) || (devide > 0.1 && devide <= 0.2)) {
  970. return 0;
  971. } else if ((num > 24 && num <= 49) || (devide > 0.2 && devide <= 0.5)) {
  972. return 1;
  973. } else {
  974. return 2;
  975. }
  976. },
  977. /**
  978. * @Description 根据数据 判定地图上图标的显示显示颜色
  979. * @Param data 作为判断的数据
  980. */
  981. paintColorByData(data) {
  982. if (data >= 200) {
  983. return "level5";
  984. } else if (data >= 100 && data < 200) {
  985. return "level4";
  986. } else if (data >= 50 && data < 100) {
  987. return "level3";
  988. } else if (data >= 10 && data < 50) {
  989. return "level2";
  990. } else if (data >= 1 && data < 10) {
  991. return "level1";
  992. } else {
  993. return "level0";
  994. }
  995. },
  996. /**
  997. * @Description 显示当期时间
  998. */
  999. currentTime() {
  1000. this.times = moment().format("YYYY.MM.DD HH:mm");
  1001. setTimeout(this.currentTime, 1000);
  1002. },
  1003. /**
  1004. * @Description 格式化时间
  1005. * @method param empty
  1006. */
  1007. formatter(str, arrv) {
  1008. if (str && arrv) {
  1009. const Objs = arrv.find((e) => e && e.plazaid == str);
  1010. return Objs ? Objs.plazaname : "--";
  1011. } else {
  1012. return "";
  1013. }
  1014. },
  1015. /**
  1016. * @Description 获取集团 中心 区域 项目 数据树数据
  1017. * @method param ccode 管理分区编码 集团首页必填
  1018. * @method param level 1集团 2中心 3区域 0广场 集团首页必填
  1019. * @method param plazaId 广场id 如果是广场则此参数必填 其他情况下非必填
  1020. */
  1021. getSystemList(ccode, level) {
  1022. let params = null;
  1023. if (level === 0) {
  1024. params = { getParams: { plazaId: ccode, level } };
  1025. } else {
  1026. params = { getParams: { ccode, level } };
  1027. }
  1028. return new Promise((resolve, reject) => {
  1029. getCardList(params).then((res) => {
  1030. if (res.result == "success") {
  1031. let result = res.data;
  1032. if (result && Array.isArray(result)) {
  1033. result.forEach((item) => {
  1034. let list = item.assetTypeList;
  1035. if (list) {
  1036. if (list.length > 3) {
  1037. item.hasArrow = true;
  1038. item.assetTypeList = list.splice(0, 3);
  1039. item.restAssetTypeList = list;
  1040. item.showColor = list.some((item) => {
  1041. return item.is_exception_num > 0;
  1042. });
  1043. } else {
  1044. item.hasArrow = false;
  1045. item.restAssetTypeList = [];
  1046. }
  1047. }
  1048. });
  1049. res.data.forEach((item) => {
  1050. item.selected = false;
  1051. item.expand = false;
  1052. });
  1053. res.data[0].selected = true;
  1054. this.currentSelectedSys = res.data[0];
  1055. this.currentSysId = res.data[0].smsxt;
  1056. this.systemList = res.data;
  1057. resolve(res);
  1058. }
  1059. }
  1060. });
  1061. });
  1062. },
  1063. /**
  1064. * @Description 获取事项状态统计数据
  1065. * @Param ccode 管理分区编码 必填
  1066. * @Param level 1集团 2中心 3区域 0广场 必填
  1067. */
  1068. getEventStatusData(level, ccode) {
  1069. let params = {
  1070. getParams: {
  1071. level,
  1072. ccode,
  1073. },
  1074. };
  1075. queryEventStatus(params).then((res) => {
  1076. if (res.result === "success") {
  1077. let data = res.data;
  1078. data[0].forEach((item) => {
  1079. if (
  1080. typeof item.rptGlsmsStatistics.overdue_unfinished === "undefined"
  1081. ) {
  1082. item.rptGlsmsStatistics.overdue_unfinished = 0;
  1083. }
  1084. });
  1085. let orginalObj = {
  1086. 1: { title: "维保", data: [], expand: 0, showToolTip: false },
  1087. 2: { title: "第三方检测", data: [], expand: 0, showToolTip: false },
  1088. 0: { title: "专维", data: [], expand: 0, showToolTip: false },
  1089. };
  1090. let arr = new Array(3);
  1091. for (let key in data) {
  1092. let obj = {};
  1093. let sortData = data[key];
  1094. if (data.hasOwnProperty(key)) {
  1095. // 维保,第三方检测排名按照即将逾期任务数量从多到少排序,多的靠前。专维按照 逾期未完成 + 即将逾期任务数据排序,多的靠前
  1096. // due_num 即将逾期 unfinished 逾期未完成
  1097. if (key == "0") {
  1098. sortData.forEach((item) => {
  1099. item.sort =
  1100. item.rptGlsmsStatistics.overdue_unfinished +
  1101. item.rptGlsmsStatistics.unfinished;
  1102. });
  1103. } else {
  1104. sortData.forEach((item) => {
  1105. item.sort = item.rptGlsmsStatistics.due_num;
  1106. });
  1107. }
  1108. orginalObj[key].data = sortBy(sortData, (option) => {
  1109. return option.sort;
  1110. }).reverse();
  1111. }
  1112. }
  1113. arr[0] = orginalObj[1];
  1114. arr[1] = orginalObj[2];
  1115. arr[2] = orginalObj[0];
  1116. this.maintainList = arr;
  1117. }
  1118. });
  1119. },
  1120. /**
  1121. *@Description 初始化地图
  1122. */
  1123. initMap() {
  1124. let that = this;
  1125. myMaps = L.map("map", {
  1126. center: new L.LatLng(38, 103),
  1127. zoom: 4,
  1128. crs: L.CRS.EPSG3857,
  1129. zoomControl: false,
  1130. boxZoom: false,
  1131. attributionControl: false,
  1132. contextmenu: true,
  1133. contextmenuWidth: 140,
  1134. minZoom: 4,
  1135. maxZoom: 10,
  1136. closePopupOnClick: true,
  1137. doubleClickZoom: false,
  1138. wheelPxPerZoomLevel: 20,
  1139. // scrollWheelZoom:false,
  1140. // dragging: false,
  1141. });
  1142. let JsonData = require("../../assets/geoData/china.json");
  1143. this.mapLayer = L.geoJSON(JsonData.features, {
  1144. style: function () {
  1145. return {
  1146. weight: 1,
  1147. color: "#B3D2FF",
  1148. fillColor: "#DEECFF",
  1149. };
  1150. },
  1151. }).addTo(myMaps);
  1152. if (this.currentLevel === 1) {
  1153. //1集团
  1154. this.pantGroupMap(this.currentZoneData, this.currentSysId);
  1155. } else if (this.currentLevel === 2) {
  1156. // 2中心
  1157. this.pantZonesMap(this.currentZoneData, this.currentSysId);
  1158. } else if (this.currentLevel === 3) {
  1159. // 3区域
  1160. this.pantProjectsMap(this.currentZoneData, this.currentSysId);
  1161. }
  1162. },
  1163. /**
  1164. * @Description 清空地图 并添加全国底图
  1165. */
  1166. clearAllLayers() {
  1167. const vm = this
  1168. myMaps.eachLayer(function (layer) {
  1169. myMaps.removeLayer(layer);
  1170. });
  1171. let JsonData = require("../../assets/geoData/china.json");
  1172. this.mapLayer = L.geoJSON(JsonData.features, {
  1173. style: function () {
  1174. return {
  1175. weight: 1,
  1176. color: vm.skinMode === "light" ? "#B3D2FF" :"#56a3c2",
  1177. fillColor: vm.skinMode === "light" ? "#DEECFF" : "#21285c",
  1178. fillOpacity: vm.skinMode === "light" ? 0.2 : 1
  1179. };
  1180. },
  1181. }).addTo(myMaps);
  1182. },
  1183. /**
  1184. * @Description 移动地图到指定中心
  1185. */
  1186. flyTo(center, zoom) {
  1187. myMaps.setView(center, zoom);
  1188. },
  1189. /**
  1190. *@description 打开弹窗
  1191. */
  1192. openMaskPanel(system) {
  1193. if(this.skinMode === 'dark') {
  1194. return false;
  1195. }
  1196. let target = this.getDataByCityCcode(this.selectedZone)
  1197. if (target) {
  1198. this.currentDialogLevel = target.level
  1199. this.currentLevel = target.level
  1200. }
  1201. this.currentSysId = system.smsxt;
  1202. this.tabData = [];
  1203. this.selectedDialogZone = this.selectedZone;
  1204. system.restAssetTypeList.forEach((item) => {
  1205. if (item.is_exception_num > 0) {
  1206. this.tabData.push({
  1207. name: item.category_name,
  1208. id: item.category_code,
  1209. });
  1210. }
  1211. });
  1212. system.assetTypeList.forEach((item) => {
  1213. if (item.is_exception_num > 0) {
  1214. this.tabData.push({
  1215. name: item.category_name,
  1216. id: item.category_code,
  1217. });
  1218. }
  1219. });
  1220. if (this.tabData.length) {
  1221. this.activeName = this.tabData[0].id;
  1222. this.currentDialogTab = this.activeName;
  1223. this.dialogVisible = true;
  1224. }
  1225. this.fetchExceptionNum(
  1226. system.smsxt,
  1227. this.activeName,
  1228. this.selectedDialogZone,
  1229. this.currentLevel
  1230. );
  1231. },
  1232. /**
  1233. * @Description 切换系统时 地图响应
  1234. * @Params system:当前选择的系统
  1235. */
  1236. getInfoOfProject(system) {
  1237. this.systemList.forEach((item) => {
  1238. item.selected = false;
  1239. });
  1240. system.selected = true;
  1241. this.currentSelectedSys = system;
  1242. this.currentSysId = system.smsxt;
  1243. //1集团 2中心 3区域 0广场
  1244. this.clearAllLayers();
  1245. if (this.currentLevel === 1) {
  1246. this.pantGroupMap(this.currentZoneData, system.smsxt);
  1247. } else if (this.currentLevel === 2) {
  1248. this.pantZonesMap(this.currentZoneData, system.smsxt);
  1249. } else if (this.currentLevel === 3) {
  1250. this.pantProjectsMap(this.currentZoneData, system.smsxt);
  1251. }
  1252. },
  1253. /**
  1254. * @Description 用于绘制集团级别的地图
  1255. * @Param data 数据
  1256. */
  1257. pantGroupMap(data) {
  1258. this.clearAllLayers();
  1259. myMaps.setView([38, 103], 4);
  1260. let that = this;
  1261. let groupLayer = new L.layerGroup();
  1262. let promiseAll = [];
  1263. let layerArr = [];
  1264. this.loadingInstance = Loading.service({
  1265. target: "#map",
  1266. fullscreen: false,
  1267. text: "数据正在加载...",
  1268. background: "rgba(255,255,255,.5)",
  1269. });
  1270. data.children.forEach((item) => {
  1271. let promise = new Promise((resolve, reject) => {
  1272. let params = {
  1273. getParams: {
  1274. smsxt: this.currentSysId,
  1275. level: 2, // 中心
  1276. ccode: item.ccode,
  1277. },
  1278. };
  1279. querySystemCard(params).then((res) => {
  1280. if (res.result === "success") {
  1281. let num = 0;
  1282. let name = item.cname.substr(0, 2);
  1283. if (res.data) {
  1284. let equip = res.data[0];
  1285. if (equip.assetTypeList) {
  1286. equip.assetTypeList.forEach((item) => {
  1287. if (item.is_exception_num) {
  1288. num += item.is_exception_num;
  1289. }
  1290. });
  1291. layerArr.push({
  1292. name,
  1293. num,
  1294. list: equip,
  1295. data: item,
  1296. fullName: item.cname,
  1297. });
  1298. }
  1299. resolve(res);
  1300. }
  1301. }
  1302. });
  1303. });
  1304. promiseAll.push(promise);
  1305. });
  1306. Promise.all(promiseAll).then((result) => {
  1307. this.loadingInstance.close();
  1308. if (this.currentLevel === 1) {
  1309. layerArr.forEach((item) => {
  1310. let zone = this.zoneNames[item.name];
  1311. let center = this.zoneCenter[zone];
  1312. let contentHtml = that.createPopupHtmlContent(
  1313. item.list.assetTypeList,
  1314. item.fullName
  1315. );
  1316. if (contentHtml) {
  1317. this.createPointOnMap(
  1318. item.num,
  1319. groupLayer,
  1320. contentHtml,
  1321. center,
  1322. item.data,
  1323. item.name,
  1324. "group",
  1325. 4
  1326. );
  1327. }
  1328. });
  1329. }
  1330. });
  1331. groupLayer.addTo(myMaps);
  1332. },
  1333. /**
  1334. * @Description 用于绘制中心地图
  1335. * @Param data 数据
  1336. */
  1337. pantZonesMap(data) {
  1338. let that = this;
  1339. this.clearAllLayers();
  1340. let name = data.cname.substr(0, 2);
  1341. let zone = this.zoneNames[name];
  1342. let zoom, inner, outer, offset;
  1343. if (zone === "huadong") {
  1344. zoom = 8;
  1345. } else if (zone == "xibei") {
  1346. zoom = 5;
  1347. } else {
  1348. zoom = 6;
  1349. }
  1350. this.flyTo(this.zoneCenter[zone], zoom);
  1351. let groupLayer = new L.layerGroup();
  1352. let promiseAll = [];
  1353. let layerArr = [];
  1354. this.loadingInstance = Loading.service({
  1355. target: "#map",
  1356. fullscreen: false,
  1357. text: "数据正在返回...",
  1358. background: "rgba(255,255,255,.5)",
  1359. });
  1360. data.children.forEach((item) => {
  1361. let promise = new Promise((resolve, reject) => {
  1362. let params = {
  1363. getParams: {
  1364. smsxt: this.currentSysId,
  1365. level: 3, // 区域
  1366. ccode: item.ccode,
  1367. },
  1368. };
  1369. querySystemCard(params).then((res) => {
  1370. if (res.result === "success") {
  1371. let name = item.cname.split("区域")[0];
  1372. let num = 0;
  1373. if (res.data) {
  1374. let equip = res.data[0];
  1375. if (equip.assetTypeList) {
  1376. equip.assetTypeList.forEach((item) => {
  1377. if (item.is_exception_num) {
  1378. num += item.is_exception_num;
  1379. }
  1380. });
  1381. layerArr.push({
  1382. name,
  1383. num,
  1384. list: equip,
  1385. data: item,
  1386. fullName: item.cname,
  1387. });
  1388. }
  1389. }
  1390. resolve(res);
  1391. }
  1392. });
  1393. });
  1394. promiseAll.push(promise);
  1395. });
  1396. Promise.all(promiseAll).then((result) => {
  1397. this.loadingInstance.close();
  1398. if (this.currentLevel === 2) {
  1399. layerArr.forEach((item) => {
  1400. let city = that.provinceCities[item.name];
  1401. let center = city.center;
  1402. let contentHtml = that.createPopupHtmlContent(
  1403. item.list.assetTypeList,
  1404. item.fullName
  1405. );
  1406. if (contentHtml) {
  1407. that.createPointOnMap(
  1408. item.num,
  1409. groupLayer,
  1410. contentHtml,
  1411. center,
  1412. item.data,
  1413. item.data.cname,
  1414. "zone",
  1415. zoom
  1416. );
  1417. }
  1418. });
  1419. }
  1420. });
  1421. groupLayer.addTo(myMaps);
  1422. },
  1423. /**
  1424. * @Description 用于绘制项目的点
  1425. * @Param data 数据
  1426. */
  1427. pantProjectsMap(data) {
  1428. this.clearAllLayers();
  1429. let name = data.cname.split("区域")[0];
  1430. let geo = this.provinceCities[name];
  1431. let that = this;
  1432. let promiseAll = [];
  1433. let layerArr = [];
  1434. let groupLayer = new L.layerGroup();
  1435. this.flyTo(geo.center, geo.zoom);
  1436. this.loadingInstance = Loading.service({
  1437. target: "#map",
  1438. fullscreen: false,
  1439. text: "数据正在返回...",
  1440. background: "rgba(255,255,255,.5)",
  1441. });
  1442. data.children.forEach((item) => {
  1443. let pormise = new Promise((resolve, reject) => {
  1444. let params = {
  1445. getParams: {
  1446. plazaId: item.cid, // 所查对象是广场的时候plazaId必传
  1447. smsxt: this.currentSysId,
  1448. level: 0, // 广场
  1449. ccode: item.ccode,
  1450. },
  1451. };
  1452. querySystemCard(params).then((res) => {
  1453. if (res.result === "success") {
  1454. let num = 0;
  1455. if (res.data && item.latitude && item.longitude) {
  1456. let equip = res.data[0];
  1457. if (equip.assetTypeList) {
  1458. equip.assetTypeList.forEach((item) => {
  1459. if (item.is_exception_num) {
  1460. num += item.is_exception_num;
  1461. }
  1462. });
  1463. }
  1464. layerArr.push({
  1465. name,
  1466. num,
  1467. list: equip,
  1468. data: item,
  1469. fullName: item.cname,
  1470. });
  1471. }
  1472. resolve(res);
  1473. }
  1474. groupLayer.addTo(myMaps);
  1475. });
  1476. });
  1477. promiseAll.push(pormise);
  1478. });
  1479. Promise.all(promiseAll).then((result) => {
  1480. this.loadingInstance.close();
  1481. if (this.currentLevel === 3) {
  1482. layerArr.forEach((item) => {
  1483. let center = [item.data.latitude, item.data.longitude];
  1484. let contentHtml = that.createPopupHtmlContent(
  1485. item.list.assetTypeList,
  1486. item.fullName
  1487. );
  1488. if (contentHtml) {
  1489. that.createPointOnMap(
  1490. item.num,
  1491. groupLayer,
  1492. contentHtml,
  1493. center,
  1494. item.data,
  1495. item.data.cname,
  1496. "project",
  1497. geo.zoom
  1498. );
  1499. }
  1500. });
  1501. }
  1502. });
  1503. groupLayer.addTo(myMaps);
  1504. },
  1505. /**
  1506. * @Description 用于绘制广场的点
  1507. * @Param num 当前点的逾期设备数
  1508. * @Param groupLayer 地图图层
  1509. * @Param contentHtml 弹出框的Html内容
  1510. * @Param center 该点坐标
  1511. * @Param data 该点数据
  1512. * @Param name 改点名称
  1513. * @Param type 地图级别 group / zone / project 集团 / 中心 / 区域
  1514. * @param zoom 缩放级别
  1515. */
  1516. createPointOnMap(
  1517. num,
  1518. groupLayer,
  1519. contentHtml,
  1520. center,
  1521. data,
  1522. name,
  1523. type,
  1524. zoom
  1525. ) {
  1526. let vm =this
  1527. let color = this.paintColorByData(num);
  1528. let textIcon = L.divIcon({
  1529. html: type == "group" ? name : `<div>${name}</div>`,
  1530. className: vm.skinMode==='light'? "my-leaflet-div-icon":"dark-my-leaflet-div-icon",
  1531. iconSize: 30,
  1532. });
  1533. let circleIcon = L.icon({
  1534. iconUrl: require(`../../assets/images/icons/${color}.png`),
  1535. iconSize: [24, 24],
  1536. iconAnchor: [16, 38],
  1537. });
  1538. if (color && center) {
  1539. let popup = L.popup({ closeOnClick: true, offset: [-3, -20] })
  1540. .setLatLng(center)
  1541. .setContent(contentHtml);
  1542. let marker = L.marker(center, { icon: textIcon }).addTo(groupLayer);
  1543. let marker2 = L.marker(center, { icon: circleIcon }).addTo(groupLayer);
  1544. let feaureGroup = L.featureGroup([marker, marker2]);
  1545. popup.on('add' , (ev) => {
  1546. let popupDom = document.querySelectorAll('.leaflet-mypopup-content')[0]
  1547. let tipDom = document.querySelectorAll('.leaflet-popup-tip')[0]
  1548. console.log(tipDom)
  1549. if (this.skinMode === 'light') {
  1550. popupDom.setAttribute('class', 'leaflet-mypopup-content')
  1551. tipDom.style.background="white"
  1552. } else {
  1553. popupDom.setAttribute('class', 'dark-leaflet-mypopup-content')
  1554. tipDom.style.background="#09173E"
  1555. }
  1556. })
  1557. marker2.on("mouseover", (ev) => {
  1558. popup.openOn(myMaps);
  1559. });
  1560. marker2.on("mouseout", (ev) => {
  1561. myMaps.closePopup(popup);
  1562. });
  1563. feaureGroup.on("click", (ev) => {
  1564. this.currentZoneData = data;
  1565. this.currentLevel = data.level;
  1566. if (data.level !== 0) {
  1567. this.getEventStatusData(data.level, data.ccode);
  1568. this.queryPlazaInfoCount(data.ccode, data.level);
  1569. this.getSystemList(data.ccode, data.level);
  1570. }
  1571. if (type !== "project") {
  1572. groupLayer.clearLayers();
  1573. }
  1574. this.createNavpathByData(data);
  1575. if (type === "group") {
  1576. this.pantZonesMap(data, this.currentSysId);
  1577. }
  1578. if (type === "zone") {
  1579. this.pantProjectsMap(data, this.currentSysId);
  1580. }
  1581. if (type === "project") {
  1582. let routeData = this.$router.resolve({
  1583. name: "/home/homePage",
  1584. });
  1585. window.open(routeData.href, "_blank");
  1586. window.__fromGroupPage = {
  1587. level: 0,
  1588. plazaName: data.cname,
  1589. plazaId: data.ccode,
  1590. };
  1591. this.$store.commit("SETPLAZENAME", data.cname);
  1592. localStorage.setItem("PLAZAID", data.ccode);
  1593. }
  1594. });
  1595. }
  1596. },
  1597. /**
  1598. *@Description 生成弹出框HTML
  1599. */
  1600. createPopupHtmlContent(data, name) {
  1601. if (Array.isArray(data) && data.length) {
  1602. let that = this;
  1603. let html = "";
  1604. let len = data.length;
  1605. for (let i = 0; i < len; i++) {
  1606. let item = data[i];
  1607. if (item.is_exception_num) {
  1608. html += `<div class="line">
  1609. <span>${item.category_name}</span>
  1610. <span>${item.asset_num || "--"}${
  1611. item.category_name === "屋面logo"
  1612. ? "个"
  1613. : item.category_name === "玻璃护栏"
  1614. ? "段"
  1615. : "台"
  1616. }</span>
  1617. <span><span style="display: inline-block;width: 16px;height: 16px;line-height: 16px;border-radius: 8px; color: white; background : #F54E45;text-align: center;cursor: default;">!</span><em>${
  1618. item.is_exception_num
  1619. }</em></span>
  1620. </div>`;
  1621. } else {
  1622. html += `<div class="line">
  1623. <span>${item.category_name}</span>
  1624. <span>${item.asset_num || "--"}${
  1625. item.category_name === "屋面logo"
  1626. ? "个"
  1627. : item.category_name === "玻璃护栏"
  1628. ? "段"
  1629. : "台"
  1630. }</span>
  1631. </div>`;
  1632. }
  1633. }
  1634. return `<div class="leaflet-mypopup-content" }"><div class="title"><span>${name}</span>-<span>${that.currentSelectedSys.smsxtname}</span></div>${html}</div>`;
  1635. } else {
  1636. return "";
  1637. }
  1638. },
  1639. },
  1640. beforeDestroy() {
  1641. window.removeEventListener("resize", this.reinitalMap);
  1642. },
  1643. };
  1644. </script>
  1645. <style scoped lang="less">
  1646. @import "../../assets/css/dark.less";
  1647. @import "../../assets/css/light.less";
  1648. .dark-my-leaflet-div-icon{
  1649. color: white;
  1650. }
  1651. @keyframes selectDownUpExtendTop {
  1652. from {
  1653. transform: translateY(8px);
  1654. opacity: 0;
  1655. }
  1656. to {
  1657. transform: translateY(0);
  1658. opacity: 1;
  1659. }
  1660. }
  1661. .selectDownUpExtendTop-enter-active {
  1662. animation: selectDownUpExtendTop 0.3s;
  1663. }
  1664. .selectDownUpExtendTop-leave-active {
  1665. animation: selectDownUpExtendTop 0.3s reverse;
  1666. }
  1667. /deep/ .p-tree-single-panel {
  1668. height: 400px !important;
  1669. }
  1670. /deep/ .el-dialog__header {
  1671. display: none !important;
  1672. }
  1673. /deep/ .el-dialog__body {
  1674. padding-top: 0;
  1675. }
  1676. </style>