王贵旺 4 tahun lalu
induk
melakukan
2f294cb3df

TEMPAT SAMPAH
src/assets/images/home/list-checkbox@2x.png


TEMPAT SAMPAH
src/assets/images/home/local@2x.png


TEMPAT SAMPAH
src/assets/images/home/map-draw@2x.png


TEMPAT SAMPAH
src/assets/images/home/speed@2x.png


TEMPAT SAMPAH
src/assets/images/home/user@2x.png


TEMPAT SAMPAH
src/assets/images/navigation/navigation@2x.png


+ 486 - 0
src/assets/index.scss

@@ -0,0 +1,486 @@
+.text-bold {
+  font-weight: bold;
+}
+.text-normal {
+  font-weight: normal;
+}
+.color-blue {
+  color: #2979ff;
+}
+.battle-warp {
+  height: 100%;
+  .van-checkbox {
+    position: absolute;
+    top: 50px;
+    right: 5px;
+    font-size: 14px;
+    background-color: #fff;
+    z-index: 1000;
+    padding: 8px 15px;
+    border-radius: 4px;
+    color: #333333;
+    font-weight: bold;
+    box-shadow: 0px 0px 18px 0px rgba(0, 0, 0, 0.13);
+  }
+  .van-tabbar {
+    z-index: 10;
+    .van-tabbar-item {
+      display: flex;
+      flex-direction: row;
+      color: #333333;
+      font-size: 14px;
+      font-weight: bold;
+      .van-tabbar-item__icon {
+        margin-bottom: 0;
+      }
+      .van-tabbar-item__text {
+        padding-left: 5px;
+      }
+      &.van-tabbar-item--active {
+        color: #ffffff;
+        background-color: #2765E2;
+      }
+    }
+  }
+  .map-search {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    z-index: 10;
+    display: flex;
+    .search-bar {
+      flex: 9;
+      display: flex;
+      justify-content: flex-start;
+      background-color: #ffffff;
+      img {
+        height: 32px;
+        width: 32px;
+        padding: 5px;
+      }
+      .van-dropdown-menu {
+        flex: 3;
+      }
+    }
+    .search-icon {
+      flex: 1;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      background-color: #ffffff;
+    }
+  }
+  .bmap-info-window-hide {
+    visibility: hidden;
+  }
+  .bmap-info-window-custom {
+    .van-popup-gas-info {
+      padding: 10px;
+    }
+    .bm-bottom {
+      padding: 5px 0 10px;
+      text-align: right;
+      margin-bottom: 10px;
+      border-bottom: 1px solid #ededed;
+    }
+    .bm-header {
+      display: flex;
+      text-align: left;
+      align-items: center;
+      justify-content: flex-start;
+      & > div:last-child {
+        flex: 1;
+        padding-left: 5px;
+      }
+      .title {
+        display: flex;
+        align-items: center;
+        justify-content: flex-start;
+        .item-tag {
+          font-size: 14px;
+          color: #666666;
+          white-space: nowrap;
+        }
+        .item-name {
+          max-width: 180px;
+          color: #333333;
+          font-size: 16px;
+          font-weight: bold;
+        }
+      }
+      .address {
+        color: #999999;
+        font-size: 12px;
+        padding-top: 5px;
+      }
+    }
+    .bm-content {
+      &__price {
+        padding: 10px;
+        margin: 10px 0;
+        background-color: #F7F7F7;
+        display: flex;
+        align-items: center;
+        justify-content: space-around;
+        &-item {
+          text-align: center;
+          .name {
+            color: #666666;
+            font-size: 12px;
+            padding-bottom: 5px;
+            .timer {
+              font-size: 10px;
+              display: inline-block;
+            }
+          }
+          .price {
+            color: #333333;
+            font-size: 12px;
+          }
+        }
+      }
+    }
+    .bm-charts {
+      height: 190px;
+      margin-bottom: 10px;
+      &__title {
+        color: #333333;
+        height: 13px;
+        line-height: 13px;
+        padding-left: 18px;
+        position: absolute;
+        margin-top: 6px;
+        font-size: 13px;
+        background-repeat: no-repeat;
+        background-size: contain;
+      }
+    }
+  }
+  .map-control-warp {
+    .title {
+      font-weight: bold;
+    }
+    .map-card {
+      width: 100%;
+      background-color: rgba(255, 255, 255, 1);
+
+      .card-input {
+        display: flex;
+        margin-bottom: 15px;
+        padding-bottom: 15px;
+        border-bottom: 1px solid #EDEDED;
+        white-space: nowrap;
+        align-items: center;
+        justify-content: space-between;
+        .btn-echarts {
+          width: 30px;
+          height: 30px;
+          cursor: pointer;
+          border-radius: 5px;
+          background-size: 60% 60%;
+          background-repeat: no-repeat;
+          background-position: center;
+          border: 2px solid #5B8FF9;
+          &.no {
+            background-color: #5B8FF9;
+          }
+          &.ok {
+            background-color: #ffffff;
+          }
+        }
+      }
+      .card-control {
+        .van-search {
+          .van-search__content {
+            background-color: #f7f8fa !important;
+          }
+        }
+        .map-list-pagination {
+          display: none;
+          padding: 0;
+          padding-top: 10px;
+          font-size: 12px;
+          font-weight: bold;
+          color: #333333;
+        }
+        .card-list {
+          margin: 0 10px;
+          overflow: hidden;
+          overflow-y: auto;
+          height: 100%;
+          padding-inline-start: 0;
+        }
+        .card-list li {
+          cursor: pointer;
+          padding: 10px 5px 10px 35px;
+          list-style: none;
+          background-size: 22px 29px;
+          background-repeat: no-repeat;
+          background-position: 3px 15px;
+          border-bottom: 1px solid #ededed;
+          .title, .title > div {
+            display: flex;
+            align-items: center;
+          }
+          .title {
+            padding-top: 3px;
+            justify-content: space-between;
+            span {
+              font-size: 14px;
+              font-weight: normal;
+            }
+            .item-tag {
+              color: #666666;
+              white-space: nowrap;
+            }
+            .item-name {
+              text-align: left;
+              max-width: 170px;
+              color: #333333;
+              font-size: 16px;
+              font-weight: bold;
+            }
+            .item-type {
+              height: 15px;
+              line-height: 15px;
+              padding: 0 1.5px;
+              font-size: 9px;
+              border-radius: 2px;
+              background-color: #22BA55;
+              color: #ffffff;
+            }
+          }
+          .address {
+            padding-top: 8px;
+            font-size: 12px;
+            text-align: left;
+            color: #999999;
+          }
+          .content {
+            padding-top: 10px;
+            font-size: 12px;
+            display: flex;
+            align-items: center;
+            justify-content: flex-start;
+            & > span {
+              &:first-child {
+                padding-right: 15px;
+              }
+            }
+            .time {
+              font-size: 11px;
+              color: #999999;
+            }
+          }
+        }
+      }
+    }
+  }
+  .map-control-opt {
+    top: 0;
+    right: 0;
+    z-index: 6;
+    padding: 15px;
+    position: absolute;
+    label {
+      padding: 5.5px;
+      margin-right: 10px;
+      background-color: #ffffff;
+    }
+    button {
+      width: 80px;
+      color: #2765E2;
+      margin-left: 10px;
+    }
+  }
+  .marker-label-tag {
+    padding: 4px 8px;
+    .title {
+      font-size: 13px;
+      font-weight: bold;
+      padding-bottom: 8px;
+    }
+    .detail {
+      font-size: 10px;
+      color: #6E7A8F;
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+      .number {
+        padding-right: 10px;
+      }
+    }
+  }
+  .text-bold-number {
+    color: #333333 !important;
+    font-weight: bold !important;
+  }
+  .anchorBL > img {
+    display: none;
+  }
+  .text-overflow-ellipsis {
+    display: -webkit-box;
+    /*作为弹性伸缩盒子模型显示*/
+    -webkit-line-clamp: 1;
+    /*显示的行数;如果要设置2行加...则设置为2*/
+    overflow: hidden;
+    /*超出的文本隐藏*/
+    text-overflow: ellipsis;
+    /* 溢出用省略号*/
+    -webkit-box-orient: vertical;
+    /*伸缩盒子的子元素排列:从上到下*/
+  }
+  .map-card-wrap {
+    width: 100%;
+    &.map {
+      position: absolute;
+      z-index: 10000;
+      top: 0;
+      left: 0;
+    }
+    &__info {
+      margin: 0;
+      border-radius: unset;
+      background-color: #ffffff;
+      box-shadow: 0px 0px 9px 1px rgba(14, 14, 16, 0.16);
+      &.map {
+        margin: 12px;
+        border-radius: 6px;
+      }
+      &-box, &-search {
+        padding: 15px 10px;
+      }
+      &-box {
+        .item {
+          .name {
+            font-size: 12px;
+            color: #606574;
+            padding-bottom: 10px;
+          }
+          .value {
+            font-size: 16px;
+            color: #1C1D21;
+            .unit {
+              font-size: 12px;
+              color: #868B9A;
+            }
+          }
+        }
+      }
+      &-search {
+        padding: 0 10px;
+        border-top: 1px solid #ededed;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        .van-dropdown-menu {
+          width: 70%;
+          .van-dropdown-menu__item {
+            justify-content: flex-start;
+          }
+        }
+      }
+    }
+  }
+  .list-icon {
+    position: fixed;
+    bottom: 15px;
+    right: 15px;
+    z-index: 10000;
+    border-radius: 50%;
+    width: 60px;
+    height: 60px;
+    overflow: hidden;
+    background-color: #ffffff;
+    box-shadow: 0px 0px 9px 1px rgba(14, 14, 16, 0.16);
+
+    background-repeat: no-repeat;
+    background-position: center 10px;
+    background-size: 45%;
+    &.list {
+      background-image: url(images/home/list-checkbox@2x.png);
+    }
+    &.map {
+      background-image: url(images/home/map-draw@2x.png);
+    }
+  }
+  .list-wrap {
+    color: #1c1d21;
+    padding: 10px 15px;
+    &__item {
+      padding: 12px;
+      text-align: left;
+      border-radius: 4px;
+      margin-bottom: 10px;
+      background-color: #ffffff;
+      box-shadow: 0px 0px 10px 1px rgba(28, 29, 33, 0.02);
+
+      .item-info .item-info__user, .item-header {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+      }
+
+      .item-header {
+        height: 36px;
+        margin-bottom: 5px;
+        border-bottom: 1px solid #efeff4;
+      }
+      .item-info .label {
+        padding: 5px 0;
+        background-repeat: no-repeat;
+        background-position: left center;
+        background-size: contain;
+        padding-left: 28px;
+        margin-bottom: 5px;
+        &.user {
+          background-image: url(images/home/user@2x.png);
+        }
+        &.speed {
+          background-image: url(images/home/speed@2x.png);
+        }
+        &.local {
+          background-image: url(images/home/local@2x.png);
+        }
+        &:last-child {
+          margin-bottom: 0;
+        }
+        .driver-wrap {
+          display: flex;
+          width: 60%;
+          overflow: hidden;
+          overflow-x: auto;
+          .driver-list {
+            padding: 4px 8px;
+            background-color: #2979FF;
+            border-radius: 2px;
+            margin-right: 8px;
+            color: #ffffff;
+            white-space: nowrap;
+            &:last-child {
+              margin-right: 0;
+            }
+          }
+        }
+        .status {
+          font-size: 10px;
+          border-radius: 2px;
+          padding: 2px 8px;
+          &__0 {
+            color: rgba(69, 199, 151, 1);
+            background-color: rgba(69, 199, 151, .1);
+          }
+          &__1 {
+            color: rgba(41, 121, 255, 1);
+            background-color: rgba(41, 121, 255, .1);
+          }
+          &__2 {
+            color: rgba(28, 29, 33, 1);
+            background-color: rgba(28, 29, 33, .1);
+          }
+        }
+      }
+    }
+  }
+}

