trail.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. <template>
  2. <div class="battle-warp">
  3. <div class="map-card-wrap map">
  4. <div class="map-card-wrap__info map">
  5. <div class="item-header" style="padding: 3px 15px;border-color: #dddddd;">
  6. <div class="text-bold">{{ queryTruckInfo.carNumber }}<span class="text-normal">({{ queryTruckInfo.linked === 1 ? '其他' : '自营' }})</span></div>
  7. <div><span class="color-blue">{{ truckInfo.uploadTime || '-' }}</span></div>
  8. </div>
  9. <div class="label item-info__user" style="padding-left: 0;margin: 10px 15px;padding-bottom: 10px;border-bottom: 1px solid #f3f4f5;display: flex;justify-content: space-between;align-items: center;" v-if="truckInfo.hasOwnProperty('truckDriverList') && truckInfo.truckDriverList.length > 0">
  10. <div class="driver-wrap" style="width: 85%;">
  11. <div v-for="(driver, driverIndex) in truckInfo.truckDriverList" :key="driverIndex" class="driver-list">{{ driver.driverName }}</div>
  12. </div>
  13. <div><van-icon :name="showStatus ? 'arrow-down' : 'arrow-up'" @click="showStatus = !showStatus" /></div>
  14. </div>
  15. <van-row v-if="showStatus" class="map-card-wrap__info-box" :gutter="3" type="flex" justify="space-around">
  16. <van-col :span="6" class="item" v-for="(item, index) of cardList" :key="index">
  17. <div class="name">{{ item.name }}</div>
  18. <div class="value">{{ item.value }} <span class="unit">{{ item.unit }}</span></div>
  19. </van-col>
  20. </van-row>
  21. <template v-else>
  22. <div class="list-wrap__item truck">
  23. <div class="map-card-wrap__info-box">
  24. <div class="item">
  25. <div class="name">累计里程</div>
  26. <div class="value">{{ cumulative.mileage.toFixed(2) }} <span class="unit">公里</span></div>
  27. </div>
  28. </div>
  29. <div class="item-info">
  30. <div class="label speed">
  31. <span>{{ cumulative.speed || '-' }}</span>公里/小时
  32. <span class="status" :class="'status__' + cumulative.speedStatus">{{ truckStatusList[cumulative.speedStatus] }}</span>
  33. </div>
  34. <div class="label local">{{ truckInfo.currAddress || '-' }}</div>
  35. </div>
  36. </div>
  37. <div class="list-wrap__item truck">
  38. <div class="map-card-wrap__info-box">
  39. <div class="item">
  40. <div class="name">累计耗能</div>
  41. <div class="value">{{ cumulative.consumption }} <span class="unit">公斤</span></div>
  42. </div>
  43. </div>
  44. <div class="volume" :class="`percent_${ cumulativeStatus(cumulative.filterPercent) }`">剩余气量:{{ cumulative.filterPercent > 0 ? `${cumulative.filterPercent}%` : '无' }}</div>
  45. <div class="map-card-wrap__info-box">
  46. <div class="item">
  47. <div class="name">累计减碳</div>
  48. <div class="value">{{ cumulative.carbon }} <span class="unit">公斤</span></div>
  49. </div>
  50. </div>
  51. </div>
  52. </template>
  53. </div>
  54. </div>
  55. <div class="footer-trail-wrap">
  56. <div>回放时段</div>
  57. <div class="back-time-list">
  58. <van-tag :color="timeStatus === 9 ? '#2979ff' : '#ffffff'" :text-color="timeStatus === 9 ? '#ffffff' : '#868b9a'" size="large" @click="timeEvent(9)">自定义</van-tag>
  59. <van-tag :color="timeStatus === 1 ? '#2979ff' : '#ffffff'" :text-color="timeStatus === 1 ? '#ffffff' : '#868b9a'" size="large" @click="timeEvent(1)">近1天</van-tag>
  60. <van-tag :color="timeStatus === 2 ? '#2979ff' : '#ffffff'" :text-color="timeStatus === 2 ? '#ffffff' : '#868b9a'" size="large" @click="timeEvent(2)">近3天</van-tag>
  61. <van-tag :color="timeStatus === 3 ? '#2979ff' : '#ffffff'" :text-color="timeStatus === 3 ? '#ffffff' : '#868b9a'" size="large" @click="timeEvent(3)">近7天</van-tag>
  62. </div>
  63. <div class="back-info-wrap">
  64. <div class="data-info">
  65. <div>总里程 {{ truckTrialInfo.mileage }}公里</div>
  66. <div>总能耗 {{ truckTrialInfo.consumption }}公斤</div>
  67. <div>总减碳 {{ truckTrialInfo.carbon }}公斤</div>
  68. </div>
  69. <div style="width: 100%;padding: 30px 0 10px;">
  70. <van-slider v-model="slider.value" :min="slider.min" :max="slider.max" bar-height="4px" disabled >
  71. <template #button>
  72. <div class="slider-custom-button"></div>
  73. </template>
  74. </van-slider>
  75. </div>
  76. <div class="back-time">
  77. <div :class="timeStatus === 9 ? 'edit' : ''" @click="calendarTimeEvent()">{{ datatime.startTime }}</div>
  78. <div @click="playTrailEvent()"><van-image width="28px" height="28px" fit="contain" :src="requestImages()"/></div>
  79. <div :class="timeStatus === 9 ? 'edit' : ''" @click="calendarTimeEvent()">{{ datatime.endTime }}</div>
  80. </div>
  81. </div>
  82. </div>
  83. <calendar-time ref="calendar" @confirm="calendarTime"></calendar-time>
  84. <el-bmap vid="bmap" :min-zoom="8" :max-zoom="20" :zoom="zoom" :center="center" :bmap-manager="bmapManager" class="bm-view" :style="mapStyle" :events="events"></el-bmap>
  85. </div>
  86. </template>
  87. <script>
  88. import 'vue-bmap-gl/dist/style.css'
  89. import axios from 'axios'
  90. import { BMapManager } from 'vue-bmap-gl'
  91. import { $gasdataTruckInfo, $gasdataTruckTrajectory } from '@/service/gasdata'
  92. import { formatDate } from '@/utils/tools'
  93. import { CalendarTime } from '@/components'
  94. // import { transformFromWGSToGCJ, transformFromGCJToBaidu } from '@/utils/wscoordinate'
  95. export default {
  96. name: 'battle',
  97. components: { CalendarTime },
  98. data() {
  99. return {
  100. backValue: 0,
  101. timeStatus: 1,
  102. showStatus: true,
  103. playStatus: 1,
  104. slider: {
  105. status: true,
  106. value: 0,
  107. min: 0,
  108. max: 100
  109. },
  110. cumulative: {
  111. mileage: 0,
  112. speed: 0,
  113. carbon: 0,
  114. consumption: 0,
  115. speedStatus: '',
  116. filterPercent: 0
  117. },
  118. datatime: {
  119. startTime: formatDate((new Date().getTime() - 86400000), 'yyyy-MM-dd hh:mm:ss'),
  120. endTime: formatDate(new Date().getTime(), 'yyyy-MM-dd hh:mm:ss')
  121. },
  122. truckInfo: {},
  123. truckTrialInfo: {},
  124. queryTruckInfo: this.$route.query,
  125. bmapManager: new BMapManager(),
  126. map: null,
  127. mapStyle: {
  128. width: '100%',
  129. height: '100%'
  130. },
  131. center: [this.$route.query.lng, this.$route.query.lat],
  132. zoom: 10,
  133. events: {
  134. init: (map) => {
  135. this.map = map
  136. this.initTrailData()
  137. // this.startDemo(o)
  138. }
  139. },
  140. timer: null,
  141. mapHeight: 400,
  142. cardList: [{
  143. name: '累计里程',
  144. value: '0',
  145. unit: '公里'
  146. }, {
  147. name: '累计耗能',
  148. value: '0',
  149. unit: '公斤'
  150. }, {
  151. name: '累计减碳',
  152. value: '0',
  153. unit: '公斤'
  154. }],
  155. truckStatusList: {
  156. 0: '行驶中',
  157. 1: '静止中',
  158. 2: '离线中'
  159. },
  160. lushu: null
  161. }
  162. },
  163. watch: {},
  164. computed: {},
  165. created() {
  166. this.dragendPointer()
  167. // this.truckTrailInfo()
  168. },
  169. mounted() {
  170. // 重置地图高度
  171. this.mapHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
  172. },
  173. beforeDestroy() {},
  174. methods: {
  175. initData() {
  176. let loaded = false
  177. try {
  178. loaded = (BMapGLLib && BMapGLLib.Lushu)
  179. } catch (err) {
  180. loaded = false
  181. }
  182. if (!loaded) {
  183. console.log('BMapGLLib.Lushu loading!')
  184. const lushu = document.createElement('script')
  185. lushu.type = 'text/javascript'
  186. lushu.src = 'https://mapopen.bj.bcebos.com/github/BMapGLLib/Lushu/src/Lushu.min.js'
  187. document.body.appendChild(lushu)
  188. const trackAnimation = document.createElement('script')
  189. trackAnimation.type = 'text/javascript'
  190. trackAnimation.src = 'https://mapopen.bj.bcebos.com/github/BMapGLLib/TrackAnimation/src/TrackAnimation.min.js'
  191. document.body.appendChild(trackAnimation)
  192. } else {
  193. console.log('BMapGLLib.Lushu is loaded!')
  194. }
  195. },
  196. // 剩余气量的状态
  197. cumulativeStatus(value) {
  198. if (value >= 0 && value < 10) {
  199. return 1
  200. } else if (value >= 10 && value < 30) {
  201. return 2
  202. } else if (value >= 30) {
  203. return 3
  204. }
  205. },
  206. calendarTime(times) {
  207. console.log(times)
  208. this.datatime.startTime = times.startTime
  209. this.datatime.endTime = times.endTime
  210. this.initTrailData()
  211. },
  212. calendarTimeEvent() {
  213. if (this.timeStatus === 9) {
  214. this.$refs.calendar.showCalender()
  215. }
  216. },
  217. timeEvent(type) {
  218. this.timeStatus = Number(type)
  219. if (this.timeStatus === 1) {
  220. this.datatime = {
  221. startTime: formatDate((new Date().getTime() - 86400000), 'yyyy-MM-dd hh:mm:ss'),
  222. endTime: formatDate(new Date().getTime(), 'yyyy-MM-dd hh:mm:ss')
  223. }
  224. } if (this.timeStatus === 2) {
  225. this.datatime = {
  226. startTime: formatDate((new Date().getTime() - 3 * 86400000), 'yyyy-MM-dd hh:mm:ss'),
  227. endTime: formatDate(new Date().getTime(), 'yyyy-MM-dd hh:mm:ss')
  228. }
  229. } if (this.timeStatus === 3) {
  230. this.datatime = {
  231. startTime: formatDate((new Date().getTime() - 7 * 86400000), 'yyyy-MM-dd hh:mm:ss'),
  232. endTime: formatDate(new Date().getTime(), 'yyyy-MM-dd hh:mm:ss')
  233. }
  234. }
  235. this.initTrailData()
  236. },
  237. requestImages () {
  238. if (this.playStatus === 1) {
  239. return require('@/assets/images/home/play.png')
  240. } else {
  241. return require('@/assets/images/home/stop.png')
  242. }
  243. },
  244. playTrailEvent() {
  245. if (this.playStatus === 1) {
  246. this.playStatus = 2
  247. this.lushu.start()
  248. if (this.slider.value >= this.slider.max) {
  249. this.slider.value = 0
  250. }
  251. this.timer = setInterval(() => {
  252. this.sliderPlayLushu()
  253. }, 100)
  254. } else {
  255. this.playStatus = 1
  256. this.lushu.pause()
  257. }
  258. },
  259. sliderPlayLushu() {
  260. const index = this.lushu.i + 1
  261. const len = this.lushu.path.length
  262. const max = this.slider.max
  263. let tmpSoliderValue = Number(this.slider.value)
  264. const lushuItem = this.lushu.path[this.lushu.i]
  265. // 累计
  266. this.cardList[0].value = lushuItem.mileage1
  267. this.cardList[1].value = lushuItem.consumption1
  268. this.cardList[2].value = lushuItem.carbon1
  269. this.cumulative = {
  270. mileage: lushuItem.mileage1.toFixed(2),
  271. speed: lushuItem.speed,
  272. carbon: lushuItem.carbon1,
  273. consumption: lushuItem.consumption1,
  274. speedStatus: lushuItem.speed > 0 ? 0 : 1,
  275. filterPercent: lushuItem.literPercent
  276. }
  277. this.center = [lushuItem.lng, lushuItem.lat]
  278. if (len > 0) {
  279. tmpSoliderValue = tmpSoliderValue > max * (index / len) ? tmpSoliderValue : max * (index / len)
  280. tmpSoliderValue += (index / (len * 10))
  281. } else {
  282. tmpSoliderValue += 0
  283. }
  284. if (tmpSoliderValue >= max) {
  285. this.playStatus = 1
  286. clearInterval(this.timer)
  287. }
  288. this.slider.value = tmpSoliderValue >= max ? max : tmpSoliderValue
  289. },
  290. mapLuShuSpeed() {
  291. let speed = 50
  292. const mileage = this.truckTrialInfo.mileage
  293. this.slider.max = mileage * 1000
  294. if (mileage > 100) {
  295. speed = 5000
  296. } else if (mileage > 80 && mileage <= 100) {
  297. speed = 2000
  298. } else if (mileage > 50 && mileage <= 80) {
  299. speed = 1000
  300. } else if (mileage > 20 && mileage <= 50) {
  301. speed = 500
  302. } else if (mileage > 5 && mileage <= 20) {
  303. speed = 100
  304. } else {
  305. speed = 50
  306. }
  307. return speed
  308. },
  309. async initTrailData() {
  310. this.initData()
  311. const truckInfo = await this.truckTrailInfo()
  312. const arrPois = truckInfo.points || []
  313. const len = arrPois.length - 1
  314. // const beginPoint = transformFromWGSToGCJ(arrPois[0].lat, arrPois[0].lng)
  315. // const endPoint = transformFromWGSToGCJ(arrPois[len].lat, arrPois[len].lng)
  316. // const baiduBeginPoint = transformFromGCJToBaidu(beginPoint.latitude, beginPoint.longitude)
  317. // const baiduEndPoint = transformFromGCJToBaidu(endPoint.latitude, endPoint.longitude)
  318. // console.log(baiduBeginPoint, baiduEndPoint)
  319. var start = new BMapGL.Point(arrPois[0].lng, arrPois[0].lat)
  320. var end = new BMapGL.Point(arrPois[len].lng, arrPois[len].lat)
  321. var drv = new BMapGL.DrivingRoute(this.map, {
  322. onSearchComplete: (res) => {
  323. if (drv.getStatus() == BMAP_STATUS_SUCCESS) {
  324. this.map.clearOverlays()
  325. // 增加起点和终点坐标
  326. this.map.addOverlay(new BMapGL.Marker(start, {
  327. offset: new BMapGL.Size(0, -10),
  328. icon: new BMapGL.Icon(require('@/assets/images/home/begin@2x.png'), new BMapGL.Size(20, 24))
  329. }))
  330. this.map.addOverlay(new BMapGL.Marker(end, {
  331. offset: new BMapGL.Size(0, -10),
  332. icon: new BMapGL.Icon(require('@/assets/images/home/end@2x.png'), new BMapGL.Size(20, 24))
  333. }))
  334. this.map.addOverlay(new BMapGL.Polyline(arrPois, { strokeColor: '#43bf91', strokeOpacity: 1 }))
  335. this.map.setViewport(arrPois)
  336. this.lushu = new BMapGLLib.LuShu(this.map, arrPois, {
  337. defaultContent: '', // 覆盖物中的内容 "从天安门到百度大厦"
  338. autoView: true, // 是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整
  339. icon: new BMapGL.Icon(require('@/assets/images/home/red@2x.png'), new BMapGL.Size(15, 15), { anchor: new BMapGL.Size(10, 10) }),
  340. speed: this.mapLuShuSpeed(), // 覆盖物移动速度,单位米/秒
  341. enableRotation: true // 是否设置marker随着道路的走向进行旋转
  342. // landmarkPois: [
  343. // { lng: 116.314782, lat: 39.913508, html: '加油站', pauseTime: 2 },
  344. // { lng: 116.315391, lat: 39.964429, html: '高速公路收费<div><img src="//map.baidu.com/img/logo-map.gif"/></div>', pauseTime: 3 },
  345. // { lng: 116.381476, lat: 39.974073, html: '肯德基早餐', pauseTime: 2 }
  346. // ]
  347. })
  348. }
  349. }
  350. })
  351. drv.search(start, end)
  352. },
  353. async queryCurrAddress(location) {
  354. const data = await axios.post(process.env.VUE_APP_BAIDU_URL + '?output=json&ak=Zvd6FzmertUwjhZih5Zfq0D8uTUhvqsH&coordtype=wgs84ll&location=' + location).then(response => {
  355. return response.data
  356. })
  357. if (data.hasOwnProperty('result')) {
  358. return data.result.addressComponent
  359. } else {
  360. return '-'
  361. }
  362. },
  363. async truckTrailInfo() {
  364. const params = {
  365. carNumber: this.queryTruckInfo.carNumber,
  366. days: (this.timeStatus === 9 ? 0 : this.timeStatus),
  367. startTime: this.datatime.startTime,
  368. endTime: this.datatime.endTime
  369. }
  370. const data = await $gasdataTruckTrajectory(params).then(response => {
  371. return response
  372. })
  373. this.truckTrialInfo = data
  374. return data
  375. },
  376. dragendPointer() {
  377. const params = {
  378. carNumber: this.queryTruckInfo.carNumber
  379. }
  380. this.markers = []
  381. $gasdataTruckInfo(params).then(async response => {
  382. this.truckInfo = response
  383. // 根据金纬度获取地理位置信息
  384. const addressInfo = await this.queryCurrAddress(response.lat + ',' + response.lng)
  385. const currAddress = addressInfo.province + addressInfo.city + addressInfo.district + addressInfo.street
  386. if (response.hasOwnProperty('currAddress')) {
  387. response.currAddress = currAddress
  388. } else {
  389. this.$set(response, 'currAddress', currAddress)
  390. }
  391. })
  392. }
  393. }
  394. }
  395. </script>