index.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <div class="battle-warp">
  3. <div class="map-card-wrap" :class="showType === 1 ? 'map' : ''">
  4. <div class="map-card-wrap__info" :class="showType === 1 ? 'map' : ''">
  5. <van-row class="map-card-wrap__info-box" :gutter="3" type="flex" justify="center">
  6. <van-col :span="6" class="item" v-for="(item, index) of cardList" :key="index">
  7. <div class="name">{{ item.name }}</div>
  8. <div class="value">{{ item.value }} <span class="unit">{{ item.unit }}</span></div>
  9. </van-col>
  10. </van-row>
  11. <div class="map-card-wrap__info-search">
  12. <van-dropdown-menu active-color="#1989fa">
  13. <van-dropdown-item v-model="tradeStatus" :options="tradeStatusList" @change="dropLoad" />
  14. <van-dropdown-item v-model="runStatus" :options="runStatusList" @change="dropLoad" />
  15. </van-dropdown-menu>
  16. <div><van-icon name="search" /></div>
  17. </div>
  18. </div>
  19. </div>
  20. <div class="list-icon" :class="showType === 1 ? 'list' : 'map'" @click="mapToListEvent">
  21. <div style="font-size: 14px;margin-top: 42px;">{{ showType === 1 ? '列表' : '地图' }}</div>
  22. </div>
  23. <el-bmap v-if="nextTickStatus && showType === 1" vid="bmap" :zoom="zoom" :center="center" class="bm-view" :style="mapStyle">
  24. <el-bmap-marker v-for="(marker, index) in markers" :key="index" :icon="marker.icon" :visible="marker.visible" :position="marker.position" :title="marker.title" :label="marker.label" :events="marker.events" :vid="index" :enable-dragging="marker.enableDragging"></el-bmap-marker>
  25. </el-bmap>
  26. <div v-else-if="nextTickStatus && showType === 2" class="list-wrap">
  27. <div class="list-wrap__item" v-for="(item, index) in truckList" :key="index">
  28. <div class="item-header">
  29. <div class="text-bold">{{ item.carNumber }}<span class="text-normal">({{ item.linked === 1 ? '其他' : '自营' }})</span></div>
  30. <div>今日里程<span class="color-blue">{{ item.mileage || '-' }}</span>公里</div>
  31. </div>
  32. <div class="item-info">
  33. <div class="label item-info__user" style="padding-left: 0" v-if="item.truckDriverList.length > 0">
  34. <div class="driver-wrap">
  35. <div v-for="(driver, driverIndex) in item.truckDriverList" :key="driverIndex" class="driver-list">{{ truckToDriverUser(driver) }}</div>
  36. </div>
  37. <div>{{ truckToDriverMobile(item.truckDriverList[0].driverName) }}</div>
  38. </div>
  39. <div class="label speed">
  40. <span>{{ item.speed || '-' }}</span>公里/小时
  41. <span class="status" :class="'status__' + item.speedStatus">{{ truckStatusList[item.speedStatus] }}</span>
  42. </div>
  43. <div class="label local">{{ item.currAddress || '-' }}</div>
  44. </div>
  45. </div>
  46. </div>
  47. </div>
  48. </template>
  49. <script>
  50. import 'vue-bmap-gl/dist/style.css'
  51. import axios from 'axios'
  52. // import { $districtList, $userFindConfigAreaList } from '@/service/user'
  53. import { $gasdataGaugeAll } from '@/service/gasdata'
  54. // import { currency, formateZeroToBar } from '@/utils/filters'
  55. // import { MarkerWindow, AreaDataAnalysis } from './components'
  56. // import { mapJsonData } from '@/mock/map'
  57. export default {
  58. name: 'battle',
  59. // components: { MarkerWindow, AreaDataAnalysis },
  60. data() {
  61. return {
  62. map: null,
  63. showType: 1,
  64. mapStyle: {
  65. width: '100%',
  66. height: '100%'
  67. },
  68. center: [116.23228, 35.7127],
  69. zoom: 8,
  70. heading: 0,
  71. index: 1,
  72. timer: null,
  73. mapHeight: 400,
  74. cardList: [{
  75. name: '在线/总量',
  76. value: '0/0',
  77. unit: '辆'
  78. }, {
  79. name: '今日总里程',
  80. value: '0',
  81. unit: '公里'
  82. }, {
  83. name: '今日总耗能',
  84. value: '0',
  85. unit: '公斤'
  86. }, {
  87. name: '今日总减碳',
  88. value: '0',
  89. unit: '公斤'
  90. }],
  91. tradeStatus: '',
  92. tradeStatusList: [
  93. { text: '全经营类型', value: '' },
  94. { text: '自营', value: 0 },
  95. { text: '外协', value: 1 }
  96. ],
  97. runStatus: '',
  98. runStatusList: [
  99. { text: '全行驶状态', value: '' },
  100. { text: '行驶', value: 0 },
  101. { text: '静止', value: 1 },
  102. { text: '离线', value: 2 }
  103. ],
  104. truckStatusList: {
  105. 0: '行驶中',
  106. 1: '静止中',
  107. 2: '离线中'
  108. },
  109. truckList: [],
  110. markers: [],
  111. nextTickStatus: true
  112. }
  113. },
  114. watch: {},
  115. computed: {},
  116. created() {
  117. this.dragendPointer()
  118. this.timer = setInterval(() => {
  119. this.dragendPointer()
  120. }, 60000)
  121. },
  122. mounted() {
  123. // 重置地图高度
  124. this.mapHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
  125. },
  126. beforeDestroy() {
  127. clearInterval(this.timer)
  128. },
  129. methods: {
  130. async queryCurrAddress(location) {
  131. const data = await axios.post(process.env.VUE_APP_BAIDU_URL + '?output=json&ak=Zvd6FzmertUwjhZih5Zfq0D8uTUhvqsH&coordtype=wgs84ll&location=' + location).then(response => {
  132. return response.data
  133. })
  134. if (data.hasOwnProperty('result')) {
  135. return data.result.addressComponent
  136. } else {
  137. return '-'
  138. }
  139. },
  140. angle(start, end) {
  141. // 通过 a、b 确定角度所处的象限
  142. const a = start[0] - end[0]
  143. const b = start[1] - end[1]
  144. // eslint-disable-next-line camelcase
  145. const a_c = Math.abs(a)
  146. // eslint-disable-next-line camelcase
  147. const b_c = Math.abs(b)
  148. // 获取得三角形的斜边 Math.hypot();
  149. const c = Math.hypot(a_c, b_c)
  150. // 计算弧度
  151. // eslint-disable-next-line camelcase
  152. const radina = Math.acos(a_c / c)
  153. // 计算角度
  154. let angleVal = Math.floor(radina * 180 / Math.PI)
  155. // 处理最终需要旋转的角度
  156. if (a > 0) {
  157. // 第二、三象限
  158. if (b > 0) {
  159. // 三
  160. angleVal = 90 + 90 - angleVal
  161. } else {
  162. angleVal = -180 + angleVal
  163. }
  164. } else {
  165. // 一、四象限
  166. if (b > 0) {
  167. // 四
  168. // eslint-disable-next-line no-self-assign
  169. angleVal = angleVal
  170. } else {
  171. // 一
  172. angleVal = -angleVal
  173. }
  174. }
  175. return angleVal
  176. },
  177. mapToListEvent() {
  178. this.showType = this.showType === 1 ? 2 : 1
  179. },
  180. truckToDriverUser(driver) {
  181. // 解释司机个人信息
  182. const driverUserInfo = driver.driverName ? driver.driverName.split('/') : []
  183. return driverUserInfo.length >= 1 ? driverUserInfo[0] : '-'
  184. },
  185. truckToDriverMobile(info) {
  186. if (info.indexOf('/') !== -1) {
  187. const userinfo = info.split('/')
  188. return userinfo[1] || '-'
  189. } else {
  190. return '-'
  191. }
  192. },
  193. dropLoad() {
  194. this.dragendPointer()
  195. },
  196. dragendPointer() {
  197. const params = {}
  198. this.markers = []
  199. if (this.tradeStatus !== '') {
  200. params.linked = this.tradeStatus
  201. }
  202. if (this.runStatus !== '') {
  203. params.speedStatus = this.runStatus
  204. }
  205. $gasdataGaugeAll(params).then(response => {
  206. const data = response.carMonitorVos
  207. // 统计数据
  208. this.cardList[0].value = response.onLine + '/' + response.total
  209. this.cardList[1].value = response.mileage.toFixed(0)
  210. this.cardList[2].value = response.consumption
  211. this.cardList[3].value = response.carbon
  212. this.truckList = data
  213. data.forEach(async item => {
  214. this.markerInfo(item)
  215. // 根据金纬度获取地理位置信息
  216. const addressInfo = await this.queryCurrAddress(item.lat + ',' + item.lng)
  217. const currAddress = addressInfo.province + addressInfo.city + addressInfo.district + addressInfo.street
  218. if (item.hasOwnProperty('currAddress')) {
  219. item.currAddress = currAddress
  220. } else {
  221. this.$set(item, 'currAddress', currAddress)
  222. }
  223. })
  224. })
  225. },
  226. markerInfo(item) {
  227. const info = {
  228. icon: {},
  229. label: {},
  230. visible: true,
  231. enableDragging: false
  232. }
  233. info.label = {
  234. content: item.carNumber,
  235. offset: [-23, -25],
  236. style: {
  237. borderWidth: 0,
  238. padding: '3px 10px',
  239. borderRadius: '4px',
  240. boxShadow: '0px 0px 9px 1px rgba(28, 29, 33, 0.16)'
  241. }
  242. }
  243. info.icon = {
  244. url: require('@/assets/images/navigation/navigation@2x.png'),
  245. size: [20, 26]
  246. }
  247. info.position = [item.lng, item.lat]
  248. this.markers.push(info)
  249. }
  250. }
  251. }
  252. </script>