a1140836302 2 rokov pred
rodič
commit
760a594ec1
38 zmenil súbory, kde vykonal 1209 pridanie a 105 odobranie
  1. 1 1
      .env.development
  2. 1 1
      .env.production
  3. 5 0
      .vscode/extensions.json
  4. 48 0
      src/api/powerCharge.js
  5. 8 0
      src/api/statistics.js
  6. BIN
      src/assets/onlineb.png
  7. BIN
      src/assets/onlinet.png
  8. 7 1
      src/layout/components/Header.vue
  9. 67 9
      src/layout/components/Navbar.vue
  10. BIN
      src/layout/components/assets/close.png
  11. BIN
      src/layout/components/assets/link.png
  12. BIN
      src/layout/components/assets/set.png
  13. BIN
      src/layout/components/assets/warn.png
  14. 85 5
      src/layout/index.vue
  15. 5 2
      src/main.js
  16. 14 5
      src/router/index.js
  17. 156 27
      src/styles/element-ui.scss
  18. 4 0
      src/utils/index.js
  19. 7 8
      src/views/control-config/components/ControlBox.vue
  20. 165 0
      src/views/control-config/setFile.vue
  21. BIN
      src/views/manage-log/assets/c1.png
  22. 0 0
      src/views/manage-log/assets/c2.png
  23. 0 0
      src/views/manage-log/assets/c3.png
  24. 0 0
      src/views/manage-log/assets/c4.png
  25. 90 0
      src/views/manage-log/components/ControlBox.vue
  26. 9 15
      src/views/manage-log/control.vue
  27. 1 1
      src/views/manage-log/robot.vue
  28. 0 1
      src/views/permission/directive.vue
  29. BIN
      src/views/power-change-monitoring/assets/break.png
  30. BIN
      src/views/power-change-monitoring/assets/edit.png
  31. BIN
      src/views/power-change-monitoring/assets/iscar.png
  32. BIN
      src/views/power-change-monitoring/assets/link.png
  33. 4 4
      src/views/power-change-monitoring/components/BinInfomation.vue
  34. 11 2
      src/views/power-change-monitoring/components/PannelItem.vue
  35. 155 2
      src/views/power-change-monitoring/components/SubTitle.vue
  36. 17 1
      src/views/power-change-monitoring/components/UserItem.vue
  37. 346 17
      src/views/power-change-monitoring/index.vue
  38. 3 3
      vue.config.js

+ 1 - 1
.env.development

@@ -2,4 +2,4 @@
 ENV = 'development'
 
 # base api
-VUE_APP_BASE_API = 'http://zk.li-ai.com.cn:8080/api'
+VUE_APP_BASE_API = 'http://192.168.3.177:8080/api'

+ 1 - 1
.env.production

@@ -2,4 +2,4 @@
 ENV = 'production'
 
 # base api
-VUE_APP_BASE_API = '/api'
+VUE_APP_BASE_API = 'http://192.168.3.177:8080/api'

+ 5 - 0
.vscode/extensions.json

@@ -0,0 +1,5 @@
+{
+    "recommendations": [
+        "ms-ceintl.vscode-language-pack-zh-hans"
+    ]
+}

+ 48 - 0
src/api/powerCharge.js

@@ -22,4 +22,52 @@ export function alarmRecord(data) {
       method: 'post',
       data
     })
+}
+//已连接站控车辆列表
+export function CarOnline(data){
+  return request({
+    url: '/vehicle/online',
+    method: 'post',
+    data
+  })
+}
+//修改车牌号
+export function EditPlate(data){
+  return request({
+    url: '/vehicle/editPlate',
+    method: 'post',
+    data
+  })
+}
+//车辆上锁
+export function Updatelock(data){
+  return request({
+    url: '/vehicle/lock',
+    method: 'post',
+    data
+  })
+}
+//车辆解锁
+export function Updateunlock(data){
+  return request({
+    url: '/vehicle/unlock',
+    method: 'post',
+    data
+  })
+}
+//锁止屏蔽
+export function EditforbidLock(data){
+  return request({
+    url: '/vehicle/forbidLock',
+    method: 'post',
+    data
+  })
+}
+//暂停恢复PLC
+export function EditSwapplc(data){
+  return request({
+    url: '/swap/plc',
+    method: 'post',
+    data
+  })
 }

+ 8 - 0
src/api/statistics.js

@@ -31,3 +31,11 @@ export function changePower(data) {
     data
   })
 }
+//处置告警消防换仓
+export function getfireProtection(data){
+  return request({
+    url: '/device/fireProtection',
+    method: 'post',
+    data
+  })
+}

BIN
src/assets/onlineb.png


BIN
src/assets/onlinet.png


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

@@ -31,9 +31,15 @@ export default {
         },
         //获取子路由
         childrenList(){
+            console.log(this.permission_routes)
+            console.log(this.$route)
             if(this.$route.matched[0].name === 'ManageLog'){
                 return this.permission_routes[9].children.slice(0,6)
-            }else{
+            }
+            else if(this.$route.matched[0].name === 'ControlConfig'){
+                return this.permission_routes[10].children.slice(0,6)
+            }
+            else{
                 return this.permission_routes[8].children.slice(0,6)
             }
         }

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

@@ -4,15 +4,29 @@
     <div class="left-menu">
       <div v-for="(item, index) in PermissionList" :key="index">
         <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>
