Browse Source

大屏提交

lilei 4 years ago
parent
commit
ded4972318

+ 54 - 3
package-lock.json

@@ -995,7 +995,6 @@
       "version": "7.6.3",
       "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
       "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
-      "dev": true,
       "requires": {
         "regenerator-runtime": "^0.13.2"
       },
@@ -1003,8 +1002,7 @@
         "regenerator-runtime": {
           "version": "0.13.3",
           "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
-          "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
-          "dev": true
+          "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
         }
       }
     },
@@ -1132,6 +1130,59 @@
         "postcss": "^7.0.0"
       }
     },
+    "@jiaminghi/bezier-curve": {
+      "version": "0.0.9",
+      "resolved": "https://registry.npmjs.org/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz",
+      "integrity": "sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==",
+      "requires": {
+        "@babel/runtime": "^7.5.5"
+      }
+    },
+    "@jiaminghi/c-render": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/@jiaminghi/c-render/-/c-render-0.4.3.tgz",
+      "integrity": "sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==",
+      "requires": {
+        "@babel/runtime": "^7.5.5",
+        "@jiaminghi/bezier-curve": "*",
+        "@jiaminghi/color": "*",
+        "@jiaminghi/transition": "*"
+      }
+    },
+    "@jiaminghi/charts": {
+      "version": "0.2.18",
+      "resolved": "https://registry.npmjs.org/@jiaminghi/charts/-/charts-0.2.18.tgz",
+      "integrity": "sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==",
+      "requires": {
+        "@babel/runtime": "^7.5.5",
+        "@jiaminghi/c-render": "^0.4.3"
+      }
+    },
+    "@jiaminghi/color": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/@jiaminghi/color/-/color-0.1.1.tgz",
+      "integrity": "sha512-M09+Sb5HGqVim0zo+nG5gU1v+6gXT8ptr0BZR6dMGt83XmCJgnZtO8s7llTW4hLFFFM5co6geZvTekqLpSPAAQ==",
+      "requires": {
+        "@babel/runtime": "^7.5.5"
+      }
+    },
+    "@jiaminghi/data-view": {
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/@jiaminghi/data-view/-/data-view-2.10.0.tgz",
+      "integrity": "sha512-Cud2MTiMcqc5k2KWabR/svuVQmXHANqURo+yj40370/LdI/gyUJ6LG203hWXEnT1nMCeiv/SLVmxv3PXLScCeA==",
+      "requires": {
+        "@babel/runtime": "^7.5.5",
+        "@jiaminghi/charts": "*"
+      }
+    },
+    "@jiaminghi/transition": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/@jiaminghi/transition/-/transition-1.1.11.tgz",
+      "integrity": "sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==",
+      "requires": {
+        "@babel/runtime": "^7.5.5"
+      }
+    },
     "@mrmlnc/readdir-enhanced": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",

+ 2 - 0
package.json

@@ -15,6 +15,8 @@
   },
   "dependencies": {
     "@antv/data-set": "^0.10.2",
+    "@jiaminghi/charts": "^0.2.18",
+    "@jiaminghi/data-view": "^2.10.0",
     "ant-design-vue": "^1.7.1",
     "axios": "^0.19.0",
     "china-division": "^2.3.1",

BIN
src/assets/dataViewBg.png


+ 1 - 1
src/components/GlobalHeader/GlobalHeader.vue

@@ -2,7 +2,7 @@
   <transition name="showHeader">
     <div v-if="visible" class="header-animat">
       <a-layout-header
-        v-if="visible && $store.state.user.nowRouteName!='NodeMap'"
+        v-if="visible && $store.state.user.nowRouteName!='NodeMap'&& $store.state.user.nowRouteName!='dataViewBoard'"
         :class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed', ]"
         :style="{ padding: '0' }">
         <div v-if="mode === 'sidemenu'" class="header">

+ 35 - 0
src/config/router.config.js

@@ -80,6 +80,41 @@ export const asyncRouterMap = [{
       }]
     }]
   },
