borard.vue 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. <template>
  2. <div class="dataView-content">
  3. <!-- <dv-loading>Loading...</dv-loading> -->
  4. <div class="data-header">
  5. <div class="total-block">
  6. <div>
  7. <div class="total-label"><i class="cor1" v-for="item in 3" :key="item">|</i>用户总数</div>
  8. <div class="total-value cor1">{{ userTotal }}</div>
  9. </div>
  10. <div>
  11. <div class="total-label"><i class="cor2" v-for="item in 3" :key="item">|</i>试点单位数</div>
  12. <div class="total-value cor2">{{ dwTotal }}</div>
  13. </div>
  14. <div>
  15. <div class="total-label"><i class="cor3" v-for="item in 3" :key="item">|</i>设备总数</div>
  16. <div class="total-value cor3">{{ devTotal }}</div>
  17. </div>
  18. </div>
  19. <div class="page-title">
  20. <!-- 智享亿家投递大数据 -->
  21. </div>
  22. <div>
  23. <div class="border-box-content">
  24. <div>区域</div>
  25. <!-- <select v-model="queryParam.provinceCode" @change="getCityList" placeholder="省">
  26. <option value="">省</option>
  27. <option v-for="item in addrProvinceList" :value="item.id" :key="item.id + 'a'">{{ item.name }}</option>
  28. </select> -->
  29. <select v-model="queryParam.cityCode" @change="getAreaList" placeholder="市">
  30. <option value="">全部</option>
  31. <option v-for="item in addrCityList" :value="item.id" :key="item.id + 'b'">{{ item.name }}
  32. </option>
  33. </select>
  34. <!-- <select v-model="queryParam.districtCode" @change="initChart" placeholder="区/县">
  35. <option value="">全部区/县</option>
  36. <option v-for="item in addrDistrictList" :value="item.id" :key="item.id + 'c'">{{ item.name }}</option>
  37. </select> -->
  38. <a-icon
  39. @click="isFullscreenMap"
  40. :style="{fontSize:'30px',padding: '7px',float: 'right', cursor: 'pointer'}"
  41. :type="isMapFull ?'fullscreen-exit':'fullscreen'" />
  42. </div>
  43. </div>
  44. </div>
  45. <div class="data-body">
  46. <div class="b-middle">
  47. <div>
  48. <dv-border-box-8 ref="map" style="padding: 10px;">
  49. <div class="lajiliang">
  50. <div class="laji-title">垃圾产生量</div>
  51. <div class="laji-item">
  52. <div class="cor1">可回收垃圾</div>
  53. <div>{{ rubbishWeightData.RECYCLING }} kg</div>
  54. </div>
  55. <div class="laji-item">
  56. <div class="cor2">其它垃圾</div>
  57. <div>{{ rubbishWeightData.GATHER_OTHER }} kg</div>
  58. </div>
  59. <div class="laji-item">
  60. <div class="cor3">厨余垃圾</div>
  61. <div>{{ rubbishWeightData.GATHER_KITCHEN }} kg</div>
  62. </div>
  63. <div class="laji-item">
  64. <div class="cor4">建筑垃圾</div>
  65. <div>{{ rubbishWeightData.GATHER_BUILDING }} kg</div>
  66. </div>
  67. <div class="laji-item">
  68. <div class="cor5">有害垃圾</div>
  69. <div>{{ rubbishWeightData.HARM }} kg</div>
  70. </div>
  71. <div class="laji-total">共计<span>{{ rubbishWeightTotal }}</span>kg</div>
  72. </div>
  73. <div id="map" :style="{height: '100%'}"></div>
  74. </dv-border-box-8>
  75. </div>
  76. <div>
  77. <div>
  78. <dv-border-box-13 ref="con1">
  79. <div id="con1" style="width: 100%;height: 100%;"></div>
  80. </dv-border-box-13>
  81. </div>
  82. <div>
  83. <dv-border-box-13 ref="con2">
  84. <div id="con2" style="width: 100%;height: 100%;"></div>
  85. </dv-border-box-13>
  86. </div>
  87. <div>
  88. <dv-border-box-13 ref="con4">
  89. <div id="con4" style="width: 100%;height: 100%;"></div>
  90. </dv-border-box-13>
  91. </div>
  92. </div>
  93. </div>
  94. <div class="b-right">
  95. <!-- 设备比例分布 -->
  96. <div>
  97. <dv-border-box-13 ref="con3">
  98. <div id="con3" style="width: 100%;height: 100%;"></div>
  99. </dv-border-box-13>
  100. </div>
  101. <!-- 各分类垃圾量分布 -->
  102. <div>
  103. <dv-border-box-13 ref="con5">
  104. <div id="con5" style="width: 100%;height: 100%;"></div>
  105. </dv-border-box-13>
  106. </div>
  107. <!-- 各机构投递量分布比例 -->
  108. <div>
  109. <dv-border-box-13 ref="con6">
  110. <div id="con6" style="width: 100%;height: 100%;"></div>
  111. </dv-border-box-13>
  112. </div>
  113. </div>
  114. </div>
  115. </div>
  116. </template>
  117. <script>
  118. import echarts from 'echarts'
  119. import {
  120. getUserTotal,
  121. getDeviceTotal,
  122. getMapStation
  123. } from '@/api/nodeMap.js'
  124. import {
  125. getNewRegister,
  126. getTimeSharingLog,
  127. getDeliveryTop,
  128. getHeatMapData,
  129. getLocationCode,
  130. getRubbishTypeTotal,
  131. querySumWeight,
  132. labelWeightPercent,
  133. devicePercent,
  134. getDwTotal
  135. } from '@/api/borard.js'
  136. import {
  137. getProvince,
  138. getCityByPro,
  139. getDistrictByCity
  140. } from '@/api/station'
  141. import moment from 'moment'
  142. import getDate from '@/libs/getDate.js'
  143. export default {
  144. name: 'DataBoratd',
  145. data () {
  146. return {
  147. queryParam: {
  148. provinceCode: '610000', // 省
  149. cityCode: '', // 市
  150. districtCode: '' // 区
  151. },
  152. addrProvinceList: [{
  153. code: '610000',
  154. id: '610000',
  155. isOpen: '0',
  156. name: '陕西省',
  157. parentId: '100000',
  158. parentIds: '100000',
  159. sort: 27,
  160. type: '2'
  161. }], // 省下拉
  162. addrCityList: [{
  163. 'id': '610100',
  164. 'sort': 1,
  165. 'parentId': '610000',
  166. 'parentIds': '100000,610000',
  167. 'isOpen': '0',
  168. 'name': '西安市',
  169. 'code': '610100'
  170. },
  171. {
  172. 'id': '610400',
  173. 'sort': 4,
  174. 'parentId': '610000',
  175. 'parentIds': '100000,610000',
  176. 'isOpen': '0',
  177. 'name': '咸阳市',
  178. 'code': '610400'
  179. }
  180. ], // 市下拉
  181. addrDistrictList: [], // 区下拉
  182. chart1: null,
  183. chart2: null,
  184. chart3: null,
  185. chart4: null,
  186. chart5: null,
  187. chart6: null,
  188. userTotal: 0,
  189. devTotal: 0,
  190. dwTotal: 0,
  191. isMapFull: false,
  192. map: null, // 地图对象
  193. markerLayer: null, // 地图点标记对象
  194. infoWindow: null, // 地图信息窗口对象
  195. beginDate: moment().subtract('days', 7).format('YYYY-MM-DD 00:00:00'), // 查询开始时间
  196. endDate: moment(moment().add(-1, 'days').endOf('day').valueOf()).format('YYYY-MM-DD 23:59:59'), // 查询结束时间
  197. rubbishWeightData: {
  198. 'GATHER_OTHER': 0, // 其它垃圾
  199. 'GATHER_KITCHEN': 0, // 厨余垃圾
  200. 'GATHER_BUILDING': 0, // 建筑垃圾
  201. 'HARM': 0, // 有害垃圾
  202. 'RECYCLING': 0 // 可回收垃圾
  203. }, // 垃圾产生量数据
  204. rubbishWeightTotal: 0 // 垃圾产生量数据总计
  205. }
  206. },
  207. methods: {
  208. // 获取省列表'
  209. getProvinceList () {
  210. getProvince().then(res => {
  211. if (res.status == 200) {
  212. this.addrProvinceList = res.data || []
  213. } else {
  214. this.addrProvinceList = []
  215. }
  216. })
  217. },
  218. // 获取城市列表
  219. getCityList (e) {
  220. if (e.target.value == '') return
  221. this.addrCityList = []
  222. this.addrDistrictList = []
  223. this.queryParam.cityCode = ''
  224. this.queryParam.districtCode = ''
  225. this.getCityListRequest(e.target.value)
  226. },
  227. getCityListRequest (val) {
  228. getCityByPro({
  229. id: val
  230. }).then(res => {
  231. if (res.status == 200) {
  232. this.addrCityList = res.data || []
  233. } else {
  234. this.addrCityList = []
  235. }
  236. })
  237. },
  238. // 获取区县列表
  239. getAreaList (e) {
  240. if (e.target.value == '') {
  241. this.initChart()
  242. return
  243. }
  244. this.addrDistrictList = []
  245. this.queryParam.districtCode = ''
  246. // 地图经纬度
  247. this.getLocationCode()
  248. this.getAreaListRequest(e.target.value)
  249. this.initChart()
  250. },
  251. getAreaListRequest (val) {
  252. getDistrictByCity({
  253. id: val
  254. }).then(res => {
  255. if (res.status == 200) {
  256. this.addrDistrictList = res.data || []
  257. } else {
  258. this.addrDistrictList = []
  259. }
  260. })
  261. },
  262. // 全屏
  263. fullScreen () {
  264. var element = document.documentElement
  265. if (element.requestFullscreen) {
  266. element.requestFullscreen()
  267. } else if (element.msRequestFullscreen) {
  268. element.msRequestFullscreen()
  269. } else if (element.mozRequestFullScreen) {
  270. element.mozRequestFullScreen()
  271. } else if (element.webkitRequestFullscreen) {
  272. element.webkitRequestFullscreen()
  273. }
  274. },
  275. // 退出全屏
  276. exitFullscreen () {
  277. if (document.exitFullscreen) {
  278. document.exitFullscreen()
  279. } else if (document.msExitFullscreen) {
  280. document.msExitFullscreen()
  281. } else if (document.mozCancelFullScreen) {
  282. document.mozCancelFullScreen()
  283. } else if (document.webkitExitFullscreen) {
  284. document.webkitExitFullscreen()
  285. }
  286. },
  287. // 地图是否全屏展示
  288. isFullscreenMap () {
  289. this.isMapFull = !this.isMapFull
  290. if (this.isMapFull) {
  291. this.fullScreen()
  292. } else {
  293. this.exitFullscreen()
  294. }
  295. this.chart1.resize()
  296. this.chart2.resize()
  297. this.chart3.resize()
  298. this.chart4.resize()
  299. },
  300. formatter (number) {
  301. const numbers = number.toString().split('').reverse()
  302. const segs = []
  303. while (numbers.length) segs.push(numbers.splice(0, 3).join(''))
  304. return segs.join(',').split('').reverse().join('')
  305. },
  306. // 获取用户总数
  307. getUser () {
  308. getUserTotal({}).then(res => {
  309. const data = res.data || 0
  310. this.userTotal = data
  311. })
  312. },
  313. // 获取设备总数
  314. getDevice () {
  315. getDeviceTotal({}).then(res => {
  316. const data = res.data || 0
  317. this.devTotal = data
  318. })
  319. },
  320. // 获取试点单位数(网点数量)
  321. getDwTotal () {
  322. getDwTotal({}).then(res => {
  323. const data = res.data.count || 0
  324. this.dwTotal = data
  325. })
  326. },
  327. // 获取新用户注册量
  328. getNewRegister () {
  329. const params = {
  330. beginRegisterTime: this.beginDate,
  331. endRegisterTime: this.endDate,
  332. 'provinceCode': this.queryParam.provinceCode,
  333. 'cityCode': this.queryParam.cityCode,
  334. 'districtCode': this.queryParam.districtCode
  335. }
  336. getNewRegister(params).then(res => {
  337. if (res.status == 200) {
  338. const xData = res.data.dateTime
  339. const yData = res.data.registerNum
  340. const arr = []
  341. yData.map(item => {
  342. arr.push(Number(item))
  343. })
  344. this.initChart1(xData, arr)
  345. }
  346. })
  347. },
  348. // 获取分时投递
  349. getTimeSharingLog () {
  350. const params = {
  351. 'beginDeliveryDate': this.beginDate,
  352. 'endDeliveryDate': this.endDate,
  353. 'provinceCode': this.queryParam.provinceCode,
  354. 'cityCode': this.queryParam.cityCode,
  355. 'districtCode': this.queryParam.districtCode
  356. }
  357. getTimeSharingLog(params).then(res => {
  358. console.log(res)
  359. if (res.status == 200) {
  360. this.initChart2(res.data)
  361. }
  362. })
  363. },
  364. // 排行榜
  365. getDeliveryTop () {
  366. const params = {
  367. 'findRubbishDataBeginDate': this.beginDate,
  368. 'findRubbishDataEndDate': this.endDate,
  369. 'provinceCode': this.queryParam.provinceCode,
  370. 'cityCode': this.queryParam.cityCode,
  371. 'districtCode': this.queryParam.districtCode
  372. }
  373. getDeliveryTop(params).then(res => {
  374. console.log(res)
  375. if (res.status == 200) {
  376. this.initChart3(res.data)
  377. }
  378. })
  379. },
  380. // 设备分布比例
  381. getDevicePercent () {
  382. devicePercent({}).then(res => {
  383. console.log(res, '------------设备分布比例')
  384. const data = res.data || []
  385. data.forEach(item => {
  386. item.name = item.LABEL_NAME
  387. item.value = item.DEVCIE_NUM
  388. })
  389. const con3 = document.getElementById('con3')
  390. const chart3 = echarts.init(con3)
  391. const option3 = this.initPie(chart3, '设备分布比例', data, '个')
  392. chart3.setOption(option3)
  393. this.chart3 = chart3
  394. this.chart3.resize()
  395. })
  396. },
  397. // 各机构投递量分布比例
  398. getLabelWeightPercent () {
  399. labelWeightPercent({}).then(res => {
  400. console.log(res, '-------各机构投递量分布比例')
  401. if (res.status == 200) {
  402. const data = res.data || []
  403. data.forEach(item => {
  404. item.name = item.labelName
  405. item.value = Math.round(item.weight / 1000000)
  406. })
  407. const con6 = document.getElementById('con6')
  408. const chart6 = echarts.init(con6)
  409. const option6 = this.initPie(chart6, '各机构投递量分布比例', data, '吨')
  410. chart6.setOption(option6)
  411. this.chart6 = chart6
  412. this.chart6.resize()
  413. }
  414. })
  415. },
  416. // 垃圾产生量
  417. getRubbishWeight () {
  418. querySumWeight({}).then(res => {
  419. console.log(res, '垃圾产生量')
  420. if (res.status == 200) {
  421. Object.keys(this.rubbishWeightData).map(item => {
  422. this.rubbishWeightData[item] = this.formatter(Math.round((res.data.list.find(key => key.rubbishType == item).rubbishWeight) / 1000))
  423. })
  424. this.rubbishWeightTotal = this.formatter(Math.round(res.data.total / 1000))
  425. } else {
  426. this.rubbishWeightTotal = 0
  427. this.rubbishWeightData = {
  428. 'GATHER_OTHER': 0, // 其它垃圾
  429. 'GATHER_KITCHEN': 0, // 厨余垃圾
  430. 'GATHER_BUILDING': 0, // 建筑垃圾
  431. 'HARM': 0, // 有害垃圾
  432. 'RECYCLING': 0 // 可回收垃圾
  433. }
  434. }
  435. })
  436. },
  437. // 各分类垃圾量分布
  438. getRubbishTypeChart () {
  439. getRubbishTypeTotal({}).then(res => {
  440. console.log(res)
  441. let data = []
  442. if (res.status == 200 && res.data) {
  443. // this.initChart3(res.data)
  444. Object.keys(this.rubbishWeightData).map(item => {
  445. const p = res.data.find(key => key.rubbishType == item)
  446. if (p) {
  447. data.push({
  448. name: p.rubbishTypeDict,
  449. value: p.rubbishWeight
  450. })
  451. }
  452. })
  453. } else {
  454. data = [{
  455. name: '可回收垃圾',
  456. value: 0
  457. },
  458. {
  459. name: '其他垃圾',
  460. value: 0
  461. },
  462. {
  463. name: '厨余垃圾',
  464. value: 0
  465. },
  466. {
  467. name: '建筑垃圾',
  468. value: 0
  469. },
  470. {
  471. name: '有害垃圾',
  472. value: 0
  473. }
  474. ]
  475. }
  476. const con5 = document.getElementById('con5')
  477. const chart5 = echarts.init(con5)
  478. const option = this.initPie(chart5, '各分类垃圾量分布', data)
  479. chart5.setOption(option)
  480. this.chart5 = chart5
  481. this.chart5.resize()
  482. })
  483. },
  484. getLocationCode () {
  485. const cityCode = this.queryParam.cityCode
  486. const districtCode = this.queryParam.districtCode
  487. getLocationCode({
  488. keyword: districtCode || cityCode
  489. }).then(res => {
  490. console.log(res)
  491. if (res.status == 200) {
  492. if (this.map) {
  493. this.map.panTo(new TMap.LatLng(res.data.lat, res.data.lng))
  494. } else {
  495. this.initMap(res.data)
  496. }
  497. }
  498. })
  499. },
  500. // 初始化地图
  501. initMap (res) {
  502. // 定义地图中心点坐标 默认定位在陕西省咸阳市
  503. var center = new TMap.LatLng(res.lat, res.lng)
  504. // 定义map变量,调用 TMap.Map() 构造函数创建地图
  505. this.map = new TMap.Map(document.getElementById('map'), {
  506. center: center, // 设置地图中心点坐标
  507. mapStyleId: 'style3',
  508. zoom: 13, // 设置地图缩放级别
  509. pitch: 0, // 设置俯仰角
  510. showControl: false,
  511. rotation: 45 // 设置地图旋转角度
  512. })
  513. // 创建并初始化MultiMarker 点标记
  514. this.markerLayer = new TMap.MultiMarker({
  515. map: this.map, // 指定地图容器
  516. // 样式定义
  517. styles: {
  518. // 创建一个styleId为"myStyle"的样式(styles的子属性名即为styleId)
  519. 'myStyle': new TMap.MarkerStyle({
  520. 'width': 40, // 点标记样式宽度(像素)
  521. 'height': 40, // 点标记样式高度(像素)
  522. 'src': '../ldt.png', // 图片路径
  523. // 焦点在图片中的像素位置,一般大头针类似形式的图片以针尖位置做为焦点,圆形点以圆心位置为焦点
  524. 'anchor': {
  525. x: 8,
  526. y: 15
  527. }
  528. })
  529. },
  530. // 点标记数据数组
  531. geometries: []
  532. })
  533. // 初始化infoWindow
  534. this.infoWindow = new TMap.InfoWindow({
  535. map: this.map,
  536. position: new TMap.LatLng(39.984104, 116.307503),
  537. offset: {
  538. x: 0,
  539. y: -32
  540. } // 设置信息窗相对position偏移像素
  541. })
  542. this.infoWindow.close() // 初始关闭信息窗关闭
  543. this.markerLayer.on('mousemove', this.showMarkTitle)
  544. // 监听地图加载完成
  545. // this.map.on('tilesloaded', this.getMapMark)
  546. },
  547. // 获取热力图
  548. getHeatMapData () {
  549. // 初始化热力图并添加至map图层
  550. const heat = new TMap.visualization.Heat({
  551. max: 180, // 热力最强阈值
  552. min: 0, // 热力最弱阈值
  553. height: 40, // 峰值高度
  554. gradientColor: { // 渐变颜色
  555. 0.2: '#0a8b4d',
  556. 0.3: '#57e0a5',
  557. 0.5: '#05a8a4'
  558. },
  559. radius: 30 // 最大辐射半径
  560. }).addTo(this.map)
  561. const params = {
  562. 'beginDeliveryDate': this.beginDate,
  563. 'endDeliveryDate': this.endDate,
  564. 'provinceCode': this.queryParam.provinceCode,
  565. 'cityCode': this.queryParam.cityCode,
  566. 'districtCode': this.queryParam.districtCode
  567. }
  568. getHeatMapData(params).then(res => {
  569. if (res.status == 200) {
  570. const ret = []
  571. for (let i = 0; i < res.data.length; i++) {
  572. if (res.data[i].lat <= 90) {
  573. ret.push({
  574. count: res.data[i].deliveryTimes,
  575. lat: res.data[i].lat,
  576. lng: res.data[i].lng
  577. })
  578. }
  579. }
  580. // console.log(ret)
  581. heat.setData(ret) // 设置数据
  582. }
  583. })
  584. },
  585. // 获取地图点坐标
  586. getMapMark () {
  587. this.getHeatMapData()
  588. getMapStation({
  589. 'provinceCode': this.queryParam.provinceCode,
  590. 'cityCode': this.queryParam.cityCode,
  591. 'districtCode': this.queryParam.districtCode
  592. }).then(res => {
  593. const list = res.data || []
  594. const data = []
  595. list.map((item, index) => {
  596. if (item.lat <= 85.051128 && item.lat >= -85.051128) {
  597. const p = {
  598. 'id': item.id, // 点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
  599. 'styleId': 'myStyle', // 指定样式id
  600. 'position': new TMap.LatLng(Number(item.lat), Number(item
  601. .lng)), // 点标记坐标位置
  602. 'properties': { // 自定义属性
  603. 'title': item.name
  604. }
  605. }
  606. data.push(p)
  607. }
  608. })
  609. // 增加点标记
  610. this.markerLayer.add(data)
  611. })
  612. },
  613. // 显示地图标记点名称
  614. showMarkTitle (evt) {
  615. this.infoWindow.open() // 打开信息窗
  616. this.infoWindow.setPosition(evt.geometry.position) // 设置信息窗位置
  617. this.infoWindow.setContent(evt.geometry.properties.title) // 设置信息窗内容
  618. },
  619. // 初始化图表
  620. initChart () {
  621. // 用户总数
  622. this.getUser()
  623. // 设备总数
  624. this.getDevice()
  625. // 网点总数
  626. this.getDwTotal()
  627. // 新注册用户
  628. this.getNewRegister()
  629. // 分时投递
  630. this.getTimeSharingLog()
  631. // 垃圾产生量
  632. this.getRubbishWeight()
  633. // 各分类垃圾量分布
  634. this.getRubbishTypeChart()
  635. // 设备分布比例
  636. this.getDevicePercent()
  637. // 各机构投递量分布比例
  638. this.getLabelWeightPercent()
  639. // 网点投递量排名
  640. this.getDeliveryTop()
  641. },
  642. // 排行榜
  643. initChart3 (res) {
  644. const con4 = document.getElementById('con4')
  645. const chart4 = echarts.init(con4)
  646. const option4 = {
  647. title: {
  648. text: '网点投递量排名',
  649. top: 20,
  650. left: 20,
  651. textStyle: {
  652. color: '#abd7ff'
  653. },
  654. textAlingn: 'left'
  655. },
  656. tooltip: {
  657. formatter: '{b0}: {c0}kg'
  658. },
  659. grid: {
  660. left: 15,
  661. right: 15,
  662. bottom: 20,
  663. top: 85,
  664. containLabel: true
  665. },
  666. xAxis: {
  667. data: res.stationName,
  668. show: false
  669. },
  670. yAxis: {
  671. name: 'kg',
  672. type: 'value'
  673. },
  674. series: [{
  675. data: res.deliveryWeight,
  676. type: 'bar',
  677. barWidth: 30,
  678. label: {
  679. normal: {
  680. show: true,
  681. position: 'top'
  682. }
  683. },
  684. itemStyle: {
  685. color: '#37a2da',
  686. shadowColor: '#246d91',
  687. shadowOffsetX: 8,
  688. shadowOffsetY: 0
  689. }
  690. }]
  691. }
  692. chart4.setOption(option4)
  693. this.chart4 = chart4
  694. this.chart4.resize()
  695. },
  696. // 分时投递记录
  697. initChart2 (res) {
  698. const con2 = document.getElementById('con2')
  699. const chart2 = echarts.init(con2)
  700. const series = []
  701. const arr = res.dayKey.slice(res.dayKey.length - 3)
  702. console.log(arr)
  703. for (let i = 0; i < arr.length; i++) {
  704. series.push({
  705. name: arr[i],
  706. data: res.value[arr[i]],
  707. type: 'line',
  708. stack: '投递量',
  709. smooth: true,
  710. barWidth: 10,
  711. label: {
  712. normal: {
  713. show: true,
  714. position: 'top'
  715. }
  716. }
  717. })
  718. }
  719. const option2 = {
  720. title: {
  721. text: '分时投递量',
  722. top: 20,
  723. left: 20,
  724. textStyle: {
  725. color: '#abd7ff'
  726. },
  727. textAlingn: 'left'
  728. },
  729. tooltip: {
  730. formatter: '{b0}时: {c0}kg'
  731. },
  732. grid: {
  733. left: 20,
  734. right: 40,
  735. bottom: 20,
  736. top: 85,
  737. containLabel: true
  738. },
  739. legend: {
  740. data: arr,
  741. orient: 'vertical',
  742. textStyle: {
  743. fontSize: 10,
  744. color: '#abd7ff'
  745. },
  746. top: 15,
  747. left: 'right'
  748. },
  749. xAxis: {
  750. name: '时',
  751. type: 'category',
  752. data: res.hourKey,
  753. nameTextStyle: {
  754. color: '#666'
  755. },
  756. axisLine: {
  757. lineStyle: {
  758. color: '#666'
  759. }
  760. }
  761. },
  762. yAxis: {
  763. name: 'kg',
  764. type: 'value',
  765. nameTextStyle: {
  766. color: '#666'
  767. },
  768. axisLine: {
  769. lineStyle: {
  770. color: '#666'
  771. }
  772. }
  773. },
  774. series: series
  775. }
  776. chart2.setOption(option2)
  777. this.chart2 = chart2
  778. this.chart2.resize()
  779. },
  780. // 初始化新用户注册量
  781. initChart1 (xData, yData) {
  782. const con1 = document.getElementById('con1')
  783. const chart1 = echarts.init(con1)
  784. const option1 = {
  785. title: {
  786. text: '新用户注册量',
  787. top: 20,
  788. left: 20,
  789. textStyle: {
  790. color: '#abd7ff'
  791. },
  792. textAlingn: 'left'
  793. },
  794. tooltip: {
  795. formatter: '{b0}日: {c0}人'
  796. },
  797. grid: {
  798. left: 15,
  799. right: 60,
  800. bottom: 20,
  801. top: 85,
  802. containLabel: true
  803. },
  804. xAxis: {
  805. name: '日期',
  806. data: xData,
  807. type: 'category',
  808. nameTextStyle: {
  809. color: '#666'
  810. },
  811. axisLine: {
  812. lineStyle: {
  813. color: '#666'
  814. }
  815. }
  816. },
  817. yAxis: {
  818. name: '用户',
  819. type: 'value',
  820. nameTextStyle: {
  821. color: '#666'
  822. },
  823. axisLine: {
  824. lineStyle: {
  825. color: '#666'
  826. }
  827. }
  828. },
  829. series: [{
  830. data: yData,
  831. type: 'line',
  832. smooth: true,
  833. label: {
  834. normal: {
  835. show: true,
  836. position: 'top'
  837. }
  838. },
  839. lineStyle: {
  840. color: 'rgba(55, 162, 218, 0.9)'
  841. },
  842. areaStyle: {
  843. color: {
  844. type: 'linear',
  845. x: 0,
  846. y: 0,
  847. x2: 0,
  848. y2: 1,
  849. colorStops: [{
  850. offset: 0,
  851. color: 'rgba(55, 162, 218, 0.5)' // 0% 处的颜色
  852. }, {
  853. offset: 1,
  854. color: 'rgba(55, 162, 218, 0.9)' // 100% 处的颜色
  855. }]
  856. }
  857. }
  858. }]
  859. }
  860. chart1.setOption(option1)
  861. this.chart1 = chart1
  862. this.chart1.resize()
  863. window.addEventListener('pageshow', this.chart1.resize())
  864. on(window, 'pageshow', this.chart1.resize())
  865. },
  866. // 初始化饼图 title: 标题 data:数据 bit:单位
  867. initPie (chart, title, data, bit) {
  868. const legend = []
  869. if (bit) {
  870. data.map(item => {
  871. const p = `${item.name}: ${item.value}${bit}`
  872. legend.push(p)
  873. })
  874. }
  875. const option = {
  876. color: ['#f56548', '#ffb301', '#7561af', '#06beff', '#20ce7a' ],
  877. title: {
  878. text: title,
  879. top: 20,
  880. left: 20,
  881. textStyle: {
  882. color: '#abd7ff'
  883. },
  884. textAlingn: 'left'
  885. },
  886. tooltip: {
  887. trigger: 'item',
  888. formatter: `{b} : {d}%`
  889. },
  890. legend: {
  891. orient: 'horizontal',
  892. left: 'center',
  893. bottom: '5',
  894. padding: 5,
  895. textStyle: {
  896. color: '#abd7ff',
  897. fontSize: 10
  898. },
  899. show: !!bit,
  900. formatter: function (name) {
  901. if (bit) {
  902. const p = data.find(item => item.name == name)
  903. return name + (p ? (':' + p.value + bit) : '')
  904. }
  905. }
  906. },
  907. series: [{
  908. type: 'pie',
  909. radius: ['30%', '50%'],
  910. startAngle: 75,
  911. top: 50,
  912. avoidLabelOverlap: true, // 在标签拥挤重叠的情况下会挪动各个标签的位置,防止标签间的重叠
  913. label: {
  914. normal: {
  915. formatter: params => {
  916. // console.log(params, 'ppppppp')
  917. return (
  918. '{name|' + params.name + '}{value|' +
  919. params.percent + '%' + '}'
  920. )
  921. },
  922. padding: [0, -70, 25, -70],
  923. rich: {
  924. name: {
  925. fontSize: 12,
  926. padding: [0, 4, 0, 4],
  927. color: '#999'
  928. },
  929. value: {
  930. fontSize: 12,
  931. color: '#999'
  932. }
  933. }
  934. }
  935. },
  936. labelLine: {
  937. normal: {
  938. length: 20,
  939. length2: 70,
  940. lineStyle: {
  941. color: '#e6e6e6'
  942. }
  943. }
  944. },
  945. data: data,
  946. insideLabel: {
  947. show: true
  948. }
  949. }]
  950. }
  951. return option
  952. }
  953. },
  954. watch: {
  955. },
  956. mounted () {
  957. const that = this
  958. // 默认定位在陕西省咸阳市
  959. this.initMap({ lat: 34.32932, lng: 108.70929 })
  960. window.onresize = () => {
  961. return (() => {
  962. that.chart1.resize()
  963. that.chart2.resize()
  964. that.chart3.resize()
  965. that.chart4.resize()
  966. that.chart5.resize()
  967. that.chart6.resize()
  968. })()
  969. }
  970. // 监听页面刷新,重置边框宽高
  971. window.addEventListener('pageshow', (e) => {
  972. // console.log(e, this.chart1, 'eeeeeeeeeeee')
  973. this.$refs.map.initWH()
  974. this.$refs.con1.initWH()
  975. this.$refs.con2.initWH()
  976. this.$refs.con3.initWH()
  977. this.$refs.con4.initWH()
  978. this.$refs.con5.initWH()
  979. this.$refs.con6.initWH()
  980. })
  981. },
  982. beforeRouteEnter (to, from, next) {
  983. next(vm => {
  984. vm.getMapMark()
  985. setTimeout(() => {
  986. vm.initChart()
  987. if (vm.queryParam.cityCode != '') {
  988. vm.getAreaListRequest(vm.queryParam.cityCode)
  989. }
  990. }, 150)
  991. })
  992. },
  993. beforeRouterLeave (to, from, next) {
  994. next(vm => {
  995. // 销毁地图
  996. vm.map.destroy()
  997. vm.map = null
  998. })
  999. }
  1000. }
  1001. </script>
  1002. <style lang="less">
  1003. .dataView-content {
  1004. width: 100%;
  1005. height: 100%;
  1006. min-height: 600px;
  1007. background-image: url(../../assets/dataViewBg.png);
  1008. background-size: 100% 100%;
  1009. display: flex;
  1010. flex-direction: column;
  1011. .data-header {
  1012. display: flex;
  1013. align-items: center;
  1014. justify-content: space-between;
  1015. background-image: url(../../assets/headBg.png);
  1016. background-repeat: no-repeat;
  1017. background-position: center center;
  1018. background-size: auto 80%;
  1019. padding: 10px 0 0;
  1020. .total-block {
  1021. width: 35%;
  1022. display: flex;
  1023. align-items: center;
  1024. justify-content: center;
  1025. >div {
  1026. width: 30%;
  1027. padding-right: 10px;
  1028. }
  1029. .total-label {
  1030. color: #fff;
  1031. text-align: left;
  1032. display: flex;
  1033. i {
  1034. transform: rotate(330deg);
  1035. display: inline-block;
  1036. font-size: 12px;
  1037. margin: 0 1px;
  1038. &:last-child {
  1039. margin-right: 10px;
  1040. }
  1041. }
  1042. }
  1043. .total-value {
  1044. font-size: 22px;
  1045. font-weight: bold;
  1046. }
  1047. .cor1 {
  1048. color: #00ff84;
  1049. }
  1050. .cor2 {
  1051. color: #d7ff00;
  1052. }
  1053. .cor3 {
  1054. color: #00c0ff;
  1055. }
  1056. }
  1057. .page-title {
  1058. width: 50%;
  1059. flex-grow: 1;
  1060. color: #00aaff;
  1061. font-size: 32px;
  1062. text-align: center;
  1063. }
  1064. >div {
  1065. padding: 15px;
  1066. &:last-child {
  1067. width: 25%;
  1068. color: #0ed3ff;
  1069. .border-box-content {
  1070. font-size: 18px;
  1071. text-align: center;
  1072. display: flex;
  1073. align-items: center;
  1074. justify-content: center;
  1075. padding-left: 50px;
  1076. select {
  1077. background: #021931;
  1078. border: 1px solid #3e566d;
  1079. min-width: 30%;
  1080. padding: 2px 20px;
  1081. margin: 0 10px;
  1082. box-shadow: inset 0 0 2px #69b2ff;
  1083. border-radius: 60px;
  1084. }
  1085. }
  1086. }
  1087. }
  1088. }
  1089. .data-body {
  1090. flex-grow: 1;
  1091. display: flex;
  1092. padding: 0 15px 15px;
  1093. .b-right {
  1094. width: 25%;
  1095. display: flex;
  1096. padding: 5px;
  1097. flex-direction: column;
  1098. justify-content: space-around;
  1099. >div {
  1100. height: 33%;
  1101. }
  1102. }
  1103. .b-middle {
  1104. width: 75%;
  1105. padding: 5px;
  1106. display: flex;
  1107. flex-direction: column;
  1108. justify-content: space-around;
  1109. >div {
  1110. &:first-child {
  1111. height: 66%;
  1112. .lajiliang {
  1113. width: 23%;
  1114. position: absolute;
  1115. padding: 15px;
  1116. background: rgba(255, 255, 255, 0.3);
  1117. border-radius: 6px;
  1118. left: 20px;
  1119. top: 20px;
  1120. z-index: 1000;
  1121. color: #fff;
  1122. .laji-title {
  1123. text-align: center;
  1124. padding: 0 0 10px;
  1125. }
  1126. .laji-item {
  1127. display: flex;
  1128. align-items: center;
  1129. justify-content: space-between;
  1130. margin: 15px 0;
  1131. >div {
  1132. &:first-child {
  1133. border-radius: 30px;
  1134. padding: 2px 10px;
  1135. font-size: 12px;
  1136. width: 50%;
  1137. text-align: center;
  1138. }
  1139. }
  1140. .cor1 {
  1141. background-color: #c2523f;
  1142. }
  1143. .cor2 {
  1144. background-color: #c59b16;
  1145. }
  1146. .cor3 {
  1147. background-color: #7561af;
  1148. }
  1149. .cor4 {
  1150. background-color: #418ec6;
  1151. }
  1152. .cor5 {
  1153. background-color: #20ce7a;
  1154. }
  1155. }
  1156. }
  1157. }
  1158. &:last-child {
  1159. height: 33%;
  1160. display: flex;
  1161. >div {
  1162. width: 33.3%;
  1163. justify-content: space-around;
  1164. align-items: center;
  1165. }
  1166. }
  1167. }
  1168. }
  1169. }
  1170. }
  1171. </style>