+ 2 - 1
src/main.js

@@ -4,6 +4,7 @@ import router from './router'
 import store from './store'
 import { longtap } from './utils/directive'
 import './assets/reset.css'
+import './assets/index.scss'
 import './utils/vant.js'
 import moment from 'moment'
 import 'moment/locale/zh-cn'
@@ -12,7 +13,7 @@ import VueBMap from 'vue-bmap-gl'
 
 Vue.use(VueBMap)
 VueBMap.initBMapApiLoader({
-  ak: 'dfhycORtYDMz78dNLo9oNiDO1ufI2TZS',
+  ak: 'Zvd6FzmertUwjhZih5Zfq0D8uTUhvqsH',
   v: '1.0'
 })
 Vue.prototype.$moment = moment

+ 18 - 24
src/router/index.js

@@ -1,39 +1,33 @@
 import Vue from 'vue'
-import { getLocalStorage } from '@/utils/storage'
 import VueRouter from 'vue-router'
 Vue.use(VueRouter)
 
 const routes = [
-  { path: '/', name: 'main' },
+  { path: '/', name: 'home' },
   {
-    path: '/login',
-    name: 'login',
-    meta: { title: '登录' },
-    component: () => import('@/views/main/login')
-  },
-  {
-    path: '/agreement',
-    name: 'agreement',
-    meta: { title: '服务协议' },
-    component: () => import(/* webpackChunkName:"name" */'@/views/main/agreement')
+    path: '/home',
+    name: 'home',
+    meta: { title: 'LNG商用车服务' },
+    component: () => import('@/views/home/index')
   }
 ]
 
 const router = new VueRouter({
   routes: [...routes]
 })