+          <svg-icon :icon-class="index === 3 || index === 4 || index === 5 ? item.meta.icon : item.children[0].meta.icon"/>
+          <svg-icon :icon-class="index === 3 || index === 4 || index === 5 ? item.meta.icon+'_active' : item.children[0].meta.icon+'_active'" class="iconacive"/>
+          <span>{{index === 3 || index === 4 || index === 5 ? 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="warn" @mouseover="getWarnList" @mouseout="LostWarn">
+        <div class="is-warn">
+          <el-badge :value="3" class="item">
+            <img src="./assets/warn.png">
+          </el-badge>
+        </div>
+        <div>消防告警</div>
+      </div>
+      <div class="warn link">
+        <div class="is-warn">
+            <img :src='isLink?require("./assets/link.png"):require("./assets/close.png")'>
+        </div>
+        <div>{{isLink?'已链接':'断开'}}</div>
+      </div>
       <div class="safedays">安全运营 {{days}} 天</div>
       <div class="time-value">
         {{ dateTime.hours }}:{{ dateTime.minutes }}:{{ dateTime.seconds }}
@@ -24,6 +38,7 @@
         </div>
       </div>
     </div>
+    <div><router-link to="/manage-log/control"><img src="./assets/set.png" width="36" height="36"></router-link></div>
     <div class="right-menu">
       <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
         <div class="avatar-wrapper">
@@ -49,9 +64,7 @@
 import { mapGetters } from "vuex";
 import { getsafeDays } from "@/api/statistics";
 export default {
-  components: {
-    
-  },
+  components: {},
   data() {
     return {
       PermissionList: [],
@@ -65,6 +78,7 @@ export default {
         seconds: "",
       },
       days:0,
+      isLink:1,
     };
   },
   computed: {
@@ -74,14 +88,26 @@ export default {
     setInterval(this.timer, 1000);
     this.menuList()
     this.getSafeDay()
+    this.getCloudState()
   },
   methods: {
+    getCloudState(){
+      this.$bus.$on('CloudState',(data)=>{
+        this.isLink=data
+      })
+    },
     //安全运行天数
     getSafeDay(){
       getsafeDays().then(res => {
         this.days=res.data
       })
     },
+    getWarnList(){
+      this.$emit('ShowWarn');
+    },
+    LostWarn(){
+      this.$emit('CloseWarn');
+    },
     //菜单路由
     menuList(){
       //console.log(this.permission_routes);
@@ -148,7 +174,7 @@ export default {
     line-height: 30px;
   }
   .left-menu {
-    width: 60%;
+    flex: 1;
     height: 100%;
     line-height: 36px;
     display: flex;
@@ -207,13 +233,35 @@ export default {
     padding-right: 1rem;
   }
   .date-time {
-    width: 18%;
+    width: 30%;
     color: white;
     display: flex;
     flex-direction: row;
     align-items: center;
     justify-content: flex-end;
     padding-right: 0.8rem;
+    
+    .warn{
+      width: 92px;
+      display: flex;
+      font-size: 16px;
+      justify-content: space-between;
+      align-items: center;
+      justify-items: center;
+      padding-right: 24px;
+      box-sizing: content-box;
+      line-height: 24px;
+      cursor: pointer;
+      height: 39px;
+    }
+    .link{
+      width: auto;
+      justify-content:flex-start;
+      img{
+       margin-right: 3px;
+       vertical-align: middle;
+      }
+    }
   .day-value {
     font-size: 0.5rem;
     line-height: 1.2rem;
@@ -222,6 +270,7 @@ export default {
   .time-value {
     font-size: 1.7rem;
     padding-right: 1rem;
+    width: 125px;
   }
   .week-value {
     font-size: 0.5rem;
@@ -229,7 +278,16 @@ export default {
   }
   .right-menu {
     height: 100%;
-    line-height: 50px;
+    line-height: 34px;
+    .el-dropdown{
+      font-size: 16px;
+      font-weight: 400;
+      color: #FFFFFF;
+      text-shadow: 0px 0px 11px rgba(34,123,255,0.8);
+      .el-icon-arrow-down:before{
+        font-weight: bold;
+      }
+    }
     &:focus {
       outline: none;
     }

BIN
src/layout/components/assets/close.png


BIN
src/layout/components/assets/link.png


BIN
src/layout/components/assets/set.png


BIN
src/layout/components/assets/warn.png


+ 85 - 5
src/layout/index.vue

@@ -1,6 +1,30 @@
 <template>
   <div class="app-wrapper">
-    <navbar />
+    <navbar @ShowWarn="ShowWarn" @CloseWarn="CloseWarn" />
+    <!-- <div class="warnTab" v-show="Isshow" @mouseover="ShowWarn" @mouseout="CloseWarn"></div> -->
+    <div class="warnTab" v-show="Isshow" @mouseover="ShowWarn" @mouseout="CloseWarn">
+      <el-table :data="warnlist" :header-cell-style="{
+          background: 'rgba(127,151,197,0.92)',
+          borderColor: '#CDDEFF',
+          height: '40px',
+          lineHeight: '40px',
+          color: 'white',
+          fontSize: '16px',
+        }" 
+        stripe 
+        fit 
+        height="100%"
+        style="width: 100%">
+          <el-table-column prop="startTime" label="开始时间" width="98" />
+          <el-table-column prop="Machine" width="106" label="设备标识" />
+          <el-table-column prop="warnInfo" label="告警信息" />
+          <el-table-column label="" align="center" width="100">
+            <template v-if="scope.row.Machine == '架载机'" slot-scope="scope">
+              <el-button class="Warnbtn" @click="ShowWarnList(scope.row.Machine)">处置</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+    </div>
     <!-- <Sidebar /> -->
     <div :class="{hasheaderView:$route.matched[0].name === 'Permission'|| $route.matched[0].name === 'ManageLog'}">
       <Header v-if="getChildrenRouter"></Header>
@@ -12,7 +36,7 @@
 <script>
 import { AppMain, Navbar } from './components'
 import Header from './components/Header'
-
+import { getfireProtection } from "@/api/statistics";
 export default {
   name: 'Layout',
   components: {
@@ -22,7 +46,33 @@ export default {
   },
   data(){
     return{
-
+      Isshow:false,
+      warnlist:[{
+        startTime:'16:23:15',
+        Machine:'架载机',
+        warnInfo:'火灾故障,持续1分钟'
+      },
+      {
+        startTime:'16:23:15',
+        Machine:'电池',
+        warnInfo:'火灾故障,持续1分钟'
+      },
+      {
+        startTime:'16:23:15',
+        Machine:'电池',
+        warnInfo:'火灾故障,持续1分钟'
+      },
+      {
+        startTime:'16:23:15',
+        Machine:'电池',
+        warnInfo:'火灾故障,持续1分钟'
+      },
+      {
+        startTime:'16:23:15',
+        Machine:'电池',
+        warnInfo:'火灾故障,持续1分钟'
+      }
+    ]
     }
   },
   mounted(){
@@ -38,7 +88,7 @@ export default {
     // }),
     //是否显示子路由
     getChildrenRouter(){
-      if((this.$route.matched[0].name === 'Permission' || this.$route.matched[0].name === 'ManageLog') && this.$route.name !== 'RolePermission' && this.$route.name !== 'UpdatePassword'){
+      if((this.$route.matched[0].name === 'Permission' || this.$route.matched[0].name === 'ManageLog' || this.$route.matched[0].name === 'ControlConfig') && this.$route.name !== 'RolePermission' && this.$route.name !== 'UpdatePassword'){
         return true;
       }else{
         return false;
@@ -46,7 +96,27 @@ export default {
     }
   },
   methods: {
-
+    ShowWarn(){
+      this.Isshow=true
+    },
+    CloseWarn(){
+      this.Isshow=false
+    },
+    ShowWarnList(Machine){
+      this.$confirm(`系统检测到【${Machine}】发生了消防问题,确认需要抓取电池吗?`, '消防换仓', {
+        cancelButtonText: '忽略',
+        confirmButtonText: '确认',
+        type: 'warning'
+      })
+        .then(async() => {
+          await getfireProtection({ targetCode:1 })
+          this.$message({
+            type: 'success',
+            message: '处理成功!'
+          })
+        })
+        .catch(err => { console.error(err) })
+    }
   }
 }
 </script>
@@ -63,6 +133,16 @@ export default {
     position: fixed;
     top: 0;
   }
+  .warnTab{
+      width: 582px;
+      height: 238px;
+      background-color: #BBCFF6;
+      z-index: 100;
+      position: absolute;
+      top: 64px;
+      right: 290px;
+      border-radius: 4px;
+  }
 }
 
 .drawer-bg {

+ 5 - 2
src/main.js

@@ -27,10 +27,13 @@ Object.keys(filters).forEach(key => {
 Vue.prototype.$echarts = echarts
 Vue.prototype.$moment = moment;
 Vue.config.productionTip = false
-
 new Vue({
   el: '#app',
   router,
   store,
-  render: h => h(App)
+  render: h => h(App),
+  beforeCreate() {
+      //此时这个this就是vm,只不过这个时候还并没有去解析模版
+      Vue.prototype.$bus = this; //安装全局事件总线
+  }
 })

+ 14 - 5
src/router/index.js

@@ -186,18 +186,27 @@ export const asyncRoutes = [
         component: () => import('@/views/manage-log/data-export'),
         name: 'DataExport',
         meta: { title: '数据导出' }
-      }
+      },
+      {
+        path: 'control',
+        component: () => import('@/views/manage-log/control'),
+        name: 'Control',
+        meta: { title: '机器人实时数据'}
+      },
     ]
   },
   {
     path: '/control-config',
     component: Layout,
+    redirect: '/control-config/setFile',
+    name: 'ControlConfig',
+    meta: {title: '站控配置',icon: 'kzpz'},
     children: [
       {
-        path: '',
-        component: () => import('@/views/control-config/index'),
-        name: 'ControlConfig',
-        meta: { title: '控制配置', icon: 'kzpz', }
+        path: 'setfile',
+        component: () => import('@/views/control-config/setFile'),
+        name: 'SetFile',
+        meta: { title: '消防配置'}
       }
     ]
   },

+ 156 - 27
src/styles/element-ui.scss

@@ -137,6 +137,58 @@
 .el-select-dropdown.is-multiple .el-select-dropdown__item.selected{
   color: rgb(132, 146, 166);
 }
+/*顶部告警列表修改*/ 
+.warnTab{
+  .el-table{
+    color: #000000;
+    font-weight: 400;
+    font-size: 16px;
+    th.gutter{
+      background-color:rgba(127,151,197,0.92);
+      border-bottom: #CDDEFF solid 1px;
+    }
+  }
+  .el-table td{
+    border-bottom:#CDDEFF solid 1px; 
+  }
+  .el-table tr{
+    background: #BBCFF6 !important;
+  }
+  .el-table--striped .el-table__body tr.el-table__row--striped td{
+    background-color: #BBCFF6;
+  }
+  .el-table--enable-row-hover .el-table__body tr:hover > td{
+    background-color: #AAC3F3!important;
+    color: #000000;
+    cursor: pointer;
+  }
+  .Warnbtn{
+    width: 48px;
+    height: 32px;
+    background: #91FDB9;
+    border-radius: 2px;
+    border: none;
+    font-size: 16px;
+    font-weight: 400;
+    color: #000000;
+    padding: 0;
+  }
+  ::-webkit-scrollbar {
+    width: 6px;
+    height: 8px;
+    background-color: #BBCFF6;
+  }
+  ::-webkit-scrollbar-thumb {
+    background-color: #EEEEEE;
+    border-radius: 6px;
+  }
+  ::-webkit-scrollbar-track{
+    border-radius: 3px;
+    background: #BBCFF6;
+  }
+}
+/*顶部告警列表修改结束*/ 
+
 /*表格样式修改*/ 
 .el-table{
   color: #e1e2e4;
@@ -261,9 +313,74 @@
     margin-top: 20px;
   }
 }
+/*修改换电监控弹窗*/
+.onlineManage{
+  .el-pagination .btn-prev, .el-pagination .btn-next{
+    background-color: #181e2e;
+  }
+  .el-pager li{
+    background-color: #181e2e;
+    border: #00e19b solid 1px;
+    min-width: 24px;
+    height: 24px;
+    line-height: 24px;
+  }
+  .el-pagination button:disabled{
+    background-color: #181e2e;
+  }
+  .el-dialog{
+    position: relative;
+    z-index: 100;
+    background-color: rgb(24, 30,46, 1);
+    margin-top: 20vh !important;
+    border-top-right-radius:20px;
+    border-bottom-left-radius:20px;
+    .el-input.is-disabled .el-input__inner{
+      background-color: #181e2e;
+      border: black solid 1px;
+    }
+    .el-dialog__body{
+      padding-bottom: 0px;
+    }
+    .el-dialog__header{
+      background: url('../assets/onlinet.png') no-repeat top;
+      border-bottom: #2d3448 solid 1px;
+      padding-left: 0px;
+      .el-dialog__title{
+        color: white;
+        width: 110px;
+        position: relative;
+        text-align: right;
+        border-bottom: white solid 3px;
+        padding-left: 15px;
+        padding-right: 15px;
+        padding-bottom: 11px;
+      }
+    }
+    .el-dialog__footer{
+      background: url('../assets/onlineb.png') no-repeat bottom;
+    }
+    .el-dialog__headerbtn:focus .el-dialog__close, .el-dialog__headerbtn:hover .el-dialog__close{
+      color: white;
+    }
+    .el-dialog__headerbtn{
+      font-size: 20px;
+    }
+  }
+}
+/*修改换电监控弹窗结束*/
+
 /*修改账号管理弹窗*/
 .rolemanage{
+  .el-form .is-required {
+      display: flex;
+      align-items: center;
+      padding-right: 25px;
+      justify-content: center;
+  }
   .el-dialog{
+    position: relative;
+    z-index: 100;
     background-color: rgb(24, 30,46, 1);
     width: 530px;
     margin-top: 28vh !important;
@@ -327,39 +444,51 @@
   }
 }
 
-//表格状态样式
-.disable{
-  .el-badge__content{
-    background-color: #ff1e1e;
-    border-color: #ff1e1e;
-  }
-}
-.nostate{
+.date-time{
   .el-badge__content{
-    background-color: #727d8a;
-    border-color: #727d8a;
-  }
-}
-.instate{
-  .el-badge__content{
-    background-color: #1eaeff;
-    border-color: #1eaeff;
+    border: none;
+    width: 16px;
+    height: 16px;
+    border-radius: 50%;
+    top: 5px;
+    padding: 0;
+    line-height: 16px;
+    text-align: center;
   }
 }
-.el-badge__content{
-  background-color: #00e19b;
-  border-color: #00e19b;
-}
-.el-badge{
-  padding-left: 12px;
-}
-.el-badge__content.is-fixed{
-  left: -10px;
-  top: 50%;
-}
 
 //表格按钮修改
 .charge-table-bottom{
+  //表格状态样式
+  .nostate{
+    .el-badge__content{
+      background-color: #727d8a;
+      border-color: #727d8a;
+    }
+  }
+  .instate{
+    .el-badge__content{
+      background-color: #1eaeff;
+      border-color: #1eaeff;
+    }
+  }
+  .disable{
+    .el-badge__content{
+      background-color: #ff1e1e;
+      border-color: #ff1e1e;
+    }
+  }
+  .el-badge__content{
+    background-color: #00e19b;
+    border-color: #00e19b;
+  }
+  .el-badge__content.is-fixed{
+    left: -10px;
+    top: 50%;
+  }
+  .el-badge{
+    padding-left: 12px;
+  }
   .el-button + .el-button{
     margin: 0;
   }

+ 4 - 0
src/utils/index.js

@@ -355,3 +355,7 @@ export function removeClass(ele, cls) {
     ele.className = ele.className.replace(reg, ' ')
   }
 }
+export function isLicensePlateNumberNER(value){
+  const isPlate=/[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))$/g.test(value)
+  return isPlate
+}

+ 7 - 8
src/views/control-config/components/ControlBox.vue

@@ -6,13 +6,13 @@
             </div>
             <div class="setspeed">
                 <div class="speed">速度: {{ speed }} m/s</div>
-                <el-button type="primary" class="set" @click="handleset('速度')">设置</el-button>
+                <!-- <el-button type="primary" class="set" @click="handleset('速度')">设置</el-button> -->
             </div>
         </div>
         <div class="left">
             <div class="setspeed" style="margin-top: 48px">
                 <div class="speed">位置: {{ position }} m/s</div>
-                <el-button type="primary" class="position" @click="handleset('位置')">设置</el-button>
+                <!-- <el-button type="primary" class="position" @click="handleset('位置')">设置</el-button> -->
             </div>
         </div>
     </div>
@@ -23,9 +23,9 @@ export default {
     name: 'ControlBox',
     props: ['title', 'img', 'speed', 'position', 'unit'],
     methods: {
-        handleset(unit) {
-            this.$emit('handleset',{title:this.title,unit:unit})
-        }
+        // handleset(unit) {
+        //     this.$emit('handleset',{title:this.title,unit:unit})
+        // }
     }
 };
 </script>
@@ -34,7 +34,6 @@ export default {
 .control-box {
     width: 45%;
     display: flex;
-    justify-content: space-between;
     padding-bottom: 64px;
 
     .left {
@@ -42,7 +41,7 @@ export default {
         flex-direction: column;
         color: #91fdb9;
         font-weight: bold;
-
+        margin-right: 20px;
         .title {
             display: flex;
             align-items: center;
@@ -61,7 +60,7 @@ export default {
             font-size: 16px;
 
             .speed {
-                width: 265px;
+                width: 365px;
                 height: 40px;
                 border: #263042 solid 1px;
                 box-sizing: border-box;

+ 165 - 0
src/views/control-config/setFile.vue

@@ -0,0 +1,165 @@
+<template>
+    <div class="charge-table">
+      <div class="charge-table-bottom">
+        <control-box
+          title="温度"
+          img="c1"
+          :speed="plcResultDTO.rAxis"
+          :position="plcResultDTO.rDpmt"
+          @handleset="handleset"
+          unit="m/s"
+        ></control-box>
+      </div>
+      <!--设置弹窗-->
+      <div class="rolemanage chargeshow">
+        <el-dialog
+          :title="`设置${dialogtext.title}-${dialogtext.unit}`"
+          :visible.sync="dialogConfigVisible"
+          :destroy-on-close="true"
+        >
+          <div class="setConfig">
+            <span>指令:</span>
+            <el-input v-model="input" placeholder="请输入指令"></el-input>
+            <el-button type="primary" class="set" @click="handleset"
+              >执行</el-button
+            >
+          </div>
+        </el-dialog>
+      </div>
+      <!--设置弹窗结束-->
+    </div>
+  </template>
+  
+  <script>
+  import wsUrl from "../../../vue.config.js"
+  import { getToken } from '@/utils/auth'
+  import ControlBox from './components/ControlBox.vue'
+  export default {
+    name: "SetFile",
+    components:{
+      ControlBox
+    },
+    data() {
+      return {
+        ws: null,
+        dialogConfigVisible: false,
+        input: "",
+        plcResultDTO:{
+          xAxis:'— — —',
+          yAxis:'— — —',
+          zAxis:'— — —',
+          rAxis:'— — —',
+          xDpmt:'— — —',
+          yDpmt:'— — —',
+          zDpmt:'— — —',
+          rDpmt:'— — —',
+        },
+        dialogtext: {}
+      };
+    },
+    mounted() {
+      if (getToken()) {
+        if (this.ws) {
+          this.ws.close();
+        }
+        this.websocketConnect();
+        // 检测websocket断开重连
+        this.detectWebsocketConnection();
+      }
+    },
+    destroyed() {
+      this.websocketOnClose();
+    },
+    methods: {
+      handleset(obj) {
+        this.dialogtext=obj
+        this.dialogConfigVisible = true;
+      },
+      websocketOnOpen() {
+        console.log("socket连接成功");
+      },
+      websocketOnMessage(m) {
+        const d = JSON.parse(m.data)
+        // console.log(d.plcResultDTO)
+        if(d.plcResultDTO){
+          this.plcResultDTO=d.plcResultDTO
+        }
+        
+      },
+      websocketOnError(e) {
+        console.log("socket错误", e);
+      },
+      websocketOnClose(e) {
+        console.log("socket断开", e);
+      },
+      detectWebsocketConnection() {
+        this.wsTimer = setInterval(() => {
+          if (this.ws.readyState != 1) {
+            this.ws.close();
+            this.websocketConnect();
+          }
+        }, 3000);
+      },
+      websocketConnect() {
+        const wstoken = getToken();
+        this.ws = new WebSocket(
+          wsUrl.devServer.proxy["/ws"].target + "/" + wstoken
+        );
+        this.ws.onopen = this.websocketOnOpen;
+        this.ws.onerror = this.websocketOnError;
+        this.ws.onmessage = this.websocketOnMessage;
+        this.ws.onclose = this.websocketOnClose;
+      },
+    },
+  };
+  </script>
+  
+  <style lang="scss" scoped>
+  .setConfig {
+    margin: 35px auto;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding-bottom: 45px;
+  
+    span {
+      color: #fff;
+      font-size: 15px;
+      text-align: right;
+    }
+  
+    .el-input {
+      width: 240px;
+      margin-right: 15px;
+    }
+  }
+  
+  .set {
+    background-color: #91fdb9;
+    color: #0b111d;
+    border-color: #91fdb9;
+    font-weight: 600;
+    letter-spacing: 1px;
+  }
+  
+  .charge-table {
+    padding: 50px;
+    background-color: #111827;
+    border: #192337 solid 1px;
+    min-height: 68vh;
+    margin: 35px;
+    display: flex;
+    flex-direction: column;
+  
+    .charge-table-bottom {
+      width: 100%;
+      min-height: 100%;
+      background-color: #111827;
+      display: flex;
+      justify-content: space-between;
+      flex-wrap: wrap;
+  
+      
+    }
+  }
+  </style>

BIN
src/views/manage-log/assets/c1.png


+ 0 - 0
src/views/control-config/assets/c2.png → src/views/manage-log/assets/c2.png


+ 0 - 0
src/views/control-config/assets/c3.png → src/views/manage-log/assets/c3.png


+ 0 - 0
src/views/control-config/assets/c4.png → src/views/manage-log/assets/c4.png


+ 90 - 0
src/views/manage-log/components/ControlBox.vue

@@ -0,0 +1,90 @@
+<template>
+    <div class="control-box">
+        <div class="left">
+            <div class="title">
+                <img :src="require(`../assets/${img}.png`)" /><span>{{ title }}</span>
+            </div>
+            <div class="setspeed">
+                <div class="speed">速度: {{ speed }} m/s</div>
+                <!-- <el-button type="primary" class="set" @click="handleset('速度')">设置</el-button> -->
+            </div>
+        </div>
+        <div class="left">
+            <div class="setspeed" style="margin-top: 48px">
+                <div class="speed">位置: {{ position }} m/s</div>
+                <!-- <el-button type="primary" class="position" @click="handleset('位置')">设置</el-button> -->
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'ControlBox',
+    props: ['title', 'img', 'speed', 'position', 'unit'],
+    methods: {
+        // handleset(unit) {
+        //     this.$emit('handleset',{title:this.title,unit:unit})
+        // }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.control-box {
+    width: 45%;
+    display: flex;
+    padding-bottom: 64px;
+
+    .left {
+        display: flex;
+        flex-direction: column;
+        color: #91fdb9;
+        font-weight: bold;
+        margin-right: 20px;
+        .title {
+            display: flex;
+            align-items: center;
+
+            span {
+                margin-left: 8px;
+                margin-top: 3px;
+                font-size: 18px;
+            }
+        }
+
+        .setspeed {
+            display: flex;
+            margin-top: 25px;
+            color: #4c5d71;
+            font-size: 16px;
+
+            .speed {
+                width: 365px;
+                height: 40px;
+                border: #263042 solid 1px;
+                box-sizing: border-box;
+                line-height: 40px;
+                padding-left: 18px;
+                margin-right: 10px;
+            }
+
+            .position {
+                background-color: #111827;
+                color: #fff;
+                border-color: #263042;
+                font-weight: 600;
+                letter-spacing: 1px;
+            }
+
+            .set {
+                background-color: #91fdb9;
+                color: #0b111d;
+                border-color: #91fdb9;
+                font-weight: 600;
+                letter-spacing: 1px;
+            }
+        }
+    }
+}
+</style>

+ 9 - 15
src/views/control-config/index.vue → src/views/manage-log/control.vue

@@ -6,7 +6,6 @@
         img="c1"
         :speed="plcResultDTO.rAxis"
         :position="plcResultDTO.rDpmt"
-        @handleset="handleset"
         unit="m/s"
       ></control-box>
       <control-box
@@ -14,7 +13,6 @@
         img="c2"
         :speed="plcResultDTO.yAxis"
         :position="plcResultDTO.yDpmt"
-        @handleset="handleset"
         unit="m/s"
       ></control-box>
       <control-box
@@ -22,7 +20,6 @@
         img="c3"
         :speed="plcResultDTO.xAxis"
         :position="plcResultDTO.xDpmt"
-        @handleset="handleset"
         unit="m/s"
       ></control-box>
       <control-box
@@ -30,12 +27,11 @@
         img="c4"
         :speed="plcResultDTO.zAxis"
         :position="plcResultDTO.zDpmt"
-        @handleset="handleset"
         unit="m/s"
       ></control-box>
     </div>
     <!--设置弹窗-->
-    <div class="rolemanage chargeshow">
+    <!-- <div class="rolemanage chargeshow">
       <el-dialog
         :title="`设置${dialogtext.title}-${dialogtext.unit}`"
         :visible.sync="dialogConfigVisible"
@@ -49,7 +45,7 @@
           >
         </div>
       </el-dialog>
-    </div>
+    </div> -->
     <!--设置弹窗结束-->
   </div>
 </template>
@@ -57,9 +53,9 @@
 <script>
 import wsUrl from "../../../vue.config.js"
 import { getToken } from '@/utils/auth'
-import ControlBox from './components/ControlBox.vue'
+import ControlBox from './components/ControlBox'
 export default {
-  name: "ControlConfig",
+  name: "Control",
   components:{
     ControlBox
   },
@@ -95,17 +91,16 @@ export default {
     this.websocketOnClose();
   },
   methods: {
-    handleset(obj) {
-      console.log(obj)
-      this.dialogtext=obj
-      this.dialogConfigVisible = true;
-    },
+    // handleset(obj) {
+    //   this.dialogtext=obj
+    //   this.dialogConfigVisible = true;
+    // },
     websocketOnOpen() {
       console.log("socket连接成功");
     },
     websocketOnMessage(m) {
       const d = JSON.parse(m.data)
-      console.log(d.plcResultDTO)
+      // console.log(d.plcResultDTO)
       if(d.plcResultDTO){
         this.plcResultDTO=d.plcResultDTO
       }
@@ -181,7 +176,6 @@ export default {
     min-height: 100%;
     background-color: #111827;
     display: flex;
-    justify-content: space-between;
     flex-wrap: wrap;
 
     

+ 1 - 1
src/views/manage-log/robot.vue

@@ -67,7 +67,7 @@
             prop="time"
             label="发生时间"
             fixed="left"
-            width="150">
+            width="180">
           </el-table-column>
           <el-table-column v-for="log in logheader" :key="log.alarmCode" :label="log.alarmName" :render-header="labelHead">
             <template slot-scope="scope">

+ 0 - 1
src/views/permission/directive.vue

@@ -47,7 +47,6 @@
           fit
           :height="tableheight"
           style="width: 100%"
-          :default-sort="{prop: 'swapId', order: 'descending'}"
         >
           <el-table-column
             prop="swapId"

BIN
src/views/power-change-monitoring/assets/break.png


BIN
src/views/power-change-monitoring/assets/edit.png


BIN
src/views/power-change-monitoring/assets/iscar.png


BIN
src/views/power-change-monitoring/assets/link.png


+ 4 - 4
src/views/power-change-monitoring/components/BinInfomation.vue

@@ -144,7 +144,7 @@ export default {
           cls['greenAnimationFive'] = true
         } else if (this.swapCode === 7) {
           cls['greenAnimationSix'] = true
-        }
+        }
       }
       if (this.step === 4 && this.swapCode === index) {
         if (this.swapCode === 1) {
@@ -197,7 +197,7 @@ export default {
   background-size: 100% 100%;
   color: #233C39;
   position: absolute;
-  z-index:99999
+  z-index:99
 }
 .yellowAnimationOne{
   animation: yellowOnestep 2s linear forwards
@@ -408,7 +408,7 @@ export default {
 .bin-carbg .battery-yellow {
   position: relative;
   width: 73px;
-  z-index: 9999;
+  z-index: 99;
 }
 
 .battery-yellow .battery-yellow-img {
@@ -503,4 +503,4 @@ export default {
   width: 101px;
   height: 35px;
 }
-</style>
+</style>

+ 11 - 2
src/views/power-change-monitoring/components/PannelItem.vue

@@ -3,17 +3,23 @@
     <div class="shinning" />
     <div class="round"><img src="../assets/ico1.png"></div>
     <div class="value">{{ value }}</div>
+    <div v-if="label=='车牌号'" @click="ShowEditCar(value)" class="editCar"><img src="../assets/edit.png"></div>
   </div>
 </template>
 
 <script>
 export default {
   name: 'PannelItem',
-  props: ['label', 'value']
+  props: ['label', 'value'],
+  methods: {
+    ShowEditCar(plate){
+        this.$emit('HandleEditPlate',plate);
+    }
+  },
 }
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
     .label {
         color: rgb(201,248,255);
         width: 38%;
@@ -54,5 +60,8 @@ export default {
         color: white;
         font-weight: 500;
         text-shadow: 0 0 0.1rem #111574;
+        .editCar{
+          cursor: pointer;
+        }
     }
 </style>

+ 155 - 2
src/views/power-change-monitoring/components/SubTitle.vue

@@ -13,7 +13,18 @@
         <div class="times" v-if="swapTime">
           换电时间:<font>{{ swapTime }}</font>
         </div>  
-        <div class="store-list active" @click="changePower" v-if="logInfo">开始换电</div>
+        <div class="handleList"  v-if="swaplogInfo">
+          <div class="plcState"><span>机器人状态:</span>{{ plcState }}</div>
+          <div class="plcState"><span>机器人暂停状态:</span>{{ plcpause?'暂停':'正常' }}</div>
+          <div class="plcState"><span>屏蔽锁止状态:</span>{{ forbidLockState==1?'已屏蔽':'正常' }}</div>
+          <div class="store-list" @click="HandleSwapplc(5)">继续</div>
+          <div class="store-list" @click="HandleSwapplc(4)" >暂停</div>
+          <div class="store-list" @click="HandleIsLock(1)" >锁止屏蔽</div>
+          <div class="store-list" @click="HandleIsLock(0)" >锁止放开</div>
+          <div class="store-list" @click="HandleOnLock" >车辆上锁</div>
+          <div class="store-list" @click="HandlerDownLock" >车辆解锁</div>
+          <div class="store-list active" @click="changePower">开始换电</div>
+        </div>
       </div>
     </div>
   </div>
@@ -21,10 +32,141 @@
 
 <script>
 import { beginSwap } from '@/api/equipment'
+import { Updateunlock,Updatelock,EditforbidLock,EditSwapplc } from '@/api/powerCharge'
 export default {
   name: "SubTitle",
-  props: ["name", "statement","logInfo","swapTime"],
+  props: ["name", "statement","swaplogInfo","swapTime","logInfo","robotState","plcpause","forbidLockState"],
+  computed:{
+    //机器人状态
+    plcState(){
+      switch(this.robotState){
+        case 0:
+          return '启动/未就绪'
+        case 1:
+          return '就绪'
+        case 2:
+          return '工作中'
+        case 3:
+          return '自动/单步操作完成'
+        case 4:
+          return '故障'
+      }
+    }
+  },
   methods:{
+    //暂停恢复
+    HandleSwapplc(id){
+      this.loading=true
+      let swaptext=''
+      if(id===4){
+        swaptext='暂停操作'
+      }
+      if(id===5){
+        swaptext='恢复操作'
+      }
+      this.$confirm(`请确认${swaptext}?`, swaptext, {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(async() => {
+          const res = await EditSwapplc(id)
+          if(res.code === 0){
+              this.$message({
+              type: 'success',
+              message: res.data,
+            })
+          }else{
+              this.$message({
+              type: 'warning',
+              message: res.msg,
+            })
+          }
+          this.loading=false
+        })
+        .catch(err => { console.error(err) })
+    },
+    ///锁止屏蔽、放开
+    HandleIsLock(islock){
+      let lockTest=''
+      if(islock === 0){
+        lockTest='锁止放开'
+      }else{
+        lockTest='锁止屏蔽'
+      }
+      this.loading=true
+      this.$confirm(`请确认${lockTest}?`, lockTest, {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(async() => {
+          const res = await EditforbidLock(islock)
+          if(res.code === 0){
+              this.$message({
+              type: 'success',
+              message: res.data,
+            })
+          }else{
+              this.$message({
+              type: 'warning',
+              message: res.msg,
+            })
+          }
+          this.loading=false
+        })
+        .catch(err => { console.error(err) })
+    },
+    //车辆上锁
+    HandleOnLock(){
+      this.loading=true
+      this.$confirm('请确认车辆上锁?', '车辆上锁', {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(async() => {
+          const res = await Updatelock()
+          if(res.code === 0){
+              this.$message({
+              type: 'success',
+              message: res.data,
+            })
+          }else{
+              this.$message({
+              type: 'warning',
+              message: res.msg,
+            })
+          }
+          this.loading=false
+        })
+        .catch(err => { console.error(err) })
+    },
+    //车辆解锁
+    HandlerDownLock(){
+      this.loading=true
+      this.$confirm('请确认车辆解锁?', '车辆解锁', {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(async() => {
+          const res = await Updateunlock()
+          if(res.code === 0){
+              this.$message({
+              type: 'success',
+              message: res.data,
+            })
+          }else{
+              this.$message({
+              type: 'warning',
+              message: res.msg,
+            })
+          }
+          this.loading=false
+        })
+        .catch(err => { console.error(err) })
+    },
     // 手动发起换电
     changePower() {
       this.loading=true
@@ -55,6 +197,17 @@ export default {
 </script>
 
 <style scoped>
+.plcState{
+  color: #86edab;
+  padding-right: 30px;
+  line-height: 32px;
+}
+.plcState span{
+  color: #596189;
+}
+.handleList{
+  display: flex;
+}
 .timestate{
   display: flex;
   align-items: center;

+ 17 - 1
src/views/power-change-monitoring/components/UserItem.vue

@@ -4,13 +4,19 @@
       <div class="userboder"></div>
       <div class="user-name">{{title}}</div>
       <div class="user-eng">{{name}}</div>
+      <div v-if="title=='车辆信息'" class="more" @click="handleCarShow">更多</div>
     </div>
   </div>
 </template>
 
 <script>
 export default {
-    props:['title','name']
+    props:['title','name'],
+    methods: {
+      handleCarShow(){
+        this.$emit('ShowCarline');
+      }
+    },
 };
 </script>
 
@@ -49,4 +55,14 @@ export default {
   margin-left: 2%;
   margin-top:13px;
 }
+.more{
+  margin-left: auto;
+  padding-right: 16px;
+  color: #008AD8;
+  font-weight: 500;
+  line-height: 36px;
+  text-shadow: 0px 0px 4px rgba(39,69,201,0.5);
+  font-size: 16px;
+  cursor: pointer;
+}
 </style>

+ 346 - 17
src/views/power-change-monitoring/index.vue

@@ -19,19 +19,27 @@
               <pannel-item :value="driverInfo.motorcade" />
             </li>
             <li>
-              <UserItem title="车辆信息" name="VEHICLE INFORMATION" />
-              <span>
-                <label>车辆VIN码</label><label>{{ Carlink }}</label>
-              </span>
+              <UserItem title="车辆信息" name="VEHICLE INFORMATION" @ShowCarline="ShowCarline" />
+              <div class="carVin">
+                <label>车辆VIN码</label>
+                <label class="linkeState" v-if="vehicleInfo.conState==1">
+                    <div><img src="./assets/link.png"></div>
+                    <div>{{ Carlink }}</div>
+                </label>
+                <label class="linkeState" v-else>
+                  <div><img src="./assets/break.png"></div>
+                  <div class="break">未链接{{ totalSecond?totalSecond+'s' :' '}}</div>
+                </label>
+              </div>
               <pannel-item :value="vehicleInfo.vin" />
               <div class="carinfo">
                 <p>
                   <label>车牌号</label>
-                  <pannel-item :value="vehicleInfo.plate" />
+                  <pannel-item :value="vehicleInfo.plate" label="车牌号" @HandleEditPlate="HandleEditPlate" />
                 </p>
                 <p>
-                  <label>解锁状态</label>
-                  <pannel-item :value="Carlock" />
+                  <label>到位状态</label>
+                  <pannel-item :value="Carsensor" />
                 </p>
               </div>
               <div class="carinfo">
@@ -40,13 +48,20 @@
                   <pannel-item :value="vehicleInfo.mileage" />
                 </p>
                 <p>
-                  <label>上电状态</label>
-                  <pannel-item :value="Carbattery" />
+                  <label>解锁状态</label>
+                  <pannel-item :value="Carlock" />
+                </p>
+              </div>
+              <div class="carinfo">
+                  <p>
+                    <label>累计换电 (次)</label>
+                    <pannel-item :value="vehicleInfo.swap" />
+                  </p>
+                  <p>
+                    <label>上电状态</label>
+                    <pannel-item :value="Carbattery" />
                 </p>
               </div>
-
-              <label>累计换电 (次)</label>
-              <pannel-item :value="vehicleInfo.swap" />
             </li>
             <li>
               <UserItem title="电池信息" name="Battery INFORMATION" />
@@ -96,7 +111,11 @@
         name="换电业务流程"
         statement="power exchange business process"
         :logInfo="swapProcess.logInfo"
+        swaplogInfo="1"
         :swapTime="swapTime"
+        :robotState="robotInfoVo.robotState"
+        :plcpause="robotInfoVo.pause"
+        :forbidLockState="forbidLockState"
       />
       <process-symbol
         :processtext="processtext"
@@ -213,11 +232,110 @@
         </div>
       </div>
     </div>
+    <!--实时车辆弹窗-->
+    <div class="onlineManage">
+      <el-dialog
+        title="实时车辆连接信息"
+        :visible.sync="dialogCarlineVisible"
+        :destroy-on-close="true"
+        width="1600px"
+      >
+        <div class="charge-table-bottom">
+          <el-table
+            :data="CarlineList"
+            :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 label="车牌号">
+                <template slot-scope="{row}">
+                  <div class="iscar">
+                    <span>{{ row.vehiclePlate }}</span><img src="./assets/iscar.png" v-if="vehicleInfo.plate==row.vehiclePlate">
+                  </div>
+                </template>
+            </el-table-column>
+            <el-table-column label="启动状态">
+                <template slot-scope="{row}">
+                  <span class="item" :class="{disable:row.state === 0}">{{ row.state === 0 ? '熄火' : '启动' }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column
+              prop="vehicleVin"
+              label="VIN码"
+              width="160"
+            />
+            <!-- <el-table-column
+              prop="mileage"
+              label="行驶里程(KW)"
+            />
+            <el-table-column
+              prop="sn"
+              label="电池编号"
+              width="220"
+            />
+            <el-table-column
+              prop="Voltage"
+              label="电压(V)"
+            />
+            <el-table-column
+              prop="Current"
+              label="电流(A)"
+            />
+            <el-table-column
+              prop="swapSoc"
+              label="SOC"
+            />
+            <el-table-column
+              prop="swapSoh"
+              label="SOH"
+            />
+            <el-table-column
+              prop="driver"
+              label="司机"
+            />
+            <el-table-column
+              prop="phone"
+              label="联系电话"
+            /> -->
+          </el-table>
+        </div>
+        <div class="pageblock">
+          站内连接车辆数:<span>{{ CarlineList.length }}</span>
+        </div>
+        <div slot="footer" class="dialog-footer" />
+      </el-dialog>
+    </div>
+    <!--实时车辆弹窗结束-->
+    <!--修改车牌号弹窗-->
+    <div class="rolemanage">
+      <el-dialog title="编辑车牌号" :visible.sync="dialogPlateVisible"
+        :destroy-on-close="true" @close="dialogClose">
+        <el-form :model="ruleForm" :rules="rules" ref="PlateForm" v-loading="loading">
+          <el-form-item label="编辑车牌号:" prop="plate">
+            <el-input v-model="ruleForm.plate" placeholder="请输入您的车牌号"></el-input>
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button class="exit" @click="dialogPlateVisible = false">取消</el-button>
+          <el-button type="primary" class="save" @click="handlePlate">确定</el-button>
+        </div>
+      </el-dialog>
+    </div>
+    <!--修改车牌号弹窗结束-->
   </div>
 </template>
 
 <script>
-import { swapInfo, swapRecord, alarmRecord } from '@/api/powerCharge'
+import { swapInfo, swapRecord, alarmRecord,CarOnline,EditPlate} from '@/api/powerCharge'
 import wsUrl from '../../../vue.config.js'
 import UserItem from './components/UserItem.vue'
 import PannelItem from './components/PannelItem.vue'
@@ -228,6 +346,7 @@ import QuarterChange from './components/QuarterChange.vue'
 import StatisticItem from './components/StatisticItem.vue'
 import '../../utils/jsmpeg.min'
 import { getToken } from '@/utils/auth'
+import { isLicensePlateNumberNER } from '@/utils'
 export default {
   name: 'PowerChangeMonitoring',
   components: {
@@ -257,7 +376,8 @@ export default {
         mileage: '—',
         batteryState: '—',
         swap: '—',
-        conState: 0
+        conState: '—',//监控120秒,1已连接 0未连接
+        sensorState:'—',//车辆到位状态,1已到位 0未到位
       },
       batteryInfo: {
         sn: '—',
@@ -334,7 +454,54 @@ export default {
       carRecord: [],
       // 告警记录
       alarmRecordList: [],
-      swapTime:null
+      swapTime:null,
+      totalSecond:120,//车辆倒计时
+      dialogCarlineVisible:false,//在线车辆弹窗
+      tableheight: 0, // 表格高度设置
+      CarlineList:[],//在线车辆列表
+      queryParams: {
+        page: 1, // 当前页
+        pageSize: 10, // 每页条数
+        orderByField: undefined, // 排序字段
+        orderByWays: 'desc'// 排序方式
+      },
+      dialogPlateVisible:false,//车牌号弹窗
+      loading: false,
+      heightTimer: false,
+      ruleForm:{
+        plate:undefined,
+      },
+      rules:{
+        plate: [
+            { required: true, message: '请输入车牌号', trigger: 'blur' },
+            { min: 6, max: 12, message: '格式错误', trigger: 'blur' }
+          ],
+      },//验证车牌号
+      cloundState:0,//云端连接状态
+      robotInfoVo:{},//机器人状态
+      forbidLockState:0,//机器人锁止状态
+    }
+  },
+  watch: {
+    tableheight(val) {
+      // 为了避免频繁触发resize函数导致页面卡顿,使用定时器
+      if (!this.heightTimer) {
+        // 一旦监听到的screenWidth值改变,就将其重新赋给data里的screenWidth
+        this.screenHeight = val
+        this.heightTimer = true
+        setTimeout(function() {
+          this.heightTimer = false
+        }, 400)
+      }
+    },
+    cloundState(val){
+      this.$bus.$emit('CloudState',val)
+    },
+    'vehicleInfo.conState'(val){
+      if(val==0){
+        this.getTotalSecond()
+        this.totalSecond=120
+      }
     }
   },
   computed: {
@@ -361,6 +528,14 @@ export default {
       } else {
         return '—'
       }
+    },
+    //车辆到位状态
+    Carsensor(){
+      if (this.vehicleInfo.sensorState != '—' && this.vehicleInfo.sensorState != null) {
+        return this.vehicleInfo.sensorState ? '已到位' : '未到位'
+      } else {
+        return '—'
+      }
     }
   },
   mounted() {
@@ -383,12 +558,94 @@ export default {
       // 开启定时器
       this.setTimerList()
     }
+    this.getTotalSecond()//倒计时
+    this.onLoadHeight()
+    this.changeWindow()
   },
   destroyed() {
     this.websocketOnClose()
     this.clearTimerList()
   },
   methods: {
+    /** 分页下一页 */
+    handleSizeChange(val) {
+      this.queryParams.pageSize = val
+    },
+    /** 分页选择页数 */
+    handleCurrentChange(val) {
+      this.queryParams.page = val
+    },
+    /* 设置初始视窗高度*/
+    onLoadHeight() {
+      this.$nextTick(() => {
+        this.tableheight = document.body.clientHeight - 460
+      })
+    },
+    /* 设置窗口变化高度*/
+    changeWindow() {
+      window.onresize = () => {
+        return (() => {
+          this.tableheight = document.body.clientHeight - 460
+        })()
+      }
+    },
+    //修改车牌号提交
+    handlePlate(){
+      if(this.ruleForm.plate==this.vehicleInfo.plate){
+        // this.$message({
+        //   type: 'warning',
+        //   message: '提交成功!'
+        // })
+        this.dialogPlateVisible=false
+      }else{
+        if(!isLicensePlateNumberNER(this.ruleForm.plate)){
+          this.$message({
+            type: 'warning',
+            message: '请填写新能源车牌号!'
+          })
+        }else{
+          EditPlate(this.ruleForm.plate).then((rs) => {
+            if(rs.code==0){
+              this.dialogPlateVisible=false
+              this.vehicleInfo.plate=this.ruleForm.plate
+              this.$message({
+                type: 'success',
+                message: '修改成功!'
+              })
+            }else{
+              this.$message({
+                type: 'error',
+                message: rs.msg
+              })
+            }
+          })
+          .catch(err => { console.error(err) })
+        }
+      }
+    },
+    // 清空表单数据车牌号
+    dialogClose() { },
+    //编辑车牌号弹窗
+    HandleEditPlate(plate){
+      this.dialogPlateVisible=true
+      this.ruleForm.plate=plate
+    },
+    //实时车辆弹窗
+    ShowCarline(){
+      this.dialogCarlineVisible=true
+      this.getCarOnline()
+    },
+    //车辆倒计时
+    getTotalSecond() {
+      if(this.vehicleInfo.conState==0){
+        let clock =  window.setInterval(() => {
+            this.totalSecond --;
+            if(this.totalSecond == 0 || this.vehicleInfo.conState==1){
+                window.clearInterval(clock);
+            }
+        }, 1000);       
+      }
+    },
     // 定时器列表
     setTimerList() {
       this.exchargeInfo()
@@ -409,6 +666,12 @@ export default {
         clearInterval(this.wsTimer)
       }
     },
+    //已连接站控车辆列表
+    getCarOnline(){
+      CarOnline().then((rs) => {
+        this.CarlineList = rs.data
+      })
+    },
     // 换电信息
     exchargeInfo() {
       swapInfo().then((rs) => {
@@ -444,7 +707,14 @@ export default {
     },
     websocketOnMessage(m) {
       const d = JSON.parse(m.data)
-      // console.log(d)
+      console.log(d)
+      //云端连接状态
+      if(d.cloundState){
+        this.cloundState=d.cloundState
+      }
+      if(d.forbidLockState<=1){
+        this.forbidLockState=d.forbidLockState
+      }
       //用户信息
       if (d.driverInfoVo) {
         this.driverInfo = d.driverInfoVo
@@ -457,6 +727,10 @@ export default {
       if (d.batteryInfo) {
         this.batteryInfo = d.batteryInfo
       }
+      //机器人状态
+      if (d.robotInfoVo) {
+        this.robotInfoVo = d.robotInfoVo
+      }
       // 换电流程动画
       if (d.swapProcess) {
         this.swapProcess = d.swapProcess
@@ -583,14 +857,23 @@ export default {
           display: flex;
           flex-direction: column;
           justify-content: space-between;
-          span {
+          .carVin {
             display: flex;
             flex-direction: row;
             justify-content: space-between;
+            margin: 0;
+            padding: 0;
+            label{
+              margin-bottom: 7px;
+            }
             label:last-child {
               text-align: right;
               color: #86edab;
               font-weight: 500;
+              margin-bottom: 0;
+            }
+            label:nth-child(2){
+               margin-bottom: 0;
             }
           }
           label {
@@ -603,6 +886,20 @@ export default {
             padding-left:12px;
             margin: 10px 0;
           }
+          .linkeState{
+            display: flex;
+            justify-content: flex-end;
+            align-items: center;
+            margin:0;
+            text-shadow: 0px 0px 4px rgba(39,69,201,0.5);
+            img{
+              padding-right: 3px;
+            }
+            .break{
+              color: #F53F3F;
+              font-weight: 500;
+            }
+          }
           .carinfo {
             display: flex;
             flex-direction: row;
@@ -804,4 +1101,36 @@ export default {
     }
   }
 }
+.charge-table-bottom {
+    width: 100%;
+    min-height: 100%;
+    background-color: #111827;
+    .item{
+      color: #86EDAB;
+    }
+    .disable{
+      color: #FF6E6E;
+    }
+    .iscar{
+      display: flex;
+      width: 100%;
+      align-items: center;
+      span{
+        padding-right: 8px;
+      }
+      img{
+        width: 20px;
+        height: 15px;
+        vertical-align: middle;
+      }
+    }
+}
+.pageblock {
+    padding: 15px 0px;
+    font-size:15px;
+    color: #C0C4CC;
+    span{
+      color: #86EDAB;
+    }
+}
 </style>

+ 3 - 3
vue.config.js

@@ -13,7 +13,7 @@ module.exports = {
   
   productionSourceMap: false,
   devServer: {
-    host: 'localhost',
+    host: '192.168.3.157',
     port: 808,
     open: true,
     overlay: {
@@ -29,13 +29,13 @@ module.exports = {
       },
       '/ws': {
         // target: `ws://192.168.3.177:8080/ws`,
-        target: `ws://zk.li-ai.com.cn:8080/ws`,
+        target: `ws://192.168.3.177:8080/ws`,
         ws: true,
         changeOrigin: true,
       },
       '/video':{
         // target: `ws://192.168.3.177:8082/`,
-        target: `ws://zk.li-ai.com.cn:8080/ws`,
+        target: `ws://192.168.3.177:8080/ws`,
         ws: true,
         changeOrigin: true,
       }