index.vue 56 KB

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