a1140836302 2 年 前
コミット
cb6627740c
48 ファイル変更865 行追加608 行削除
  1. 17 0
      package-lock.json
  2. 1 0
      package.json
  3. 18 0
      src/api/log.js
  4. 1 1
      src/api/statistics.js
  5. 12 0
      src/icons/svg/kzpz.svg
  6. 12 0
      src/icons/svg/kzpz_active.svg
  7. 10 0
      src/icons/svg/rzgl.svg
  8. 13 0
      src/icons/svg/rzgl_active.svg
  9. 9 7
      src/layout/components/Header.vue
  10. 35 9
      src/layout/components/Navbar.vue
  11. 2 3
      src/layout/index.vue
  12. 3 1
      src/main.js
  13. 48 1
      src/router/index.js
  14. 17 2
      src/styles/element-ui.scss
  15. 1 1
      src/utils/request.js
  16. 13 0
      src/views/control-config/index.vue
  17. 0 49
      src/views/directive/clipboard/clipboard.js
  18. 0 13
      src/views/directive/clipboard/index.js
  19. 0 77
      src/views/directive/el-drag-dialog/drag.js
  20. 0 13
      src/views/directive/el-drag-dialog/index.js
  21. 0 41
      src/views/directive/el-table/adaptive.js
  22. 0 13
      src/views/directive/el-table/index.js
  23. 0 13
      src/views/directive/permission/index.js
  24. 0 31
      src/views/directive/permission/permission.js
  25. 0 91
      src/views/directive/sticky.js
  26. 0 13
      src/views/directive/waves/index.js
  27. 0 26
      src/views/directive/waves/waves.css
  28. 0 72
      src/views/directive/waves/waves.js
  29. 15 6
      src/views/equipment-monitoring/components/BatteryStatus.vue
  30. 3 2
      src/views/equipment-monitoring/components/StorageInfo.vue
  31. 24 20
      src/views/equipment-monitoring/components/SubTitle.vue
  32. 21 0
      src/views/equipment-monitoring/index.scss
  33. 61 37
      src/views/equipment-monitoring/index.vue
  34. 0 32
      src/views/error-log/index.vue
  35. 13 0
      src/views/manage-log/battery-charger.vue
  36. 13 0
      src/views/manage-log/bms.vue
  37. 13 0
      src/views/manage-log/change-record.vue
  38. 0 0
      src/views/manage-log/components/ErrorTestA.vue
  39. 0 0
      src/views/manage-log/components/ErrorTestB.vue
  40. 91 0
      src/views/manage-log/log.scss
  41. 326 0
      src/views/manage-log/robot.vue
  42. 5 0
      src/views/permission/cartype-manage/index.vue
  43. 17 9
      src/views/permission/directive.vue
  44. 13 5
      src/views/permission/page.vue
  45. 12 4
      src/views/permission/record-alarm/index.vue
  46. 5 5
      src/views/power-change-monitoring/index.vue
  47. 17 7
      src/views/statistical-analysis/index.vue
  48. 4 4
      vue.config.js

+ 17 - 0
package-lock.json

@@ -9,6 +9,7 @@
       "version": "4.4.0",
       "license": "MIT",
       "dependencies": {
+        "af-table-column": "^1.0.3",
         "axios": "0.18.1",
         "clipboard": "2.0.4",
         "codemirror": "5.45.0",
@@ -3600,6 +3601,14 @@
         "node": ">=0.8"
       }
     },
+    "node_modules/af-table-column": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/af-table-column/-/af-table-column-1.0.3.tgz",
+      "integrity": "sha512-zdI7MsmppAZemofr4zM7Kae7CGQGlyfnbTj6l0DgNDfRtzJs7ryiX7fbAq96MCRtt4EVcrZ+fX+rnpznrpB34Q==",
+      "dependencies": {
+        "vue": "^2.6.10"
+      }
+    },
     "node_modules/aggregate-error": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
@@ -25806,6 +25815,14 @@
         "printj": "~1.1.0"
       }
     },
+    "af-table-column": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/af-table-column/-/af-table-column-1.0.3.tgz",
+      "integrity": "sha512-zdI7MsmppAZemofr4zM7Kae7CGQGlyfnbTj6l0DgNDfRtzJs7ryiX7fbAq96MCRtt4EVcrZ+fX+rnpznrpB34Q==",
+      "requires": {
+        "vue": "^2.6.10"
+      }
+    },
     "aggregate-error": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",

+ 1 - 0
package.json

@@ -15,6 +15,7 @@
     "test:ci": "npm run lint && npm run test:unit"
   },
   "dependencies": {
+    "af-table-column": "^1.0.3",
     "axios": "0.18.1",
     "clipboard": "2.0.4",
     "codemirror": "5.45.0",

+ 18 - 0
src/api/log.js

@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+//日志数据字典
+export function logModel(data) {
+    return request({
+      url: '/plc/list',
+      method: 'post',
+      data
+    })
+}
+//机器人日志列表
+export function robotList(data) {
+    return request({
+      url: '/log/robotList',
+      method: 'post',
+      data
+    })
+}

+ 1 - 1
src/api/statistics.js

@@ -16,7 +16,7 @@ export function getAlarmType(data) {
   })
 }
 //安全运行天数