+  {
+    path: '/dataView',
+    name: 'dataView',
+    redirect: '/dataView',
+    component: PageView,
+    meta: {
+      title: '大数据看板',
+      icon: 'fund',
+      // permission: 'M_dataView'
+    },
+    hideChildrenInMenu: true,
+    children: [{
+      path: '/dataView',
+      name: 'dataView',
+      redirect: '/dataView/board',
+      component: RouteView,
+      meta: {
+        title: '大数据看板',
+        icon: 'fund',
+        permission: 'M_map'
+      },
+      hideChildrenInMenu: true,
+      children: [{
+        path: '/dataView/board',
+        name: 'dataViewBoard',
+        component: () => import(/* webpackChunkName: "map" */ '@/views/dataView/borard.vue'),
+        meta: {
+          title: '大数据看板',
+          icon: 'fund',
+          hidden: true,
+          hiddenHeaderContent: true,
+        }
+      }]
+    }]
+  },
   {
     path: '/shop',
     redirect: '/shop/goods',

+ 7 - 8
src/layouts/BasicLayout.vue

@@ -36,7 +36,7 @@
         @toggle="toggle" />
 
       <!-- layout content -->
-      <a-layout-content :style="{ height: '100%', margin: '24px 24px 0', paddingTop: fixedHeader ? '64px' : '0' }">
+      <a-layout-content :style="{ height: '100%', margin: $store.state.user.nowRouteName!='dataViewBoard'?'24px 24px 0':'0px', paddingTop: fixedHeader ? '64px' : '0' }">
         <multi-tab v-if="multiTab"></multi-tab>
         <transition name="page-transition">
           <route-view />
@@ -44,7 +44,7 @@
       </a-layout-content>
 
       <!-- layout footer -->
-      <a-layout-footer>
+      <a-layout-footer v-if="$store.state.user.nowRouteName!='dataViewBoard'">
         <global-footer />
       </a-layout-footer>
 
@@ -114,16 +114,15 @@ export default {
   },
   watch: {
     sidebarOpened (val) {
-      // console.log(this.$store.state.user.nowRouteName, 'vvvvvvvvvvv')
-      if (this.$store.state.user.nowRouteName != 'NodeMap') {
+      const nowRouteName = this.$store.state.user.nowRouteName
+      if (nowRouteName != 'NodeMap' && nowRouteName != 'dataViewBoard') {
         this.collapsed = !val
       } else {
         this.collapsed = true
 	  }
     },
     nowRouteName (val) {
-      // console.log(val, 'vvvvvvvvvvv')
-      if (val == 'NodeMap') {
+      if (val == 'NodeMap' || val == 'dataViewBoard') {
         this.collapsed = true
       } else {
         this.collapsed = false
@@ -143,7 +142,7 @@ export default {
   mounted () {
     const userAgent = navigator.userAgent
     console.log(userAgent, this.collapsed, this.nowRouteName, 'this.collapsedthis.collapsedthis.collapsed')
-    if (userAgent.indexOf('Edge') > -1 && this.nowRouteName != 'NodeMap') {
+    if (userAgent.indexOf('Edge') > -1 && this.nowRouteName != 'NodeMap' && this.nowRouteName != 'dataViewBoard') {
       this.$nextTick(() => {
         this.collapsed = !this.collapsed
         setTimeout(() => {
@@ -151,7 +150,7 @@ export default {
         }, 16)
       })
     }
-    if (this.nowRouteName == 'NodeMap') {
+    if (this.nowRouteName == 'NodeMap' || this.nowRouteName == 'dataViewBoard') {
       this.$nextTick(() => {
 		  this.collapsed = true
       })

+ 11 - 4
src/layouts/PageView.vue

@@ -1,5 +1,5 @@
 <template>
-  <div :style="!$route.meta.hiddenHeaderContent ? 'margin: -24px -24px 0px;' : null">
+  <div :class="$store.state.user.nowRouteName=='dataViewBoard'?'dataViewBoard':''" :style="!$route.meta.hiddenHeaderContent ? 'margin: -24px -24px 0px;' : null">
     <!-- pageHeader , route meta :true on hide -->
     <page-header v-if="!$route.meta.hiddenHeaderContent" :title="pageTitle" :logo="logo" :avatar="avatar">
       <slot slot="action" name="action"></slot>
@@ -37,8 +37,8 @@
         </div>
       </div>
     </page-header>
-    <div class="content">
-      <div class="page-header-index-wide">
+    <div class="content" :style="$store.state.user.nowRouteName!='dataViewBoard' ? 'margin: 24px 24px 0;' : null">
+      <div :class="$store.state.user.nowRouteName=='dataViewBoard'?'dataViewBoard':''" class="page-header-index-wide">
         <slot>
           <!-- keep-alive  -->
           <keep-alive v-if="multiTab">
@@ -124,7 +124,6 @@ export default {
 
 <style lang="less" scoped>
   .content {
-    margin: 24px 24px 0;
     .link {
       margin-top: 16px;
       &:not(:empty) {
@@ -149,6 +148,14 @@ export default {
       }
     }
   }
+  .dataViewBoard{
+    height: 100%;
+    width: 100%;
+    .content{
+      height: 100%;
+      width: 100%;
+    }
+  }
   .page-menu-search {
     text-align: center;
     margin-bottom: 16px;

+ 3 - 1
src/main.js

@@ -22,7 +22,9 @@ import VueCookies from 'vue-cookies' // global filter
 import scroll from 'vue-seamless-scroll'
 Vue.use(scroll)
 Vue.config.productionTip = false
-
+// datav
+import dataV from '@jiaminghi/data-view'
+Vue.use(dataV)
 // mount axios Vue.$http and this.$http
 Vue.use(VueAxios)
 Vue.use(VueCookies)

+ 490 - 0
src/views/dataView/borard.vue

@@ -0,0 +1,490 @@
+<template>
+  <div class="dataView-content">
+    <div class="data-header">
+      <dv-border-box-5 :color="['rgba(115, 164, 255, 0.3)', 'rgba(0,125,255,0.2)']" >
+        智享亿家投递大数据
+      </dv-border-box-5>
+      <dv-border-box-5 :color="['rgba(46, 77, 255, 0.2)', 'rgba(0,125,255,0.2)']" :reverse="true">
+        区域
+        <select>
+          <option>全部</option>
+          <option>西安</option>
+          <option>渭南</option>
+          <option>咸阳</option>
+        </select>
+        <a-icon @click="isFullscreenMap" :style="{fontSize:'30px',padding: '7px',float: 'right', cursor: 'pointer'}" :type="isMapFull ?'fullscreen-exit':'fullscreen'" />
+      </dv-border-box-5>
+    </div>
+    <div class="data-body">
+      <div class="b-left">
+        <div>
+          <dv-border-box-13>
+            <div id="con1" style="width: 100%;height: 100%;"></div>
+          </dv-border-box-13>
+        </div>
+        <div>
+          <dv-border-box-13>
+            <div id="con2" style="width: 100%;height: 100%;"></div>
+          </dv-border-box-13>
+        </div>
+      </div>
+      <div class="b-middle">
+        <div>
+          <dv-border-box-12 style="padding: 10px;">
+            <div id="map" :style="{height: '100%'}"></div>
+          </dv-border-box-12>
+        </div>
+        <div>
+          <dv-border-box-8 title="dv-border-box-11">
+            <div class="total-block">
+              <div>
+                <dv-digital-flop
+                  :config="userTotal"
+                  style="width:100%;height:50px;" />
+                <div class="total-label">用户总数</div>
+              </div>
+              <div>
+                <dv-digital-flop
+                  :config="devTotal"
+                  style="width:100%;height:50px;" />
+                <div class="total-label">设备总数</div>
+              </div>
+            </div>
+          </dv-border-box-8>
+        </div>
+      </div>
+      <div class="b-right">
+        <div>
+          <dv-border-box-13>
+            <div id="con3" style="width: 100%;height: 100%;"></div>
+          </dv-border-box-13>
+        </div>
+        <div>
+          <dv-border-box-13>
+            <div id="con4" style="width: 100%;height: 100%;"></div>
+          </dv-border-box-13>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Charts, { changeDefaultConfig } from '@jiaminghi/charts'
+import {
+  getUserTotal,
+  getDeviceTotal,
+  getMapStation
+} from '@/api/nodeMap.js'
+export default {
+  name: 'DataBoratd',
+  data () {
+    return {
+      chart1: null,
+      chart2: null,
+      chart3: null,
+      chart4: null,
+      userTotal: {
+        number: [253461],
+        content: '{nt}',
+        formatter: this.formatter
+      },
+      devTotal: {
+        number: [1250],
+        content: '{nt}',
+        formatter: this.formatter
+      },
+      isMapFull: false,
+      map: null, // 地图对象
+      markerLayer: null, // 地图点标记对象
+      infoWindow: null // 地图信息窗口对象
+    }
+  },
+  methods: {
+    // 全屏
+    fullScreen () {
+      var element = document.documentElement
+      if (element.requestFullscreen) {
+        element.requestFullscreen()
+      } else if (element.msRequestFullscreen) {
+        element.msRequestFullscreen()
+      } else if (element.mozRequestFullScreen) {
+        element.mozRequestFullScreen()
+      } else if (element.webkitRequestFullscreen) {
+        element.webkitRequestFullscreen()
+      }
+    },
+    // 退出全屏
+    exitFullscreen () {
+      if (document.exitFullscreen) {
+        document.exitFullscreen()
+      } else if (document.msExitFullscreen) {
+        document.msExitFullscreen()
+      } else if (document.mozCancelFullScreen) {
+        document.mozCancelFullScreen()
+      } else if (document.webkitExitFullscreen) {
+        document.webkitExitFullscreen()
+      }
+    },
+    // 地图是否全屏展示
+    isFullscreenMap () {
+      this.isMapFull = !this.isMapFull
+      if (this.isMapFull) {
+        this.fullScreen()
+      } else {
+        this.exitFullscreen()
+      }
+      this.chart1.resize()
+      this.chart2.resize()
+      this.chart3.resize()
+      this.chart4.resize()
+    },
+    formatter (number) {
+      const numbers = number.toString().split('').reverse()
+      const segs = []
+      while (numbers.length) segs.push(numbers.splice(0, 3).join(''))
+      return segs.join(',').split('').reverse().join('')
+    },
+    // 初始化地图
+    initMap () {
+      // 定义地图中心点坐标 默认定位在陕西省咸阳市
+      var center = new TMap.LatLng(34.329828, 108.708344)
+      // 定义map变量,调用 TMap.Map() 构造函数创建地图
+      this.map = new TMap.Map(document.getElementById('map'), {
+        center: center, // 设置地图中心点坐标
+        mapStyleId: 'style3',
+        zoom: 17.2, // 设置地图缩放级别
+        pitch: 43.5, // 设置俯仰角
+        rotation: 45 // 设置地图旋转角度
+      })
+      // 创建并初始化MultiMarker 点标记
+      this.markerLayer = new TMap.MultiMarker({
+        map: this.map, // 指定地图容器
+        // 样式定义
+        styles: {
+          // 创建一个styleId为"myStyle"的样式(styles的子属性名即为styleId)
+          'myStyle': new TMap.MarkerStyle({
+            'width': 30, // 点标记样式宽度(像素)
+            'height': 30, // 点标记样式高度(像素)
+            'src': '../mark.png', // 图片路径
+            // 焦点在图片中的像素位置,一般大头针类似形式的图片以针尖位置做为焦点,圆形点以圆心位置为焦点
+            'anchor': {
+              x: 16,
+              y: 32
+            }
+          })
+        },
+        // 点标记数据数组
+        geometries: []
+      })
+      // 初始化infoWindow
+      this.infoWindow = new TMap.InfoWindow({
+        map: this.map,
+        position: new TMap.LatLng(39.984104, 116.307503),
+        offset: {
+          x: 0,
+          y: -32
+        } // 设置信息窗相对position偏移像素
+      })
+      this.infoWindow.close() // 初始关闭信息窗关闭
+      this.markerLayer.on('mousemove', this.showMarkTitle)
+      // 监听地图加载完成
+      this.map.on('tilesloaded', this.getMapMark)
+    },
+    // 获取地图点坐标
+    getMapMark () {
+      getMapStation({}).then(res => {
+        const list = res.data || []
+        const data = []
+        list.map((item, index) => {
+          if (item.lat <= 85.051128 && item.lat >= -85.051128) {
+            const p = {
+              'id': item.id, // 点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
+              'styleId': 'myStyle', // 指定样式id
+              'position': new TMap.LatLng(Number(item.lat), Number(item.lng)), // 点标记坐标位置
+              'properties': { // 自定义属性
+                'title': item.name
+              }
+            }
+            data.push(p)
+          }
+        })
+        // 增加点标记
+        this.markerLayer.add(data)
+      })
+    },
+    // 显示地图标记点名称
+    showMarkTitle (evt) {
+      this.infoWindow.open() // 打开信息窗
+      this.infoWindow.setPosition(evt.geometry.position) // 设置信息窗位置
+      this.infoWindow.setContent(evt.geometry.properties.title) // 设置信息窗内容
+    },
+    // 初始化图表
+    initChart () {
+      // 图表配置
+      changeDefaultConfig('color', ['#00ffff'])
+      changeDefaultConfig('title', {
+        offset: [0, -40],
+        style: {
+          fill: '#a2ebff',
+          textAlign: 'center'
+        }
+      })
+      const xyOpts = {
+        nameTextStyle: {
+          fill: '#fff',
+          fontSize: 10
+        },
+        axisLabel: {
+          style: {
+            fill: '#fff'
+          }
+        },
+        axisLine: {
+          show: false
+        }
+      }
+      changeDefaultConfig('xAxis', xyOpts)
+      changeDefaultConfig('yAxis', xyOpts)
+      changeDefaultConfig('grid', {
+        right: 60,
+        bottom: 50,
+        top: 85,
+        left: 50
+      })
+      // 新用户注册量
+      const con1 = document.getElementById('con1')
+      const chart1 = new Charts(con1)
+      const option1 = {
+        title: {
+          text: '新用户注册量'
+        },
+        xAxis: {
+          name: '日期',
+          data: ['03-25', '03-26', '03-27', '03-28', '03-29', '03-30', '03-31']
+        },
+        yAxis: {
+          name: '用户',
+          data: 'value'
+        },
+        series: [
+          {
+            data: [120, 98, 100, 125, 110, 87, 160],
+            type: 'line',
+            smooth: true,
+            lineArea: {
+              show: true,
+              gradient: ['rgba(55, 162, 218, 0.5)', 'rgba(55, 162, 218, 0.9)']
+            }
+          }
+        ]
+      }
+      chart1.setOption(option1)
+      this.chart1 = chart1
+      // 分时投递量
+      const con2 = document.getElementById('con2')
+      const chart2 = new Charts(con2)
+      const option2 = {
+        title: {
+          text: '分时投递量'
+        },
+        legend: {
+          show: false
+        },
+        xAxis: {
+          name: '时间段',
+          data: ['08', '10', '12', '14', '16', '18', '20']
+        },
+        yAxis: {
+          name: 'kg',
+          data: 'value'
+        },
+        series: [
+          {
+            name: '系列A',
+            data: [1200, 2230, 1900, 2100, 3500, 4200, 3985],
+            type: 'line',
+            stack: 'a',
+            smooth: true,
+            lineArea: {
+              show: true,
+              gradient: ['rgba(55, 162, 218, 0.5)', 'rgba(55, 162, 218, 0.9)']
+            }
+          },
+          {
+            name: '系列B',
+            data: [1200, 2230, 1900, 2100, 3500, 4200, 3985],
+            type: 'line',
+            stack: 'a',
+            smooth: true,
+            lineArea: {
+              show: true,
+              gradient: ['rgba(55, 162, 218, 0.5)', 'rgba(55, 162, 218, 0.9)']
+            }
+          },
+          {
+            name: '系列C',
+            data: [1200, 2230, 1900, 2100, 3500, 4200, 3985],
+            type: 'line',
+            stack: 'a',
+            smooth: true,
+            lineArea: {
+              show: true,
+              gradient: ['rgba(55, 162, 218, 0.5)', 'rgba(55, 162, 218, 0.9)']
+            }
+          }
+        ]
+      }
+      chart2.setOption(option2)
+      this.chart2 = chart2
+      // 设备分布比例
+      const con3 = document.getElementById('con3')
+      const chart3 = new Charts(con3)
+      const option3 = {
+        title: {
+          text: '设备分布比例'
+        },
+        series: [
+          {
+            type: 'pie',
+            radius: '40%',
+            startAngle: -Math.PI / 8,
+            data: [
+              { name: '企业', value: 5 },
+              { name: '学校', value: 14 },
+              { name: '公共机构', value: 32 },
+              { name: '居民小区', value: 49 }
+            ],
+            insideLabel: {
+              show: true
+            }
+          }
+        ]
+      }
+      chart3.setOption(option3)
+      this.chart3 = chart3
+      // 网点投递量排名
+      const con4 = document.getElementById('con4')
+      const chart4 = new Charts(con4)
+      const option4 = {
+        title: {
+          text: '网点投递量排名'
+        },
+        xAxis: {
+          name: '网点',
+          data: ['科技路', '钟楼', '南门', '中登大厦', '海景国际', '十里锦绣', '绿地生态城']
+        },
+        yAxis: {
+          name: 'kg',
+          data: 'value'
+        },
+        series: [
+          {
+            data: [1200, 2230, 1900, 2100, 3500, 4200, 3985],
+            type: 'bar',
+            gradient: {
+              color: ['#37a2da', '#67e0e3']
+            }
+          }
+        ]
+      }
+      chart4.setOption(option4)
+      this.chart4 = chart4
+    }
+  },
+  mounted () {
+    this.initChart()
+    this.initMap()
+  }
+}
+</script>
+
+<style lang="less">
+  .dataView-content{
+    width: 100%;
+    height: 100%;
+    min-height: 600px;
+    background-image: url(../../assets/dataViewBg.png);
+    background-size: 100% 100%;
+    display: flex;
+    flex-direction: column;
+    .data-header{
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      > div{
+        height: 80px;
+        line-height: 80px;
+        &:first-child{
+          width: 40%;
+          color: #79ccff;
+          .border-box-content{
+            font-size: 30px;
+            text-align: center;
+          }
+        }
+        &:last-child{
+          width: 25%;
+          color: #0ed3ff;
+          .border-box-content{
+            font-size: 18px;
+            text-align: center;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            padding-left: 50px;
+            select{
+              background: #021931;
+              border: 1px solid #3e566d;
+              width: 35%;
+              padding: 2px 10px;
+              margin: 0 10px;
+              box-shadow: inset 0 0 2px #69b2ff;
+              border-radius: 6px;
+            }
+          }
+        }
+      }
+    }
+    .data-body{
+      flex-grow: 1;
+      display: flex;
+      .b-left,.b-right{
+        width: 25%;
+        display: flex;
+        padding: 5px;
+        flex-direction: column;
+        >div{
+          height: 50%;
+        }
+      }
+      .b-middle{
+        width: 50%;
+        padding: 5px;
+        display: flex;
+        flex-direction: column;
+        >div{
+          &:first-child{
+            height: 80%;
+          }
+          &:last-child{
+            height: 20%;
+            .total-block{
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              height: 100%;
+              > div{
+                width: 40%;
+              }
+              .total-label{
+                color: #fff;
+                text-align: center;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+</style>