-router.beforeEach((to, from, next) => {
-  const mwxtoken = getLocalStorage('mwxtoken')
 
-  if (to.meta.title) { // 每页增加title
-    document.title = to.meta.title
-  }
-  if (mwxtoken) {
-    if (to.name === 'main') return next('/boss')
-    return next()
-  }
-  if (to.name === 'login' || to.name === 'agreement') return next()
-  return next('/login')
-})
+// router.beforeEach((to, from, next) => {
+//   const mwxtoken = getLocalStorage('mwxtoken')
+//
+//   if (to.meta.title) { // 每页增加title
+//     document.title = to.meta.title
+//   }
+//   if (mwxtoken) {
+//     if (to.name === 'main') return next('/boss')
+//     return next()
+//   }
+//   if (to.name === 'login' || to.name === 'agreement') return next()
+//   return next('/login')
+// })
 
 export default router

+ 5 - 0
src/service/gasdata.js

@@ -0,0 +1,5 @@
+import R from '@/utils/request'
+
+export async function $gasdataGaugeAll (data) {
+  return await R({ url: 'gasdata/gauge/all', data })
+}

+ 1 - 49
src/store/modules/user.js

@@ -1,7 +1,4 @@
-import { $login, $logout } from '@/service/main'
-import { setLocalStorage, getLocalStorage, removeLocalStorage } from '@/utils/storage'
-
-const Base64 = require('js-base64').Base64
+import { getLocalStorage, removeLocalStorage } from '@/utils/storage'
 
 const user = {
   state: {
@@ -32,57 +29,12 @@ const user = {
   actions: {
     login({ commit, state }, data) {
       return new Promise((resolve, reject) => {
-        $login(data).then(response => {
-          if (response.data.code === 0) {
-            const token = response.data.data.access_token
-            const user = response.data.data.user
-            const orgId = user.authorities[0].orgId
-            const roleId = user.authorities[0].roles[0].roleId
-            const identifier = Base64.encode(
-              'woperation:' + orgId + ':' + user.user_id + ':' + roleId
-            )
-
-            setLocalStorage('mwxtoken', token)
-            setLocalStorage('mwxuser', JSON.stringify(user))
-            setLocalStorage('mwxidntf', identifier)
-            setLocalStorage('mwxorg', orgId)
-            setLocalStorage('mwxrole', roleId)
-            commit('setmwxtoken', token)
-            commit('setmwxidntf', identifier)
-            commit('setmwxuser', user)
-            commit('setmwxrole', roleId)
-            commit('setmwxorg', orgId)
 
-            resolve(response)
-          }
-        }).catch(error => {
-          reject(error)
-        })
       })
     },
     logout({ commit, state }) {
       return new Promise((resolve, reject) => {
-        const data = {
-          client_id: 'woperation',
-          user_id: state.mwxuser.user_id
-        }
-        $logout(data).then(response => {
-          removeLocalStorage('mwxtoken')
-          removeLocalStorage('mwxuser')
-          removeLocalStorage('mwxidntf')
-          removeLocalStorage('mwxorg')
-          removeLocalStorage('mwxrole')
-          removeLocalStorage('location_pointer')
-          commit('setmwxtoken')
-          commit('setmwxidntf')
-          commit('setmwxuser')
-          commit('setmwxrole')
-          commit('setmwxorg')
 
-          resolve()
-        }).catch(error => {
-          reject(error)
-        })
       })
     },
     clear({ commit, state }) {

+ 243 - 0
src/views/home/index.vue

@@ -0,0 +1,243 @@
+<template>
+  <div class="battle-warp">
+    <div class="map-card-wrap" :class="showType === 1 ? 'map' : ''">
+      <div class="map-card-wrap__info" :class="showType === 1 ? 'map' : ''">
+        <van-row class="map-card-wrap__info-box" :gutter="3" type="flex" justify="center">
+          <van-col :span="6" class="item" v-for="(item, index) of cardList" :key="index">
+            <div class="name">{{ item.name }}</div>
+            <div class="value">{{ item.value }} <span class="unit">{{ item.unit }}</span></div>
+          </van-col>
+        </van-row>
+        <div class="map-card-wrap__info-search">
+          <van-dropdown-menu active-color="#1989fa">
+            <van-dropdown-item v-model="tradeStatus" :options="tradeStatusList" />
+            <van-dropdown-item v-model="runStatus" :options="runStatusList" />
+          </van-dropdown-menu>
+          <div><van-icon name="search" /></div>
+        </div>
+      </div>
+    </div>
+    <div class="list-icon" :class="showType === 1 ? 'list' : 'map'" @click="mapToListEvent">
+      <div style="font-size: 14px;margin-top: 42px;">{{ showType === 1 ? '列表' : '地图' }}</div>
+    </div>
+    <el-bmap v-if="nextTickStatus && showType === 1" vid="bmap" :zoom="zoom" :center="center" class="bm-view" :style="mapStyle">
+      <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>
+    </el-bmap>
+    <div v-else-if="nextTickStatus && showType === 2" class="list-wrap">
+      <div class="list-wrap__item" v-for="(item, index) in truckList" :key="index">
+        <div class="item-header">
+          <div class="text-bold">{{ item.carNumber }}<span class="text-normal">({{ item.linked === 1 ? '其他' : '自营' }})</span></div>
+          <div>今日里程<span class="color-blue">{{ item.mileage || '-' }}</span>公里</div>
+        </div>
+        <div class="item-info">
+          <div class="label item-info__user" style="padding-left: 0" v-if="item.truckDriverList.length > 0">
+            <div class="driver-wrap">
+              <div v-for="(driver, driverIndex) in item.truckDriverList" :key="driverIndex" class="driver-list">{{ driver.tmpDriverName || '-' }}</div>
+            </div>
+            <div>{{ item.truckDriverList[0].tmpDriverMobile || '-' }}</div>
+          </div>
+          <div class="label speed">
+            <span>{{ item.speed || '-' }}</span>公里/小时
+            <span class="status" :class="'status__' + item.speedStatus">{{ truckStatusList[item.speedStatus] }}</span>
+          </div>
+          <div class="label local">{{ item.currAddress || '-' }}</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import 'vue-bmap-gl/dist/style.css'
+import axios from 'axios'
+// import { $districtList, $userFindConfigAreaList } from '@/service/user'
+import { $gasdataGaugeAll } from '@/service/gasdata'
+// import { currency, formateZeroToBar } from '@/utils/filters'
+// import { MarkerWindow, AreaDataAnalysis } from './components'
+// import { mapJsonData } from '@/mock/map'
+export default {
+  name: 'battle',
+  // components: { MarkerWindow, AreaDataAnalysis },
+  data() {
+    return {
+      map: null,
+      showType: 1,
+      mapStyle: {
+        width: '100%',
+        height: '100%'
+      },
+      center: [116.23228, 35.7127],
+      zoom: 8,
+      heading: 0,
+      index: 1,
+      timer: null,
+      mapHeight: 400,
+      cardList: [{
+        name: '在线/总量',
+        value: '0/0',
+        unit: '辆'
+      }, {
+        name: '今日总里程',
+        value: '0',
+        unit: '公里'
+      }, {
+        name: '今日总耗能',
+        value: '0',
+        unit: '公斤'
+      }, {
+        name: '今日总减碳',
+        value: '0',
+        unit: '公斤'
+      }],
+      tradeStatus: 0,
+      tradeStatusList: [
+        { text: '全经营类型', value: 0 },
+        { text: '自营', value: 1 },
+        { text: '外协', value: 2 }
+      ],
+      runStatus: 0,
+      runStatusList: [
+        { text: '全行驶状态', value: 0 },
+        { text: '行驶', value: 1 },
+        { text: '静止', value: 2 },
+        { text: '离线', value: 3 }
+      ],
+      truckStatusList: {
+        0: '行驶中',
+        1: '静止中',
+        2: '离线中'
+      },
+      truckList: [],
+      markers: [],
+      nextTickStatus: true
+    }
+  },
+  watch: {},
+  computed: {},
+  created() {
+    this.dragendPointer()
+    setInterval(() => {
+      this.dragendPointer()
+    }, 60000)
+  },
+  mounted() {
+    // 重置地图高度
+    this.mapHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
+  },
+  beforeDestroy() {
+    clearTimeout(this.timer)
+  },
+  methods: {
+    async queryCurrAddress(location) {
+      const url = 'https://api.map.baidu.com/reverse_geocoding/v3/'
+
+      const data = await axios.post(url + '?output=json&ak=Zvd6FzmertUwjhZih5Zfq0D8uTUhvqsH&coordtype=wgs84ll&location=' + location).then(response => {
+        return response.data
+      })
+
+      if (data.hasOwnProperty('result')) {
+        return data.result.addressComponent
+      } else {
+        return '-'
+      }
+    },
+    angle(start, end) {
+      // 通过 a、b 确定角度所处的象限
+      const a = start[0] - end[0]
+      const b = start[1] - end[1]
+      // eslint-disable-next-line camelcase
+      const a_c = Math.abs(a)
+      // eslint-disable-next-line camelcase
+      const b_c = Math.abs(b)
+      // 获取得三角形的斜边 Math.hypot();
+      const c = Math.hypot(a_c, b_c)
+      // 计算弧度
+      // eslint-disable-next-line camelcase
+      const radina = Math.acos(a_c / c)
+      // 计算角度
+      let angleVal = Math.floor(radina * 180 / Math.PI)
+      // 处理最终需要旋转的角度
+      if (a > 0) {
+        // 第二、三象限
+        if (b > 0) {
+          // 三
+          angleVal = 90 + 90 - angleVal
+        } else {
+          angleVal = -180 + angleVal
+        }
+      } else {
+        // 一、四象限
+        if (b > 0) {
+          // 四
+          // eslint-disable-next-line no-self-assign
+          angleVal = angleVal
+        } else {
+          // 一
+          angleVal = -angleVal
+        }
+      }
+      return angleVal
+    },
+    mapToListEvent() {
+      this.showType = this.showType === 1 ? 2 : 1
+    },
+    truckToDriverInfo(item, type = 'user') {
+      // 解释司机个人信息
+      if (item.hasOwnProperty('truckDriverList') && item.truckDriverList.length > 0) {
+        item.truckDriverList.forEach(driver => {
+          const driverUserInfo = driver.driverName ? driver.driverName.split('/') : []
+          driver.tmpDriverName = driverUserInfo.length >= 1 ? driverUserInfo[0] : '-'
+          driver.tmpDriverMobile = driverUserInfo.length >= 2 ? driverUserInfo[1] : '-'
+        })
+      } else {
+        return '-'
+      }
+    },
+    dragendPointer() {
+      this.markers = []
+      $gasdataGaugeAll({}).then(response => {
+        const data = response.carMonitorVos
+
+        // 统计数据
+        this.cardList[0].value = response.onLine + '/' + response.total
+        this.cardList[1].value = response.mileage.toFixed(0)
+        this.cardList[2].value = response.consumption
+        this.cardList[3].value = response.carbon
+        this.truckList = data
+
+        data.forEach(async item => {
+          this.markerInfo(item)
+          // 根据金纬度获取地理位置信息
+          const addressInfo = await this.queryCurrAddress(item.lat + ',' + item.lng)
+          item.currAddress = addressInfo.province + addressInfo.city + addressInfo.district + addressInfo.street
+        })
+      })
+    },
+    markerInfo(item) {
+      const info = {
+        icon: {},
+        label: {},
+        visible: true,
+        enableDragging: false
+      }
+
+      info.label = {
+        content: item.carNumber,
+        offset: [-23, -25],
+        style: {
+          borderWidth: 0,
+          padding: '3px 10px',
+          borderRadius: '4px',
+          boxShadow: '0px 0px 9px 1px rgba(28, 29, 33, 0.16)'
+        }
+      }
+      info.icon = {
+        url: require('@/assets/images/navigation/navigation@2x.png'),
+        size: [20, 26]
+      }
+      info.position = [item.lng, item.lat]
+
+      this.markers.push(info)
+    }
+  }
+}
+</script>

+ 342 - 0
src/views/home/list.vue

@@ -0,0 +1,342 @@
+<template>
+  <div class="battle-warp">
+    <div class="map-card-wrap">
+      <div class="map-card-wrap__info">
+        <van-row class="map-card-wrap__info-box" :gutter="3" type="flex" justify="center">
+          <van-col :span="6" class="item" v-for="(item, index) of cardList" :key="index">
+            <div class="name">{{ item.name }}</div>
+            <div class="value">{{ item.value }} <span class="unit">{{ item.unit }}</span></div>
+          </van-col>
+        </van-row>
+        <div class="map-card-wrap__info-search">
+          <van-dropdown-menu active-color="#1989fa">
+            <van-dropdown-item v-model="tradeStatus" :options="tradeStatusList" />
+            <van-dropdown-item v-model="runStatus" :options="runStatusList" />
+          </van-dropdown-menu>
+          <div><van-icon name="search" /></div>
+        </div>
+      </div>
+    </div>
+    <div class="list-icon">
+      <van-icon name="bars" size="30" style="margin-top: 10px;" />
+      <div style="font-size: 12px;">列表</div>
+    </div>
+    <!--头部查询条件-->
+<!--    <div class="map-search">
+      <div class="search-bar">
+        <img src="@/assets/user.png" @click="userInfo" />
+        <van-dropdown-menu>
+          <van-dropdown-item v-model="finds.districtId" :options="districtList" @change="(value) => { initGasstationList(value, 'area') }" />
+          <van-dropdown-item v-model="finds.gasType" :options="gasstationType" @change="initGasstationList" />
+        </van-dropdown-menu>
+      </div>
+      <div class="search-icon" @click="searchGasstationList"><van-icon name="search" /></div>
+    </div>-->
+    <!--底部标签栏-->
+<!--    <van-tabbar v-model="active">
+      <van-tabbar-item icon="gem-o" @click="meClickEvent">我的贡献</van-tabbar-item>
+      <van-tabbar-item icon="plus" @click="gasstationClickEvent">新增站点</van-tabbar-item>
+      <van-tabbar-item icon="chart-trending-o" @click.native="dataAnalysisEvent('open')">智能分析</van-tabbar-item>
+    </van-tabbar>-->
+    <!--地标文字-->
+<!--    <van-checkbox v-model="markerTitleStatus" shape="square" checked-color="#2765E2" @change="markerLabelEvent">地标文字</van-checkbox>-->
+    <!--加气站列表-->
+<!--    <van-popup v-model="gasstationInfoStatus" position="right" :style="{ width: '100%', height: '100%' }">
+      <div class="map-control-warp">
+        <div class="map-card">
+          <div class="card-control">
+            <van-search v-model="filterGasstationName" show-action placeholder="请输入加气站">
+              <template #action>
+                <div @click="searchBackEvent">返回</div>
+              </template>
+            </van-search>
+            <div class="map-list-pagination">共 {{pages.total}} 站点</div>
+            <ul class="card-list" :style="{ height: (mapHeight - 55) + 'px'}">
+              <li v-for="(item, index) of currGasstationList" :key="index" :class="'icon-' + (item.gasType || 2004)" @click="markerClickEvent(item)">
+                <div class="title">
+                  <div>
+                    <span class="item-name text-overflow-ellipsis">{{gasstationNickName(item)}}</span>
+                    <span class="item-tag">[{{getGasstationTypeName(item.gasType)}}]</span>
+                  </div>
+                  <div class="item-type" v-if="item.gasType === 1001">自</div>
+                  <div class="item-type" v-else-if="item.gasType === 1002">合</div>
+                  <div class="item-type" v-else-if="item.gasType === 1003">盟</div>
+                </div>
+                <div class="address text-overflow-ellipsis">{{item.address}}</div>
+                <div class="content">
+                  <span>
+                    <span class="text-bold-number">{{ (gasstationCheckType(item.gasType) ? item.offlineGasQty : (item.gasQty + item.offlineGasQty)) | formateZeroToBar('no') }}</span>吨<span class="time">({{ (gasstationCheckType(item.gasType) ? item.offlineGasQtyDate : item.gasQtyDate) | formateTData('date') }})</span>
+                  </span>
+                  <span>
+                    <span class="text-bold-number">{{ (gasstationCheckType(item.gasType) ? item.offlinePrice : item.price) | currency }}</span>/公斤<span class="time">({{ (gasstationCheckType(item.gasType) ? item.offlinePriceDate : item.priceDate) | formateTData('date') }})</span>
+                  </span>
+                </div>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+    </van-popup>-->
+    <!--某个站点单击显示信息-->
+<!--    <van-popup v-model="currentWindow.markerWindowStatus" class="bmap-info-window-custom" round position="bottom">
+      <marker-window v-if="currentWindow.markerWindowStatus" :rowData="currentWindow.data" :isNotDxStatus="gasstationCheckType(currentWindow.data.gasType)"></marker-window>
+    </van-popup>-->
+    <!--区域数据分析-->
+<!--    <van-popup v-model="markerDataAnalysisStatus" position="bottom">
+      <area-data-analysis v-if="markerDataAnalysisStatus" :name="analysisDistrictName" :finds="finds"></area-data-analysis>
+    </van-popup>-->
+  </div>
+</template>
+<script>
+import 'vue-bmap-gl/dist/style.css'
+// import { $districtList, $userFindConfigAreaList } from '@/service/user'
+// import { $gasdataGasstationList } from '@/service/gasdata'
+import { currency, formateZeroToBar } from '@/utils/filters'
+// import { MarkerWindow, AreaDataAnalysis } from './components'
+import { mapJsonData } from '@/mock/map'
+
+export default {
+  name: 'battle',
+  // components: { MarkerWindow, AreaDataAnalysis },
+  data() {
+    return {
+      mapStyle: {
+        width: '100%',
+        height: '100%'
+      },
+      center: [116.23228, 35.7127],
+      zoom: 7,
+      mapHeight: 400,
+      cardList: [{
+        name: '在线/总量',
+        value: '55/100',
+        unit: '辆'
+      }, {
+        name: '今日总里程',
+        value: '600',
+        unit: '公里'
+      }, {
+        name: '今日总耗能',
+        value: '234.12',
+        unit: '公斤'
+      }, {
+        name: '今日总减碳',
+        value: '123.56',
+        unit: '公斤'
+      }],
+      tradeStatus: 0,
+      tradeStatusList: [
+        { text: '全经营类型', value: 0 },
+        { text: '自营', value: 1 },
+        { text: '外协', value: 2 }
+      ],
+      runStatus: 0,
+      runStatusList: [
+        { text: '全行驶状态', value: 0 },
+        { text: '行驶', value: 1 },
+        { text: '静止', value: 2 },
+        { text: '离线', value: 3 }
+      ]
+    }
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {
+    // 重置地图高度
+    this.mapHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
+  },
+  methods: {
+    // 初始化数据
+    initData() {
+      // 初始化区域list
+      this.initDistrictList()
+      // 加气站list
+      this.initGasstationList()
+      // 获取地图经纬度数据
+      this.pointList = mapJsonData('all')
+    },
+    districtToAreaList() {
+      /* $userFindConfigAreaList({ districtId: this.finds.districtId }).then(response => {
+        const tmpPointList = []
+        const data = response || []
+        const featuresList = this.pointList.features || []
+
+        data.forEach(item => {
+          for (let i = 0; i < featuresList.length; i++) {
+            if (trim(featuresList[i].properties.name) === trim(item.areaName)) {
+              const tmpCoordList = featuresList[i].geometry.coordinates || []
+              tmpCoordList.forEach(coord => {
+                tmpPointList.push(...new Set(coord))
+              })
+              break
+            }
+          }
+        })
+        this.polygon.path = tmpPointList
+      }) */
+    },
+    markerLabelEvent() {
+      this.$nextTick(() => {
+        this.gasstationList.forEach(item => {
+          item.markerStatus = !this.markerTitleStatus
+        })
+      })
+    },
+    initDistrictList() {
+      /* $districtList({}).then(response => {
+        const tmpRes = response || []
+
+        let pointX = 0
+        let pointY = 0
+        tmpRes.forEach((item, index) => {
+          item.value = item.districtId
+          item.text = item.districtName
+          item.points = this.points[item.districtName]
+          pointX += item.points[0]
+          pointY += item.points[1]
+        })
+        if (tmpRes.length > 0) {
+          this.center = [pointX / tmpRes.length, pointY / tmpRes.length]
+        }
+        tmpRes.unshift({ value: '', text: '全区域', points: this.center })
+        this.districtList = tmpRes
+      }) */
+    },
+    setMapCenter(value) {
+      this.districtList.forEach(item => {
+        if (value === item.value) {
+          this.center = item.points
+        }
+      })
+    },
+    initGasstationList(value = '', type = '') {
+      // const params = this.finds
+
+      if (type === 'area') {
+        this.districtToAreaList()
+      }
+      // 设置中心位置
+      this.setMapCenter(value)
+      this.filterGasstationName = ''
+      this.dataAnalysisEvent('close')
+      /* $gasdataGasstationList(params).then(response => {
+        const res = response || []
+        // 通过接口获取的数据,不可变
+        this.gasstationList = [...new Set(res)]
+        // 可通过加气站名过来
+        this.currGasstationList = [...new Set(res)]
+        this.pages.total = this.gasstationList.length
+      }) */
+    },
+    async dataAnalysisEvent(type) {
+      if (type === 'open') {
+        if (this.markerDataAnalysisStatus) return false
+
+        this.markerDataAnalysisStatus = true
+      } else {
+        this.markerDataAnalysisStatus = false
+      }
+    },
+    // 获取加气站类型
+    getGasstationTypeName(type) {
+      let name = '-'
+
+      this.gasstationType.forEach(item => {
+        if (type === item.value) {
+          name = this.gasstationCheckType(type) ? item.text : '大象加气'
+        }
+      })
+
+      return name
+    },
+    gasstationCheckType(type) {
+      if (type === 2001 || type === 2002 || type === 2003 || type === 2004) {
+        return true
+      }
+
+      return false
+    },
+    filterGasstationList(value) {
+      this.currGasstationList = this.gasstationList.filter(item => item.nickName && item.nickName.indexOf(value) !== -1)
+    },
+    searchBackEvent() {
+      this.gasstationInfoStatus = false
+    },
+    markerPopVisibleNode() {
+      const dom = document.getElementsByClassName('BMap_bubble_pop')[0]
+      const shadow = document.getElementsByClassName('shadow')[0]
+      let currClass = dom.getAttribute('class')
+      let currShadowClass = shadow.getAttribute('class')
+
+      if (this.currentWindow.markerWindowStatus) {
+        currClass = currClass.replace('bmap-info-window-hide', '')
+        currShadowClass = currShadowClass.replace('bmap-info-window-hide', '')
+      } else {
+        currClass = currClass.concat(' bmap-info-window-hide')
+        currShadowClass = currShadowClass.concat(' bmap-info-window-hide')
+      }
+
+      dom.setAttribute('class', currClass)
+      shadow.setAttribute('class', currShadowClass)
+    },
+    mapMarkIcon(item) {
+      // let imageURL = require('@/assets/battle/g_map_icon_default.png')
+      //
+      // if (item.gasType === 100 || item.gasType === 1001 || item.gasType === 1002 || item.gasType === 1003) {
+      //   imageURL = require('@/assets/battle/g_map_icon_1.png')
+      // } else if (item.gasType === 2001) {
+      //   imageURL = require('@/assets/battle/g_map_icon_3.png')
+      // } else if (item.gasType === 2002) {
+      //   imageURL = require('@/assets/battle/g_map_icon_2.png')
+      // } else if (item.gasType === 2003) {
+      //   imageURL = require('@/assets/battle/g_map_icon_4.png')
+      // } else if (item.gasType === 2004) {
+      //   imageURL = require('@/assets/battle/g_map_icon_default.png')
+      // }
+      // return { url: imageURL, size: [20, 26] }
+    },
+    // 点击某个点弹框
+    markerClickEvent(item) {
+      this.infoWindowClose(item)
+      this.infoWindowOpen(item)
+    },
+    // 关闭窗口
+    infoWindowClose(item) {
+      this.currentWindow.markerWindowStatus = false
+    },
+    // 打开窗口
+    infoWindowOpen(item) {
+      this.currentWindow.markerWindowStatus = false
+      // 统计图
+      this.$nextTick(() => {
+        this.currentWindow.data = item
+
+        this.currentWindow.markerWindowStatus = true
+      })
+    },
+    markerLabelContent(item) {
+      let html = ''
+
+      html += '<div class="marker-label-tag"><div class="title">' + this.gasstationNickName(item) + '</div><div class="detail"><div class="number"><span class="text-bold-number">' + formateZeroToBar(item.gasQty + item.offlineGasQty, 'no') + '</span> 吨</div><div class="money"><span class="text-bold-number">' + currency((this.gasstationCheckType(item.gasType) ? item.offlinePrice : item.price)) + '</span>/公斤</div></div></div>'
+
+      return html
+    },
+    searchGasstationList() {
+      this.gasstationInfoStatus = true
+    },
+    gasstationNickName(item) {
+      return item.nickName || '-'
+    },
+    meClickEvent() {
+      this.$router.push({ path: '/me' })
+    },
+    userInfo() {
+      this.$router.push({ path: '/user' })
+    },
+    gasstationClickEvent() {
+      this.$router.push({ path: '/form', query: { type: 'add' } })
+    }
+  }
+}
+</script>