-export function safeDays(data) {
+export function getsafeDays(data) {
   return request({
     url: '/statistics/days',
     method: 'post',

+ 12 - 0
src/icons/svg/kzpz.svg

@@ -0,0 +1,12 @@
+<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="Frame" clip-path="url(#clip0_11_78901)">
+<path id="Vector" d="M9 16.625C12.935 16.625 16.125 13.435 16.125 9.5C16.125 5.56497 12.935 2.375 9 2.375C5.06497 2.375 1.875 5.56497 1.875 9.5C1.875 13.435 5.06497 16.625 9 16.625Z" stroke="#636C97" stroke-width="2"/>
+<path id="Vector_2" d="M13.502 9.7223V9.72229C13.502 8.63302 12.6189 7.75 11.5297 7.75H6.46956C5.38029 7.75 4.49726 8.63302 4.49726 9.72229V9.7223C4.49726 10.8116 5.38029 11.6946 6.46956 11.6946H11.5297C12.6189 11.6946 13.502 10.8116 13.502 9.7223Z" stroke="#636C97" stroke-width="2"/>
+<path id="Vector_3" d="M9.75195 9.81982C9.75195 10.8554 10.5914 11.6948 11.627 11.6948C12.6625 11.6948 13.502 10.8554 13.502 9.81982C13.502 8.78429 12.6625 7.94482 11.627 7.94482C10.5914 7.94482 9.75195 8.78429 9.75195 9.81982Z" stroke="#636C97" stroke-width="2"/>
+</g>
+<defs>
+<clipPath id="clip0_11_78901">
+<rect width="18" height="18" fill="white" transform="translate(0 0.5)"/>
+</clipPath>
+</defs>
+</svg>

+ 12 - 0
src/icons/svg/kzpz_active.svg

@@ -0,0 +1,12 @@
+<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="Frame" clip-path="url(#clip0_11_78915)">
+<path id="Vector" d="M9 16.625C12.935 16.625 16.125 13.435 16.125 9.5C16.125 5.56497 12.935 2.375 9 2.375C5.06497 2.375 1.875 5.56497 1.875 9.5C1.875 13.435 5.06497 16.625 9 16.625Z" stroke="#91FDB9" stroke-width="2"/>
+<path id="Vector_2" d="M13.502 9.7223V9.72229C13.502 8.63302 12.6189 7.75 11.5297 7.75H6.46956C5.38029 7.75 4.49726 8.63302 4.49726 9.72229V9.7223C4.49726 10.8116 5.38029 11.6946 6.46956 11.6946H11.5297C12.6189 11.6946 13.502 10.8116 13.502 9.7223Z" stroke="#91FDB9" stroke-width="2"/>
+<path id="Vector_3" d="M9.75195 9.81982C9.75195 10.8554 10.5914 11.6948 11.627 11.6948C12.6625 11.6948 13.502 10.8554 13.502 9.81982C13.502 8.78429 12.6625 7.94482 11.627 7.94482C10.5914 7.94482 9.75195 8.78429 9.75195 9.81982Z" stroke="#91FDB9" stroke-width="2"/>
+</g>
+<defs>
+<clipPath id="clip0_11_78915">
+<rect width="18" height="18" fill="white" transform="translate(0 0.5)"/>
+</clipPath>
+</defs>
+</svg>

+ 10 - 0
src/icons/svg/rzgl.svg

@@ -0,0 +1,10 @@
+<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="Group 3409">
+<g id="Frame">
+<path id="Vector" d="M15.375 4.75H4.875V17.5H15.375V4.75Z" stroke="#636C97" stroke-width="2" stroke-linejoin="round"/>
+<path id="Vector_2" d="M13.125 4.75V2.5H3C2.79289 2.5 2.625 2.66789 2.625 2.875V15.25H4.875" stroke="#636C97" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path id="Vector_3" d="M7.875 9.25H12.375" stroke="#636C97" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path id="Vector_4" d="M7.875 12.25H12.375" stroke="#636C97" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+</g>
+</svg>

+ 13 - 0
src/icons/svg/rzgl_active.svg

@@ -0,0 +1,13 @@
+<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="Frame" clip-path="url(#clip0_11_78895)">
+<path id="Vector" d="M15.375 4.25H4.875V17H15.375V4.25Z" stroke="#91FDB9" stroke-width="2" stroke-linejoin="round"/>
+<path id="Vector_2" d="M13.125 4.25V2H3C2.79289 2 2.625 2.16789 2.625 2.375V14.75H4.875" stroke="#91FDB9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path id="Vector_3" d="M7.875 8.75H12.375" stroke="#91FDB9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path id="Vector_4" d="M7.875 11.75H12.375" stroke="#91FDB9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+<defs>
+<clipPath id="clip0_11_78895">
+<rect width="18" height="18" fill="white" transform="translate(0 0.5)"/>
+</clipPath>
+</defs>
+</svg>

+ 9 - 7
src/layout/components/Header.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="permission">
-        <div v-for="(item,index) in permissionList" :key="index" :class="{active:item.name === $route.name}">
+        <div v-for="(item,index) in childrenList" :key="index" :class="{active:item.name === $route.name}">
             <router-link :to="item.path">
                 <span>{{item.meta.title}}</span>
             </router-link>
@@ -17,15 +17,9 @@ export default {
     name: 'Header',
     data(){
         return{
-            permissionList:[],
             isactive:true,
         }
     },
-    mounted() {
-        //获取站控管理子路由
-        this.permissionList = this.permission_routes[8].children.slice(0,6)
-        // console.log(this.$route)
-    },
     computed: {
         ...mapGetters(["sidebar", "name", "device", "permission_routes"]),
         cloudshow(){
@@ -34,6 +28,14 @@ export default {
             }else{
                 return false
             }
+        },
+        //获取子路由
+        childrenList(){
+            if(this.$route.matched[0].name === 'ManageLog'){
+                return this.permission_routes[9].children.slice(0,6)
+            }else{
+                return this.permission_routes[8].children.slice(0,6)
+            }
         }
     },
 }

+ 35 - 9
src/layout/components/Navbar.vue

@@ -3,16 +3,17 @@
     <div class="left-title">重卡换电智能站控系统</div>
     <div class="left-menu">
       <div v-for="(item, index) in PermissionList" :key="index">
-        <router-link :to="item.path">
-          <svg-icon :icon-class="index === 3 ? item.meta.icon : item.children[0].meta.icon"/>
-          <svg-icon :icon-class="index === 3 ? item.meta.icon+'_active' : item.children[0].meta.icon+'_active'" class="iconacive"/>
-          <span>{{index === 3 ? item.meta.title : item.children[0].meta.title}}</span>
+        <router-link :to="item.path" :class="{'routerlink':index === 3 || index === 4}">
+          <svg-icon :icon-class="index === 3 || index === 4 ? item.meta.icon : item.children[0].meta.icon"/>
+          <svg-icon :icon-class="index === 3 || index === 4 ? item.meta.icon+'_active' : item.children[0].meta.icon+'_active'" class="iconacive"/>
+          <span>{{index === 3 || index === 4 ? item.meta.title : item.children[0].meta.title}}</span>
+          <i class="el-submenu__icon-arrow el-icon-arrow-down" v-if="index === 3 || index === 4"></i>
         </router-link>
       </div>
     </div>
     
     <div class="date-time">
-      <div class="safedays">安全运营88天</div>
+      <div class="safedays">安全运营 {{days}} 天</div>
       <div class="time-value">
         {{ dateTime.hours }}:{{ dateTime.minutes }}:{{ dateTime.seconds }}
       </div>
@@ -46,7 +47,7 @@
 
 <script>
 import { mapGetters } from "vuex";
-
+import { getsafeDays } from "@/api/statistics";
 export default {
   components: {
     
@@ -63,6 +64,7 @@ export default {
         minutes: "",
         seconds: "",
       },
+      days:0,
     };
   },
   computed: {
@@ -71,12 +73,19 @@ export default {
   mounted() {
     setInterval(this.timer, 1000);
     this.menuList()
+    this.getSafeDay()
   },
   methods: {
+    //安全运行天数
+    getSafeDay(){
+      getsafeDays().then(res => {
+        this.days=res.data
+      })
+    },
     //菜单路由
     menuList(){
-      // console.log(this.permission_routes);
-      this.PermissionList = this.permission_routes.slice(5, 9);
+      //console.log(this.permission_routes);
+      this.PermissionList = this.permission_routes.slice(5, 11);
     },
     //当前时间
     timer() {
@@ -113,6 +122,13 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+.el-submenu__icon-arrow{
+  right: -18px;
+  top:40%;
+  font-size: 16px;
+  font-weight: bold;
+  transform: rotate(180deg);
+}
 .navbar {
   height: 65px;
   overflow: hidden;
@@ -143,6 +159,9 @@ export default {
     div{
       margin-right: 40px;
     }
+    .routerlink{
+      position: relative;
+    }
     .router-link-active{
       color: #91fdb9;
       position: relative;
@@ -152,8 +171,15 @@ export default {
       svg:first-child{
         display: none;
       }
+      .el-submenu__icon-arrow{
+        right: -20px !important;
+        position: absolute;
+        transform: rotate(360deg);
+        color: #91fdb9;
+        top:40%
+      }
     }
-
+    
     span{
       font-size: 20px;
       font-weight: 600;

+ 2 - 3
src/layout/index.vue

@@ -2,7 +2,7 @@
   <div class="app-wrapper">
     <navbar />
     <!-- <Sidebar /> -->
-    <div :class="{hasheaderView:$route.matched[0].name === 'Permission'}">
+    <div :class="{hasheaderView:$route.matched[0].name === 'Permission'|| $route.matched[0].name === 'ManageLog'}">
       <Header v-if="getChildrenRouter"></Header>
       <app-main />
     </div>
@@ -12,7 +12,6 @@
 <script>
 import { AppMain, Navbar } from './components'
 import Header from './components/Header'
-import { mapState } from 'vuex'
 
 export default {
   name: 'Layout',
@@ -39,7 +38,7 @@ export default {
     // }),
     //是否显示子路由
     getChildrenRouter(){
-      if(this.$route.matched[0].name === 'Permission' && this.$route.name !== 'RolePermission' && this.$route.name !== 'UpdatePassword'){
+      if((this.$route.matched[0].name === 'Permission' || this.$route.matched[0].name === 'ManageLog') && this.$route.name !== 'RolePermission' && this.$route.name !== 'UpdatePassword'){
         return true;
       }else{
         return false;

+ 3 - 1
src/main.js

@@ -13,11 +13,13 @@ import './utils/error-log' // error log
 import * as filters from './filters' // global filters
 import * as echarts from 'echarts'
 import moment from "moment"
+//表格宽度自适应
+import AFTableColumn from 'af-table-column'
 
 Vue.use(Element, {
   size: Cookies.get('size') || 'medium', // set element-ui default size
 })
-
+Vue.use(AFTableColumn)
 // register global utility filters
 Object.keys(filters).forEach(key => {
   Vue.filter(key, filters[key])

+ 48 - 1
src/router/index.js

@@ -145,7 +145,54 @@ export const asyncRoutes = [
       }
     ]
   },
-
+  {
+    path: '/manage-log',
+    component: Layout,
+    redirect: '/manage-log/robot',
+    name: 'ManageLog',
+    meta: {
+      title: '日志管理',
+      icon: 'rzgl'
+    },
+    children: [
+      {
+        path: 'robot',
+        component: () => import('@/views/manage-log/robot'),
+        name: 'Robot',
+        meta: { title: '机器人' }
+      },
+      {
+        path: 'battery-charger',
+        component: () => import('@/views/manage-log/battery-charger'),
+        name: 'BatteryCharger',
+        meta: { title: '充电机' }
+      },
+      {
+        path: 'bms',
+        component: () => import('@/views/manage-log/bms'),
+        name: 'Bms',
+        meta: { title: 'BMS' }
+      },
+      {
+        path: 'change-record',
+        component: () => import('@/views/manage-log/change-record'),
+        name: 'ChangeRecord',
+        meta: { title: '换电记录' }
+      }
+    ]
+  },
+  {
+    path: '/control-config',
+    component: Layout,
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/control-config/index'),
+        name: 'ControlConfig',
+        meta: { title: '控制配置', icon: 'kzpz', }
+      }
+    ]
+  },
   /** when your routing map is too long, you can split it into small modules **/
 
   // 404 page must be placed at the end !!!

+ 17 - 2
src/styles/element-ui.scss

@@ -99,6 +99,17 @@
   background-color: #111827;
   color: #fff;
   border: 1px solid #263042;
+  .el-input__inner:focus,.el-input__inner:hover{
+    border-color:none;
+  }
+}
+.el-date-range-picker__editor 
+{
+  .el-input__inner{
+    background-color: #fff;
+    border-color: #C0C4CC;
+    color: #606266;
+  }
 }
 .charge-tools{
   .el-input--medium .el-input__inner{
@@ -123,7 +134,9 @@
 .el-select-dropdown__item:hover,.el-select-dropdown__item.selected{
   color:black;
 }
-
+.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{
+  color: rgb(132, 146, 166);
+}
 /*表格样式修改*/ 
 .el-table{
   color: #e1e2e4;
@@ -138,10 +151,12 @@
     border-bottom: #2f3c86 solid 1px;
   }
 }
-
 .el-table::before {
   display: none;
 }
+.el-table__fixed-body-wrapper{
+  height: calc(100% - 65px) !important;
+}
 .el-table tr{
   background: #111827;
   height:56px;

+ 1 - 1
src/utils/request.js

@@ -58,7 +58,7 @@ service.interceptors.response.use(
       })
     } else {
       return res
-    }
+    }
   },
 
   error => {

+ 13 - 0
src/views/control-config/index.vue

@@ -0,0 +1,13 @@
+<template>
+  
+</template>
+
+<script>
+export default {
+    name:'ControlConfig'
+}
+</script>
+
+<style>
+
+</style>

+ 0 - 49
src/views/directive/clipboard/clipboard.js

@@ -1,49 +0,0 @@
-// Inspired by https://github.com/Inndy/vue-clipboard2
-const Clipboard = require('clipboard')
-if (!Clipboard) {
-  throw new Error('you should npm install `clipboard` --save at first ')
-}
-
-export default {
-  bind(el, binding) {
-    if (binding.arg === 'success') {
-      el._v_clipboard_success = binding.value
-    } else if (binding.arg === 'error') {
-      el._v_clipboard_error = binding.value
-    } else {
-      const clipboard = new Clipboard(el, {
-        text() { return binding.value },
-        action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
-      })
-      clipboard.on('success', e => {
-        const callback = el._v_clipboard_success
-        callback && callback(e) // eslint-disable-line
-      })
-      clipboard.on('error', e => {
-        const callback = el._v_clipboard_error
-        callback && callback(e) // eslint-disable-line
-      })
-      el._v_clipboard = clipboard
-    }
-  },
-  update(el, binding) {
-    if (binding.arg === 'success') {
-      el._v_clipboard_success = binding.value
-    } else if (binding.arg === 'error') {
-      el._v_clipboard_error = binding.value
-    } else {
-      el._v_clipboard.text = function() { return binding.value }
-      el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
-    }
-  },
-  unbind(el, binding) {
-    if (binding.arg === 'success') {
-      delete el._v_clipboard_success
-    } else if (binding.arg === 'error') {
-      delete el._v_clipboard_error
-    } else {
-      el._v_clipboard.destroy()
-      delete el._v_clipboard
-    }
-  }
-}

+ 0 - 13
src/views/directive/clipboard/index.js

@@ -1,13 +0,0 @@
-import Clipboard from './clipboard'
-
-const install = function(Vue) {
-  Vue.directive('Clipboard', Clipboard)
-}
-
-if (window.Vue) {
-  window.clipboard = Clipboard
-  Vue.use(install); // eslint-disable-line
-}
-
-Clipboard.install = install
-export default Clipboard

+ 0 - 77
src/views/directive/el-drag-dialog/drag.js

@@ -1,77 +0,0 @@
-export default {
-  bind(el, binding, vnode) {
-    const dialogHeaderEl = el.querySelector('.el-dialog__header')
-    const dragDom = el.querySelector('.el-dialog')
-    dialogHeaderEl.style.cssText += ';cursor:move;'
-    dragDom.style.cssText += ';top:0px;'
-
-    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
-    const getStyle = (function() {
-      if (window.document.currentStyle) {
-        return (dom, attr) => dom.currentStyle[attr]
-      } else {
-        return (dom, attr) => getComputedStyle(dom, false)[attr]
-      }
-    })()
-
-    dialogHeaderEl.onmousedown = (e) => {
-      // 鼠标按下,计算当前元素距离可视区的距离
-      const disX = e.clientX - dialogHeaderEl.offsetLeft
-      const disY = e.clientY - dialogHeaderEl.offsetTop
-
-      const dragDomWidth = dragDom.offsetWidth
-      const dragDomHeight = dragDom.offsetHeight
-
-      const screenWidth = document.body.clientWidth
-      const screenHeight = document.body.clientHeight
-
-      const minDragDomLeft = dragDom.offsetLeft
-      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
-
-      const minDragDomTop = dragDom.offsetTop
-      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
-
-      // 获取到的值带px 正则匹配替换
-      let styL = getStyle(dragDom, 'left')
-      let styT = getStyle(dragDom, 'top')
-
-      if (styL.includes('%')) {
-        styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
-        styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
-      } else {
-        styL = +styL.replace(/\px/g, '')
-        styT = +styT.replace(/\px/g, '')
-      }
-
-      document.onmousemove = function(e) {
-        // 通过事件委托,计算移动的距离
-        let left = e.clientX - disX
-        let top = e.clientY - disY
-
-        // 边界处理
-        if (-(left) > minDragDomLeft) {
-          left = -minDragDomLeft
-        } else if (left > maxDragDomLeft) {
-          left = maxDragDomLeft
-        }
-
-        if (-(top) > minDragDomTop) {
-          top = -minDragDomTop
-        } else if (top > maxDragDomTop) {
-          top = maxDragDomTop
-        }
-
-        // 移动当前元素
-        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
-
-        // emit onDrag event
-        vnode.child.$emit('dragDialog')
-      }
-
-      document.onmouseup = function(e) {
-        document.onmousemove = null
-        document.onmouseup = null
-      }
-    }
-  }
-}

+ 0 - 13
src/views/directive/el-drag-dialog/index.js

@@ -1,13 +0,0 @@
-import drag from './drag'
-
-const install = function(Vue) {
-  Vue.directive('el-drag-dialog', drag)
-}
-
-if (window.Vue) {
-  window['el-drag-dialog'] = drag
-  Vue.use(install); // eslint-disable-line
-}
-
-drag.install = install
-export default drag

+ 0 - 41
src/views/directive/el-table/adaptive.js

@@ -1,41 +0,0 @@
-import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
-
-/**
- * How to use
- * <el-table height="100px" v-el-height-adaptive-table="{bottomOffset: 30}">...</el-table>
- * el-table height is must be set
- * bottomOffset: 30(default)   // The height of the table from the bottom of the page.
- */
-
-const doResize = (el, binding, vnode) => {
-  const { componentInstance: $table } = vnode
-
-  const { value } = binding
-
-  if (!$table.height) {
-    throw new Error(`el-$table must set the height. Such as height='100px'`)
-  }
-  const bottomOffset = (value && value.bottomOffset) || 30
-
-  if (!$table) return
-
-  const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
-  $table.layout.setHeight(height)
-  $table.doLayout()
-}
-
-export default {
-  bind(el, binding, vnode) {
-    el.resizeListener = () => {
-      doResize(el, binding, vnode)
-    }
-    // parameter 1 is must be "Element" type
-    addResizeListener(window.document.body, el.resizeListener)
-  },
-  inserted(el, binding, vnode) {
-    doResize(el, binding, vnode)
-  },
-  unbind(el) {
-    removeResizeListener(window.document.body, el.resizeListener)
-  }
-}

+ 0 - 13
src/views/directive/el-table/index.js

@@ -1,13 +0,0 @@
-import adaptive from './adaptive'
-
-const install = function(Vue) {
-  Vue.directive('el-height-adaptive-table', adaptive)
-}
-
-if (window.Vue) {
-  window['el-height-adaptive-table'] = adaptive
-  Vue.use(install); // eslint-disable-line
-}
-
-adaptive.install = install
-export default adaptive

+ 0 - 13
src/views/directive/permission/index.js

@@ -1,13 +0,0 @@
-import permission from './permission'
-
-const install = function(Vue) {
-  Vue.directive('permission', permission)
-}
-
-if (window.Vue) {
-  window['permission'] = permission
-  Vue.use(install); // eslint-disable-line
-}
-
-permission.install = install
-export default permission

+ 0 - 31
src/views/directive/permission/permission.js

@@ -1,31 +0,0 @@
-import store from '@/store'
-
-function checkPermission(el, binding) {
-  const { value } = binding
-  const roles = store.getters && store.getters.roles
-
-  if (value && value instanceof Array) {
-    if (value.length > 0) {
-      const permissionRoles = value
-
-      const hasPermission = roles.some(role => {
-        return permissionRoles.includes(role)
-      })
-
-      if (!hasPermission) {
-        el.parentNode && el.parentNode.removeChild(el)
-      }
-    }
-  } else {
-    throw new Error(`need roles! Like v-permission="['admin','editor']"`)
-  }
-}
-
-export default {
-  inserted(el, binding) {
-    checkPermission(el, binding)
-  },
-  update(el, binding) {
-    checkPermission(el, binding)
-  }
-}

+ 0 - 91
src/views/directive/sticky.js

@@ -1,91 +0,0 @@
-const vueSticky = {}
-let listenAction
-vueSticky.install = Vue => {
-  Vue.directive('sticky', {
-    inserted(el, binding) {
-      const params = binding.value || {}
-      const stickyTop = params.stickyTop || 0
-      const zIndex = params.zIndex || 1000
-      const elStyle = el.style
-
-      elStyle.position = '-webkit-sticky'
-      elStyle.position = 'sticky'
-      // if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
-      // if (~elStyle.position.indexOf('sticky')) {
-      //     elStyle.top = `${stickyTop}px`;
-      //     elStyle.zIndex = zIndex;
-      //     return
-      // }
-      const elHeight = el.getBoundingClientRect().height
-      const elWidth = el.getBoundingClientRect().width
-      elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
-
-      const parentElm = el.parentNode || document.documentElement
-      const placeholder = document.createElement('div')
-      placeholder.style.display = 'none'
-      placeholder.style.width = `${elWidth}px`
-      placeholder.style.height = `${elHeight}px`
-      parentElm.insertBefore(placeholder, el)
-
-      let active = false
-
-      const getScroll = (target, top) => {
-        const prop = top ? 'pageYOffset' : 'pageXOffset'
-        const method = top ? 'scrollTop' : 'scrollLeft'
-        let ret = target[prop]
-        if (typeof ret !== 'number') {
-          ret = window.document.documentElement[method]
-        }
-        return ret
-      }
-
-      const sticky = () => {
-        if (active) {
-          return
-        }
-        if (!elStyle.height) {
-          elStyle.height = `${el.offsetHeight}px`
-        }
-
-        elStyle.position = 'fixed'
-        elStyle.width = `${elWidth}px`
-        placeholder.style.display = 'inline-block'
-        active = true
-      }
-
-      const reset = () => {
-        if (!active) {
-          return
-        }
-
-        elStyle.position = ''
-        placeholder.style.display = 'none'
-        active = false
-      }
-
-      const check = () => {
-        const scrollTop = getScroll(window, true)
-        const offsetTop = el.getBoundingClientRect().top
-        if (offsetTop < stickyTop) {
-          sticky()
-        } else {
-          if (scrollTop < elHeight + stickyTop) {
-            reset()
-          }
-        }
-      }
-      listenAction = () => {
-        check()
-      }
-
-      window.addEventListener('scroll', listenAction)
-    },
-
-    unbind() {
-      window.removeEventListener('scroll', listenAction)
-    }
-  })
-}
-
-export default vueSticky
-

+ 0 - 13
src/views/directive/waves/index.js

@@ -1,13 +0,0 @@
-import waves from './waves'
-
-const install = function(Vue) {
-  Vue.directive('waves', waves)
-}
-
-if (window.Vue) {
-  window.waves = waves
-  Vue.use(install); // eslint-disable-line
-}
-
-waves.install = install
-export default waves

+ 0 - 26
src/views/directive/waves/waves.css

@@ -1,26 +0,0 @@
-.waves-ripple {
-    position: absolute;
-    border-radius: 100%;
-    background-color: rgba(0, 0, 0, 0.15);
-    background-clip: padding-box;
-    pointer-events: none;
-    -webkit-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-    -webkit-transform: scale(0);
-    -ms-transform: scale(0);
-    transform: scale(0);
-    opacity: 1;
-}
-
-.waves-ripple.z-active {
-    opacity: 0;
-    -webkit-transform: scale(2);
-    -ms-transform: scale(2);
-    transform: scale(2);
-    -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
-    transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
-    transition: opacity 1.2s ease-out, transform 0.6s ease-out;
-    transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
-}

+ 0 - 72
src/views/directive/waves/waves.js

@@ -1,72 +0,0 @@
-import './waves.css'
-
-const context = '@@wavesContext'
-
-function handleClick(el, binding) {
-  function handle(e) {
-    const customOpts = Object.assign({}, binding.value)
-    const opts = Object.assign({
-      ele: el, // 波纹作用元素
-      type: 'hit', // hit 点击位置扩散 center中心点扩展
-      color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
-    },
-    customOpts
-    )
-    const target = opts.ele
-    if (target) {
-      target.style.position = 'relative'
-      target.style.overflow = 'hidden'
-      const rect = target.getBoundingClientRect()
-      let ripple = target.querySelector('.waves-ripple')
-      if (!ripple) {
-        ripple = document.createElement('span')
-        ripple.className = 'waves-ripple'
-        ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
-        target.appendChild(ripple)
-      } else {
-        ripple.className = 'waves-ripple'
-      }
-      switch (opts.type) {
-        case 'center':
-          ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px'
-          ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px'
-          break
-        default:
-          ripple.style.top =
-            (e.pageY - rect.top - ripple.offsetHeight / 2 - document.documentElement.scrollTop ||
-              document.body.scrollTop) + 'px'
-          ripple.style.left =
-            (e.pageX - rect.left - ripple.offsetWidth / 2 - document.documentElement.scrollLeft ||
-              document.body.scrollLeft) + 'px'
-      }
-      ripple.style.backgroundColor = opts.color
-      ripple.className = 'waves-ripple z-active'
-      return false
-    }
-  }
-
-  if (!el[context]) {
-    el[context] = {
-      removeHandle: handle
-    }
-  } else {
-    el[context].removeHandle = handle
-  }
-
-  return handle
-}
-
-export default {
-  bind(el, binding) {
-    el.addEventListener('click', handleClick(el, binding), false)
-  },
-  update(el, binding) {
-    el.removeEventListener('click', el[context].removeHandle, false)
-    el.addEventListener('click', handleClick(el, binding), false)
-  },
-  unbind(el) {
-    el.removeEventListener('click', el[context].removeHandle, false)
-    el[context] = null
-    delete el[context]
-  }
-}

+ 15 - 6
src/views/equipment-monitoring/components/BatteryStatus.vue

@@ -8,17 +8,17 @@
             <span>电池编号</span><span>{{sn}}</span>
         </div>
         <div class="percent">
-            <div><span>{{5}}</span></div>
+            <div><span>{{soc}}</span></div>
             <div>%</div>
         </div>
         <div class="line"><span></span><span></span></div>
         <div class="power">
             <div class="power-percent">
-                <span v-for="item in 100" :key="item"></span>
+                <span v-for="item in 100" :key="item" :style="{'backgroundColor': soc >= item ? setcolor :''}"></span>
             </div>
             <div class="power-text">
                 <span>电池电量</span>
-                <span>预计<em>{{chgEstimatedTime}}</em>后充满</span>
+                <span>预计 <em>{{chgEstimatedTime}}</em> 分钟后充满</span>
             </div>
         </div>
     </div>
@@ -27,7 +27,7 @@
 <script>
 export default {
     name: "BatteryStatus",
-    props:['storeCode','comState','sn','chgEstimatedTime'],
+    props:['storeCode','comState','sn','chgEstimatedTime','soc'],
     computed:{
         statustext(){
             if(this.comState===1){
@@ -35,6 +35,15 @@ export default {
             }else{
                 return ['通讯异常','warning']
             }
+        },
+        setcolor(){
+            if(this.soc<=30 && this.soc > 0){
+                return '#ce4545'
+            }else if(this.soc > 30 && this.soc <= 70){
+                return '#f8dc4b'
+            }else if(this.soc > 70){
+                return '#44ab41'
+            }
         }
     }
 };
@@ -77,8 +86,8 @@ export default {
 
     :last-child {
         color: white;
-        padding-left: 16px;
-        font-size: 16px;
+        padding-left: 10px;
+        font-size: 14px;
         font-weight: 600;
     }
 }

+ 3 - 2
src/views/equipment-monitoring/components/StorageInfo.vue

@@ -5,6 +5,7 @@
             :storeCode="storeCode"
             :comState="comState"
             :sn="sn"
+            :soc="soc"
             :chgEstimatedTime="chgEstimatedTime"
             ></BatteryStatus>
             <div class="battery-info">
@@ -46,7 +47,7 @@ import BatteryStatus from "./BatteryStatus.vue";
 import BatteryCharger from "./BatteryCharger.vue"
 export default {
     name:"StorageInfo",
-    props:['storeCode','comState','sn','chgEstimatedTime','current','voltage','minTemperature','maxTemperature','maxCellVoltage','minCellVoltage',
+    props:['storeCode','comState','sn','soc','chgEstimatedTime','current','voltage','minTemperature','maxTemperature','maxCellVoltage','minCellVoltage',
         'soh','storeState','chargerInfoVo'],
     components: {
         BatteryInfo,
@@ -82,7 +83,7 @@ export default {
         min-height: 100%;
         margin-right: 22px;
         .container{
-            padding: 2vh 25px 0vh 25px;
+            padding: 1.3vh 25px 0.5vh 25px;
             color: #404a63;
             font-size: 15px;
             

+ 24 - 20
src/views/equipment-monitoring/components/SubTitle.vue

@@ -18,21 +18,21 @@
     <div class="rolemanage">
       <el-dialog :title="dialogType === 'check' ? '检修换仓' : '消防换仓'" :visible.sync="dialogStoreVisible">
         <el-form ref="StoreForm" :model="StoreForm" :rules="rules">
-          <el-form-item
-            :label="dialogType === 'check' ? '检修仓:' : '故障仓:'"
+          <el-form-item
+            :label="dialogType === 'check' ? '检修仓:' : '故障仓:'"
             :label-width="formLabelWidth"
-            prop="currentStore"
+            prop="currentStore"
           >
-            <el-select
-              v-model="StoreForm.currentStore"
+            <el-select
+              v-model="StoreForm.currentStore"
               clearable
-              :placeholder="dialogType === 'check' ? '请选择检修仓' : '请选择故障仓'"
+              :placeholder="dialogType === 'check' ? '请选择检修仓' : '请选择故障仓'"
             >
               <el-option
                 v-for="item in StoreCodeList"
                 :key="item.id"
-                :label="item+'仓'"
-                :value="item"
+                :label="item+'仓'"
+                :value="item"
               />
             </el-select>
           </el-form-item>
@@ -41,8 +41,8 @@
               <el-option
                 v-for="item in StoreCodeList"
                 :key="item.id"
-                :label="item+'仓'"
-                :value="item"
+                :label="item+'仓'"
+                :value="item"
               />
             </el-select>
           </el-form-item>
@@ -94,7 +94,8 @@ export default {
         ]
       },
       formLabelWidth: '120px',
-      StoreCodeList: null
+      StoreCodeList: null,
+      loading:false,
     }
   },
   mounted() {
@@ -109,6 +110,7 @@ export default {
     },
     // 手动发起换电
     changePower() {
+      this.loading=true
       this.$confirm('请确认站控系统手动发起换电?', '开始换电', {
         confirmButtonText: '确认',
         cancelButtonText: '取消',
@@ -116,11 +118,10 @@ export default {
       })
         .then(async() => {
           const res = await beginSwap()
-          console.log(res)
-          this.$message({
-            type: 'success',
-            message: '操作成功!'
-          })
+          // this.$message({
+          //   type: 'success',
+          //   message: '操作成功!'
+          // })
         })
         .catch(err => { console.error(err) })
     },
@@ -154,10 +155,11 @@ export default {
       this.$refs[formName].validate(valid => {
         if (valid) {
           const params = this.StoreForm
+          this.loading=true;
           // 检修换仓
           if (this.dialogType === 'check') {
             mtStore(params).then(res => {
-              if (res.code === 0) {
+              if (res) {
                 this.loading = false
                 this.dialogStoreVisible = false
                 this.$message({
@@ -167,14 +169,15 @@ export default {
                 this.resetForm()
               } else {
                 this.loading = false
-                return this.$message.error(res.msg)
+                this.dialogStoreVisible = false
+                this.resetForm()
               }
             })
           }
           // 消防换仓
           else {
             fireStore(params).then(res => {
-              if (res.code === 0) {
+              if (res) {
                 this.loading = false
                 this.dialogStoreVisible = false
                 this.$message({
@@ -184,7 +187,8 @@ export default {
                 this.resetForm()
               } else {
                 this.loading = false
-                return this.$message.error(res.msg)
+                this.dialogStoreVisible = false
+                this.resetForm()
               }
             })
           }

+ 21 - 0
src/views/equipment-monitoring/index.scss

@@ -170,10 +170,31 @@
         .storage-bottom {
             display: flex;
             padding: 20px;
+            overflow: hidden;
             .storagebox{
                 width: 100%;
                 display: flex;
             }
         }
+        .storage-page{
+            text-align: right;
+            color: #fff;
+            padding-right: 30px;
+            font-size: 13px;
+            padding-bottom: 10px;
+            span{
+                padding: 0 6px;
+            }
+            a{
+                margin-right: 10px;
+            }
+            a.active{
+                color: #1890ff;
+                border: #1890ff solid 1px;
+                background-color: #111827;
+                padding:0 4px;
+                text-align: center;
+            }
+        }
     }
 }

+ 61 - 37
src/views/equipment-monitoring/index.vue

@@ -10,42 +10,42 @@
               <span>机器人状态</span>
               <div class="status">
                 <div class="status-list">
-                  <img
-                    :src="robotInfoVo.robotState === 1 ? require('./assets/status1-active.png') : require('./assets/status1.png')"
-                    width="58"
+                  <img
+                    :src="robotInfoVo.robotState === 2 ? require('./assets/status1-active.png') : require('./assets/status1.png')"
+                    width="58"
                   >
                   <div class="staus-info">
-                    <div class="infoimg"><img
-                      v-if="robotInfoVo.robotState === 1"
-                      src="./assets/success.png"
+                    <div class="infoimg"><img
+                      v-if="robotInfoVo.robotState === 2"
+                      src="./assets/success.png"
                     ></div>
-                    <div class="infotext" :class="{ active: robotInfoVo.robotState === 1 }">运行</div>
+                    <div class="infotext" :class="{ active: robotInfoVo.robotState === 2 }">运行</div>
                   </div>
                 </div>
                 <div class="status-list">
-                  <img
-                    :src="robotInfoVo.robotState === 2 ? require('./assets/status2-active.png') : require('./assets/status2.png')"
-                    width="58"
+                  <img
+                    :src="robotInfoVo.robotState === 1 ? require('./assets/status2-active.png') : require('./assets/status2.png')"
+                    width="58"
                   >
                   <div class="staus-info">
-                    <div class="infoimg"><img
-                      v-if="robotInfoVo.robotState === 2"
-                      src="./assets/warn.png"
+                    <div class="infoimg"><img
+                      v-if="robotInfoVo.robotState === 1"
+                      src="./assets/warn.png"
                     ></div>
-                    <div class="infotext" :class="{ active: robotInfoVo.robotState === 2 }">待机</div>
+                    <div class="infotext" :class="{ active: robotInfoVo.robotState === 1 }">待机</div>
                   </div>
                 </div>
                 <div class="status-list">
-                  <img
-                    :src="robotInfoVo.robotState === 3 ? require('./assets/status3-active.png') : require('./assets/status3.png')"
-                    width="58"
+                  <img
+                    :src="robotInfoVo.robotState === 4 ? require('./assets/status3-active.png') : require('./assets/status3.png')"
+                    width="58"
                   >
                   <div class="staus-info">
-                    <div class="infoimg"><img
-                      v-if="robotInfoVo.robotState === 3"
-                      src="./assets/danger.png"
+                    <div class="infoimg"><img
+                      v-if="robotInfoVo.robotState === 4"
+                      src="./assets/danger.png"
                     ></div>
-                    <div class="infotext" :class="{ active: robotInfoVo.robotState === 3 }">故障</div>
+                    <div class="infotext" :class="{ active: robotInfoVo.robotState === 4 }">故障</div>
                   </div>
                 </div>
               </div>
@@ -56,7 +56,7 @@
                 <div class="signal-status-list">
                   <div class="signal-icon">
                     <img src="./assets/info1.png" width="58"><img
-                      :src="robotInfoVo.plcState ? require('./assets/signal1.png') : require('./assets/signal2.png')"
+                      :src="robotInfoVo.plcState ? require('./assets/signal1.png') : require('./assets/signal2.png')"
                     >
                   </div>
                   <div class="signal-text">PLC通信</div>
@@ -64,7 +64,7 @@
                 <div class="signal-status-list">
                   <div class="signal-icon">
                     <img src="./assets/info2.png" width="58"><img
-                      :src="robotInfoVo.liftingServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
+                      :src="robotInfoVo.liftingServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
                     >
                   </div>
                   <div class="signal-text">举升伺服</div>
@@ -72,7 +72,7 @@
                 <div class="signal-status-list">
                   <div class="signal-icon">
                     <img src="./assets/info3.png" width="58"><img
-                      :src="robotInfoVo.rotaryServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
+                      :src="robotInfoVo.rotaryServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
                     >
                   </div>
                   <div class="signal-text">旋转伺服</div>
@@ -80,7 +80,7 @@
                 <div class="signal-status-list">
                   <div class="signal-icon">
                     <img src="./assets/info4.png" width="58"><img
-                      :src="robotInfoVo.palletServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
+                      :src="robotInfoVo.palletServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
                     >
                   </div>
                   <div class="signal-text">货叉伺服</div>
@@ -88,7 +88,7 @@
                 <div class="signal-status-list">
                   <div class="signal-icon">
                     <img src="./assets/info5.png" width="58"><img
-                      :src="robotInfoVo.walkServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
+                      :src="robotInfoVo.walkServo ? require('./assets/signal1.png') : require('./assets/signal2.png')"
                     >
                   </div>
                   <div class="signal-text">行走伺服</div>
@@ -120,15 +120,16 @@
     <div class="box-second">
       <sub-title name="储充信息" statement="STORAGE AND CHARGING INFORMATION" num="8" step="1" />
       <div class="storage-bottom" :style="{ height: screenHeight }">
-        <el-carousel indicator-position="outside" :height="height" :autoplay="false">
-          <el-carousel-item>
+        <el-carousel indicator-position="none" arrow="never" :height="height" :autoplay="false" ref="chargerPages">
+          <el-carousel-item :key="1" :name="pageName[0]">
             <div class="storagebox">
               <StorageInfo
-                v-for="(item,index) in storeInfoListFirst"
+                v-for="(item,index) in storeInfoListFirst"
                 :key="index"
                 :store-code="item.storeCode"
                 :com-state="item.comState"
                 :sn="item.sn"
+                :soc="item.soc"
                 :chg-estimated-time="item.chargerInfoVo.chgEstimatedTime"
                 :current="item.current"
                 :voltage="item.voltage"
@@ -142,14 +143,15 @@
               />
             </div>
           </el-carousel-item>
-          <el-carousel-item>
+          <el-carousel-item :key="2" :name="pageName[1]">
             <div class="storagebox">
               <StorageInfo
-                v-for="(item,index) in storeInfoListSecond"
+                v-for="(item,index) in storeInfoListSecond"
                 :key="index"
                 :store-code="item.storeCode"
                 :com-state="item.comState"
                 :sn="item.sn"
+                :soc="item.soc"
                 :chg-estimated-time="item.chargerInfoVo.chgEstimatedTime"
                 :current="item.current"
                 :voltage="item.voltage"
@@ -165,6 +167,13 @@
           </el-carousel-item>
         </el-carousel>
       </div>
+      <div class="storage-page">
+          <a @click="clickPrev()">&lt;</a>
+          <a @click="clickPage(pageName[0])" :class="{'active':!Isactive}">1</a>
+          <span>/</span>
+          <a @click="clickPage(pageName[1])" :class="{'active':Isactive}">2</a>
+          <a @click="clickNext()">&gt;</a>
+      </div>
     </div>
   </div>
 </template>
@@ -188,7 +197,9 @@ export default {
       screenHeight: null,
       robotInfoVo: {},
       storeInfoListFirst: [], // 第一屏储充信息
-      storeInfoListSecond: [] // 第二屏储充信息
+      storeInfoListSecond: [], // 第二屏储充信
+      pageName:['pfirst','psecond'],
+      Isactive: false,
     }
   },
   mounted() {
@@ -210,6 +221,19 @@ export default {
     this.clearTimerList()
   },
   methods: {
+    //走马灯分页
+    clickPage(pageId){
+        this.$refs.chargerPages.setActiveItem(pageId)
+        this.Isactive=!this.Isactive
+    },
+    clickPrev(){
+        this.$refs.chargerPages.prev()
+        this.Isactive=!this.Isactive
+    },
+    clickNext(){
+        this.$refs.chargerPages.next()
+        this.Isactive=!this.Isactive
+    },
     // 清除定时器列表
     clearTimerList() {
       if (this.wsTimer) {
@@ -220,9 +244,9 @@ export default {
     onLoadHeight() {
       this.$nextTick(() => {
         if (document.body.clientHeight >= 1080) {
-          this.screenHeight = '65vh'
+          this.screenHeight = '63vh'
         } else {
-          this.screenHeight = '72vh'
+          this.screenHeight = '70vh'
         }
       })
     },
@@ -231,9 +255,9 @@ export default {
       window.onresize = () => {
         return (() => {
           if (document.body.clientHeight >= 1080) {
-            this.screenHeight = '65vh'
+            this.screenHeight = '63vh'
           } else {
-            this.screenHeight = '72vh'
+            this.screenHeight = '70vh'
           }
         })()
       }
@@ -285,4 +309,4 @@ export default {
         display: none;
     }
 }
-</style>
+</style>

+ 0 - 32
src/views/error-log/index.vue

@@ -1,32 +0,0 @@
-<template>
-  <div class="errPage-container">
-    <ErrorA />
-    <ErrorB />
-    <h3>Please click the bug icon in the upper right corner</h3>
-    <aside>
-      Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.
-      <a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/error.html">
-        Document introduction
-      </a>
-    </aside>
-    <a href="#">
-      <img src="https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif">
-    </a>
-  </div>
-</template>
-
-<script>
-import ErrorA from './components/ErrorTestA'
-import ErrorB from './components/ErrorTestB'
-
-export default {
-  name: 'ErrorLog',
-  components: { ErrorA, ErrorB }
-}
-</script>
-
-<style scoped>
-  .errPage-container {
-    padding: 30px;
-  }
-</style>

+ 13 - 0
src/views/manage-log/battery-charger.vue

@@ -0,0 +1,13 @@
+<template>
+  
+</template>
+
+<script>
+export default {
+    name: 'BatteryCharger',
+}
+</script>
+
+<style>
+
+</style>

+ 13 - 0
src/views/manage-log/bms.vue

@@ -0,0 +1,13 @@
+<template>
+  
+</template>
+
+<script>
+export default {
+    name: 'BatteryCharger',
+}
+</script>
+
+<style>
+
+</style>

+ 13 - 0
src/views/manage-log/change-record.vue

@@ -0,0 +1,13 @@
+<template>
+  
+</template>
+
+<script>
+export default {
+    name:'ChangeRecord'
+}
+</script>
+
+<style>
+
+</style>

+ 0 - 0
src/views/error-log/components/ErrorTestA.vue → src/views/manage-log/components/ErrorTestA.vue


+ 0 - 0
src/views/error-log/components/ErrorTestB.vue → src/views/manage-log/components/ErrorTestB.vue


+ 91 - 0
src/views/manage-log/log.scss

@@ -0,0 +1,91 @@
+.charge-box {
+    display: flex;
+    padding: 0 35px;
+    flex-direction: column;
+
+    .charge-tools {
+        height: 88px;
+        background-color: #111827;
+        border: #192337 solid 1px;
+        padding: 25px;
+        width: 100%;
+
+        .serch {
+            background-color: #111827;
+            width: 70px;
+            height: 40px;
+            border: #263042 solid 1px;
+            margin-left: 8px;
+            font-size: 16px;
+        }
+        .serch:hover{
+            color: #69b889;
+            background-color: #181e2e;
+            border-color: #69b889;
+        }
+        .actve {
+            background-color: #91fdb9;
+            color: #111827;
+            border: none;
+        }
+        .actve:hover{
+            background-color: #69b889;
+            border-color: #69b889;
+            color: white;
+        }
+
+        .days {
+            background-color: #111827;
+            height: 40px;
+            border: #263042 solid 1px;
+            width: 92px;
+            margin-right: 18px;
+            font-size: 16px;
+        }
+
+        .times {
+            background-color: #111827;
+            height: 40px;
+            border: #263042 solid 1px;
+        }
+    }
+
+    .charge-table {
+        padding: 15px 25px;
+        background-color: #111827;
+        border: #192337 solid 1px;
+        width: 100%;
+        min-height: 68vh;
+        margin-top: 3vh;
+        display: flex;
+        flex-direction: column;
+
+        .charge-table-top {
+            height: 50px;
+            width: 100%;
+            text-align: right;
+            margin-bottom: 10px;
+
+            .daochu {
+                background-color: #111827;
+                width: 100px;
+                border: #91fdb9 solid 1px;
+                color: #91fdb9;
+                height: 40px;
+                font-size: 14px;
+                font-weight: 600;
+            }
+        }
+
+        .charge-table-bottom {
+            width: 100%;
+            min-height: 100%;
+            background-color: #111827;
+        }
+
+        .pageblock {
+            text-align: right;
+            padding: 15px 0px;
+        }
+    }
+}

+ 326 - 0
src/views/manage-log/robot.vue

@@ -0,0 +1,326 @@
+<template>
+  <div class="charge-box">
+    <div class="charge-tools">
+      <el-form :inline="true" :model="queryParams">
+        <el-form-item label="日志范围:" style="margin-left: 35px">
+          <el-select 
+            multiple
+            v-model="robotValue" 
+            clearable 
+            placeholder="请选择"
+            @change="changeSelect"
+            collapse-tags
+            @remove-tag="removeTag"
+          >
+            <el-option label="全选" value="全选" @click.native="selectAll"></el-option>
+            <el-option
+              v-for="item in logOptions"
+              :key="item.alarmCode"
+              :label="item.alarmName"
+              :value="item.alarmCode"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="时间范围:" style="margin-left: 50px">
+          <el-date-picker
+            v-model="dateTime"
+            class="times"
+            type="datetimerange"
+            range-separator="至"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+            format="yyyy-MM-dd HH:mm:ss"
+          />
+        </el-form-item>
+
+        <el-form-item>
+          <el-button type="primary" class="serch actve" @click="handleQuery">查询</el-button>
+          <el-button type="primary" class="serch" @click="resetForm">重置</el-button>
+        </el-form-item>
+
+      </el-form>
+    </div>
+
+    <div class="charge-table">
+      <div class="charge-table-top">
+        <el-button type="primary" class="daochu" @click="chargeExport">导出结果</el-button>
+      </div>
+      <div class="charge-table-bottom">
+        <el-table
+          :data="datalist"
+          :header-cell-style="{
+            background: '#1d283e',
+            borderColor: '#2f3c86',
+            height: '36px',
+            lineHeight: '36px',
+            color:'white',
+            fontSize: '15px',
+          }"
+          stripe
+          fit
+          :height="tableheight"
+          style="width: 100%"
+          :default-sort="{prop: 'chargerId', order: 'descending'}"
+          @selection-change="handleSelectionChange"
+        >
+        <el-table-column
+          type="selection"
+          width="55">
+        </el-table-column>
+        <af-table-column
+          prop="time"
+          label="发生时间"
+          fixed
+          width="140">
+        </af-table-column>
+        <af-table-column
+          prop="plcTag"
+          label="日志编号"
+          fixed
+          width="120">
+        </af-table-column>
+        <af-table-column v-for="log in logOptions" :key="log.alarmCode" :label="log.alarmName">
+          <template slot-scope="scope">
+            {{ scope.row.time }}
+          </template>
+        </af-table-column>
+
+          <!-- <el-table-column label="时段明细" width="100" align="center" fixed="right">
+            <template slot-scope="scope">
+              <el-button type="primary" class="handle" size="small" @click="chargeShow(scope.row.interval)">明细</el-button>
+            </template>
+          </el-table-column> -->
+        </el-table>
+      </div>
+      <div class="pageblock">
+        <el-pagination
+          :current-page="queryParams.page"
+          :page-sizes="[10, 20, 30, 40]"
+          :page-size="queryParams.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="total"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+
+    <!--时段明细弹窗-->
+    <div class="rolemanage chargeshow">
+      <el-dialog
+        title="充电明细"
+        :visible.sync="dialogChargeVisible"
+        :destroy-on-close="true"
+      >
+        <div class="charge-table-bottom">
+          <el-table
+            :data="chargeShowList"
+            :header-cell-style="{
+              background: '#1d283e',
+              borderColor: '#2f3c86',
+              height: '36px',
+              lineHeight: '36px',
+              color:'white',
+              fontSize: '16px',
+            }"
+            stripe
+            fit
+            :height="tableheight-80"
+            style="width: 100%"
+          >
+            <el-table-column
+              prop="index"
+              label="序号"
+            />
+            <el-table-column
+              prop="startTime"
+              label="开始时间段"
+            />
+            <el-table-column
+              prop="endTime"
+              label="结束时间段"
+            />
+            <el-table-column
+              prop="chargePower"
+              label="充电量kWh"
+            />
+          </el-table>
+        </div>
+        <div slot="footer" class="dialog-footer" />
+      </el-dialog>
+    </div>
+    <!--时段明细弹窗结束-->
+  </div>
+</template>
+
+<script>
+import './log.scss'
+import { chargeList, chargeExport, getChargeCode } from '@/api/records'
+import { logModel,robotList } from '@/api/log'
+import serverUrl from '../../../vue.config.js'
+export default {
+  name: 'Robot',
+  components: {},
+  data() {
+    return {
+      // 查询时间数组
+      dateTime: '',
+      // 充电机ID下拉列表
+      chargerArr: null,
+      // 数据列表
+      datalist: [],
+      // 查询参数
+      queryParams: {
+        page: 1, // 当前页
+        pageSize: 10, // 每页条数
+        chargerId: undefined, 
+        chgSn: undefined, // 电池编号
+        chgBeginTime: undefined,
+        chgEndTime: undefined,
+        orderByField: undefined, // 排序字段
+        orderByWays: 'desc'// 排序方式
+      },
+      total: 0, // 总条数,
+      tableheight: 0, // 表格高度设置
+      dialogChargeVisible: false, // 弹窗显示
+      chargeShowList: [],// 充电机明细弹窗列表
+      checked: false,
+      indeterminate: false,
+      robotValue:'',
+      logOptions: [],
+      multipleSelection:[]
+    }
+  },
+  watch: {
+    tableheight(val) {
+      // 为了避免频繁触发resize函数导致页面卡顿,使用定时器
+      if (!this.heightTimer) {
+        // 一旦监听到的screenWidth值改变,就将其重新赋给data里的screenWidth
+        this.screenHeight = val
+        this.heightTimer = true
+        setTimeout(function() {
+          this.heightTimer = false
+        }, 400)
+      }
+    }
+  },
+  mounted() {
+    this.getChargeCode()
+    this.onLoadHeight()
+    this.changeWindow()
+    this.getLogModel()
+    this.getrobotList()
+  },
+  methods: {
+    /* 设置初始视窗高度*/
+    onLoadHeight() {
+      this.$nextTick(() => {
+        this.tableheight = document.body.clientHeight - 460
+      })
+    },
+    /* 设置窗口变化高度*/
+    changeWindow() {
+      window.onresize = () => {
+        return (() => {
+          this.tableheight = document.body.clientHeight - 460
+        })()
+      }
+    },
+    selectAll() {
+      if (this.robotValue.length < this.logOptions.length) {
+        this.robotValue = [];
+        this.logOptions.map((item) => {
+          this.robotValue.push(item.value);
+        });
+        this.robotValue.unshift("全选");
+      } else {
+        this.robotValue = [];
+      }
+      this.$emit("SelectedData", this.robotValue);
+    },
+    changeSelect(val) {
+      if (!val.includes("全选") && val.length === this.logOptions.length) {
+        this.robotValue.unshift("全选");
+      } else if (val.includes("全选") && val.length - 1 < this.logOptions.length) {
+        this.robotValue = this.robotValue.filter((item) => {
+          return item !== "全选";
+        });
+      }
+      this.$emit("SelectedData", this.robotValue);
+    },
+    removeTag(val) {
+      if (val === "全选") {
+        this.robotValue = [];
+      }
+      this.$emit("SelectedData", this.robotValue);
+    },
+    //列表选择
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    //获取机器人日志列表
+    getrobotList(){
+      const params={}
+      robotList(params).then( res =>{
+        console.log(res)
+        this.datalist= res.data
+      })
+    },
+    //获取日志数据字典
+    getLogModel(){
+      logModel().then( res =>{
+        this.logOptions= res.data
+      })
+    },
+    // 充电明细弹窗显示
+    chargeShow(list) {
+      this.dialogChargeVisible = true
+      this.chargeShowList = list
+    },
+    // 获取充电机ID
+    getChargeCode() {
+      getChargeCode().then(res => {
+        this.chargerArr = res.data
+      })
+    },
+    /** 分页下一页 */
+    handleSizeChange(val) {
+      this.queryParams.pageSize = val
+    },
+    /** 分页选择页数 */
+    handleCurrentChange(val) {
+      this.queryParams.page = val
+    },
+    // 搜索
+    handleQuery() {
+      if (this.dateTime) {
+        this.queryParams.chgBeginTime = this.$moment(this.dateTime[0]).format('YYYY-MM-DD HH:mm:ss')
+        this.queryParams.chgEndTime = this.$moment(this.dateTime[1]).format('YYYY-MM-DD HH:mm:ss')
+      }
+      console.log(this.queryParams)
+    },
+    // 搜索重置
+    resetForm() {
+      this.queryParams.chgBeginTime = undefined
+      this.queryParams.chgEndTime = undefined
+      this.queryParams.chargerId = undefined
+      this.queryParams.chgSn = undefined
+    },
+    // 导出结果
+    chargeExport() {
+      this.$confirm('确认导出结果?', '导出结果', {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+      .then(async() => {
+          const res = await chargeExport(this.queryParams)
+          const execlUrl=serverUrl.devServer.proxy['/api'].target+'/excel/'+res.data
+          window.open(execlUrl,'_blank')
+        })
+      .catch(err => { console.error(err) })
+    }
+  }
+}
+</script>

+ 5 - 0
src/views/permission/cartype-manage/index.vue

@@ -60,6 +60,11 @@
               label="前端电池距离(CM)"
               >
             </el-table-column>
+            <el-table-column
+              prop="batteryHighly"
+              label="电池高度(MM)"
+              >
+            </el-table-column>
             <el-table-column
               prop="createTime"
               label="创建时间"

+ 17 - 9
src/views/permission/directive.vue

@@ -63,17 +63,17 @@
           <el-table-column
             prop="vehicleVin"
             label="车辆识别码"
-            width="150"
+            width="150"
           />
           <el-table-column
             prop="vehicleOdo"
             label="车辆ODO(KM)"
-            width="130"
+            width="130"
           />
           <el-table-column
             prop="connTime"
             label="车站连接时间"
-            width="230"
+            width="230"
           />
           <el-table-column
             prop="driverName"
@@ -115,7 +115,7 @@
           <el-table-column
             prop="swapSn"
             label="换电电池编号"
-            width="168"
+            width="228"
           />
           <el-table-column
             prop="swapSoc"
@@ -138,7 +138,7 @@
           layout="total, sizes, prev, pager, next, jumper"
           :total="total"
           @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
+          @current-change="handleCurrentChange"
         />
       </div>
     </div>
@@ -148,6 +148,7 @@
 <script>
 import './permission.scss'
 import { swapList, swapExport } from '@/api/records'
+import serverUrl from '../../../vue.config.js'
 export default {
   name: 'DirectivePermission',
   components: {},
@@ -243,11 +244,18 @@ export default {
     },
     // 导出结果
     swapExport() {
-      const params = this.queryParams
-      swapExport(params).then(res => {
-        console.log(res.data)
+      this.$confirm('确认导出结果?', '导出结果', {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning'
       })
+      .then(async() => {
+          const res = await swapExport(this.queryParams)
+          const execlUrl=serverUrl.devServer.proxy['/api'].target+'/excel/'+res.data
+          window.open(execlUrl,'_blank')
+        })
+      .catch(err => { console.error(err) })
     }
   }
 }
-</script>
+</script>

+ 13 - 5
src/views/permission/page.vue

@@ -141,7 +141,7 @@
           layout="total, sizes, prev, pager, next, jumper"
           :total="total"
           @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
+          @current-change="handleCurrentChange"
         />
       </div>
     </div>
@@ -197,6 +197,7 @@
 <script>
 import './permission.scss'
 import { chargeList, chargeExport, getChargeCode } from '@/api/records'
+import serverUrl from '../../../vue.config.js'
 export default {
   name: 'PagePermission',
   components: {},
@@ -308,11 +309,18 @@ export default {
     },
     // 导出结果
     chargeExport() {
-      const params = this.queryParams
-      chargeExport(params).then(res => {
-        console.log(res.data)
+      this.$confirm('确认导出结果?', '导出结果', {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning'
       })
+      .then(async() => {
+          const res = await chargeExport(this.queryParams)
+          const execlUrl=serverUrl.devServer.proxy['/api'].target+'/excel/'+res.data
+          window.open(execlUrl,'_blank')
+        })
+      .catch(err => { console.error(err) })
     }
   }
 }
-</script>
+</script>

+ 12 - 4
src/views/permission/record-alarm/index.vue

@@ -164,6 +164,7 @@
   <script>
   import '../permission.scss';
   import { alarmList,alarmExport,alarmDispose } from "@/api/records";
+  import serverUrl from '../../../../vue.config.js'
   export default {
     name: "RecordAlarm",
     components: {},
@@ -277,10 +278,17 @@
       },
       //导出结果
       alarmExport(){
-        const params=this.queryParams
-        alarmExport(params).then(res=>{
-          console.log(res.data)
-        });
+        this.$confirm('确认导出结果?', '导出结果', {
+          confirmButtonText: '确认',
+          cancelButtonText: '取消',
+          type: 'warning'
+        })
+        .then(async() => {
+            const res = await alarmExport(this.queryParams)
+            const execlUrl=serverUrl.devServer.proxy['/api'].target+'/excel/'+res.data
+            window.open(execlUrl,'_blank')
+          })
+        .catch(err => { console.error(err) })
       },
       //告警状态弹窗
       handlealarm(row){

+ 5 - 5
src/views/power-change-monitoring/index.vue

@@ -65,7 +65,7 @@
                 </P>
               </div>
               <label>换电量(kWh)</label>
-              <pannel-item :value="batteryInfo.space" />
+              <pannel-item :value="batteryInfo.swapCapacity" />
             </li>
           </ul>
           <div class="bin-info">
@@ -302,8 +302,8 @@ export default {
       processtext: [
         '车辆验证',
         '发起换电申请',
-        '开始换电',
-        '更换电池',
+        '卸载车辆电池',
+        '安装满电电池',
         '换电完成'
       ],
       processImages: [
@@ -698,7 +698,7 @@ export default {
         font-family: "微软雅黑";
 
         .v-plate {
-          width: 25%;
+          width: 20%;
         }
         .v-type {
           width: 22%;
@@ -710,7 +710,7 @@ export default {
           width: 15%;
         }
         .v-power {
-          width: 15%;
+          width: 25%;
         }
         .color-blue {
           color: rgb(20, 189, 243);

+ 17 - 7
src/views/statistical-analysis/index.vue

@@ -74,7 +74,8 @@ export default {
             barData:{
                 alarmFreq:[],
                 date:[],
-            }
+            },
+            fullscreenLoading:false
         }
     },
     mounted() {
@@ -280,7 +281,7 @@ export default {
         getFirstpie() {
             let firstpie = echarts.init(this.$refs.firstpie)
             var dataCake = [
-                { value: this.pieData.storeFreq, name: '储充报警', percentage: this.pieData.systemAlarm },
+                { value: this.pieData.storeFreq, name: '储充报警', percentage: this.pieData.storeAlarm },
                 { value: this.pieData.batteryFreq, name: '电池报警', percentage: this.pieData.batteryAlarm },
                 { value: this.pieData.systemFreq, name: '系统报警', percentage: this.pieData.systemAlarm },
             ]
@@ -510,14 +511,22 @@ export default {
                 beginTime:this.beginTime,
                 endTime:this.endTime
             }
-            this.$nextTick(()=>{
-                this.changePower(params)
-                this.getAlarmType(params)
-                this.getAlarm(params)
-            })
+            if((params.beginTime && params.endTime) !== undefined){
+                this.$nextTick(()=>{
+                    this.changePower(params)
+                    this.getAlarmType(params)
+                    this.getAlarm(params)
+                })
+            }else{
+                this.$alert('请选择开始日期和结束日期', '消息提示', {
+                    confirmButtonText: '退出',
+                    type: 'warning'
+                })
+            }
         },
         //近7天日期
         Sevenday(){
+            this.loading=true
             const start = new Date();
             const end = new Date();
             this.beginTime=this.$moment(start.setTime(start.getTime() - 3600 * 1000 * 24 * 6)).format('YYYY-MM-DD')
@@ -530,6 +539,7 @@ export default {
                 this.changePower(params)
                 this.getAlarmType(params)
                 this.getAlarm(params)
+                this.loading=false
             })
         },
         //近30天日期

+ 4 - 4
vue.config.js

@@ -12,7 +12,7 @@ module.exports = {
   lintOnSave: false,
   productionSourceMap: false,
   devServer: {
-    host: 'localhost',
+    host: '192.168.2.92',
     port: 8080,
     open: true,
     overlay: {
@@ -21,19 +21,19 @@ module.exports = {
     },
     proxy: {
       '/api': {
-        target: `http://test.hlchsw.com`,
+        target: `http://192.168.2.89:8080`,
         // target: `http://172.16.12.146:8080`,
         ws: true,
         changeOrigin: true,
       },
       '/ws': {
-         target: `ws://test.hlchsw.com/ws`,
+         target: `ws://192.168.2.89:8080/ws`,
         // target: `ws://172.16.12.146:8080/ws`,
         ws: true,
         changeOrigin: true,
       },
       '/video':{
-        target: `ws://test.hlchsw.com/`,
+        target: `ws://192.168.2.89:8080/`,
         // target: `ws://172.16.12.146:8080/ws`,
         ws: true,
         changeOrigin: true,