huangmp 4 лет назад
Родитель
Сommit
ed07111836

Разница между файлами не показана из-за своего большого размера
+ 239 - 100
package-lock.json


+ 3 - 0
package.json

@@ -38,7 +38,10 @@
     "three": "^0.128.0",
     "vue": "^2.6.10",
     "vue-axios": "^2.1.2",
+    "vue-contextmenujs": "^1.3.13",
     "vue-count-to": "^1.0.13",
+    "vue-drag-resize": "^1.5.4",
+    "vue-grid-layout": "^2.3.12",
     "vue-i18n": "^8.7.0",
     "vue-router": "^3.0.1",
     "vuex": "^3.1.1"

BIN
public/img/test/paking.png


+ 0 - 0
public/img/test/paking-empty.png → public/img/test/parking1-empty.png


+ 0 - 0
public/img/test/paking1.png → public/img/test/parking1.png


+ 0 - 0
public/img/test/paking2-empty.png → public/img/test/parking2-empty.png


+ 0 - 0
public/img/test/paking2.png → public/img/test/parking2.png


+ 17 - 0
src/api/estate/parkingarea.js

@@ -48,3 +48,20 @@ export const update = (row) => {
   })
 }
 
+export const saveLayout = (row) => {
+  return request({
+    url: '/api/cyzh-estate/parkingarea/saveLayout',
+    method: 'post',
+    data: row
+  })
+}
+
+export const getLayout = (parkingLotId) => {
+  return request({
+    url: '/api/cyzh-estate/parkingarea/getLayout',
+    method: 'get',
+    params: {
+      parkingLotId
+    }
+  })
+}

+ 10 - 0
src/api/estate/parkingspace.js

@@ -48,3 +48,13 @@ export const update = (row) => {
   })
 }
 
+export const bindCar = (carId, parkingSpaceId) => {
+  return request({
+    url: '/api/cyzh-estate/parkingspace/bindCar',
+    method: 'post',
+    params: {
+      carId,
+      parkingSpaceId
+    }
+  })
+}

+ 6 - 6
src/components/dialog/comps/visitor-detail.vue

@@ -1,8 +1,8 @@
 <template>
   <div>
-    <div class="contain-main" style="color: #ebebeb;">
+    <div class="contain-main" style="padding-top: 10px;">
      <div class="content" >
-       <div class="face" style="padding-bottom: 1.25rem;" v-if="detail.faceUrl">
+       <div class="face" style="padding-bottom:4%;" v-if="detail.faceUrl">
          <el-image style="width: 100px;height: 100px;" :src="detail.faceUrl" :preview-src-list="[detail.faceUrl]" z-index="999999"></el-image>
        </div>
         <label>人员姓名:{{detail.userName}}</label>
@@ -44,10 +44,10 @@
     display: flex;
     justify-content: center;
     align-items: center;
-    padding: 1.25rem;
-    margin-top: 1.25rem;
+    margin-top: 1%;
     flex-direction: column;
-    color: #ebebeb
+    color: #ebebeb;
+    padding-bottom: 0.625rem;
   }
 
   .content {
@@ -55,7 +55,7 @@
     flex-direction: column;
 
     label {
-      margin-bottom: 0.9375rem;
+      margin-bottom: 2.2%;
     }
   }
 </style>

+ 2 - 2
src/components/dialog/my-dialog.vue

@@ -118,8 +118,8 @@
 
     .dialog {
       position: relative;
-      width: 46%;
-      height: 56%;
+      width: 48%;
+      height: 58%;
       background-color: rgba(4, 25, 50, .3);
 
       .close {

+ 50 - 1
src/main.js

@@ -39,7 +39,7 @@ import animated from 'animate.css'
 Vue.use(animated)
 
 Vue.prototype.$animateCss = (element, animationName, time) => {
-  new Promise((resolve, reject) => {
+  new Promise((resolve) => {
     const node = document.querySelector(element);
     node.classList.add('animate__animated', animationName);
     if (time) {
@@ -172,6 +172,55 @@ Vue.prototype.$addStorageEvent = function(type, key, data) {
   }
 }
 
+//判空函数
+Vue.prototype.$isEmpty=function(value){
+	switch (typeof value) {
+		case 'undefined':
+			return true;
+		case 'string':
+			if(value=='undefined') return true
+			if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
+			break;
+		case 'boolean':
+			if (!value) return true;
+			break;
+		case 'number':
+			if (0 === value || isNaN(value)) return true;
+			break;
+		case 'object':
+			if (null === value || value.length === 0) return true;
+			for (var i in value) {
+				return false;
+			}
+			return true;
+	}
+	return false;
+}
+
+Vue.prototype.$isNotEmpty=function(value){
+	switch (typeof value) {
+		case 'undefined':
+			return false;
+		case 'string':
+			if(value=='undefined') return false
+			if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return false;
+			break;
+		case 'boolean':
+			if (!value) return false;
+			break;
+		case 'number':
+			if (0 === value || isNaN(value)) return false;
+			break;
+		case 'object':
+			if (null === value || value.length === 0) return false;
+			for (var i in value) {
+				return true;
+			}
+			return false;
+	}
+	return true;
+}
+
 new Vue({
   router,
   store,

+ 1 - 1
src/page/login/userlogin.vue

@@ -41,7 +41,7 @@
         </el-row>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" size="small" @click.native.prevent="handleLogin" class="login-submit">
+        <el-button type="primary" size="small" @click.native.prevent="handleLogin" class="login-submit" >
           {{$t('login.submit')}}
         </el-button>
       </el-form-item>

+ 2 - 1
src/styles/login.scss

@@ -123,7 +123,8 @@
   font-weight: 300;
   color: #ddd;
   cursor: pointer;
-  margin-top: 30px;
+  margin-top: 1.25rem;
+  margin-bottom: 10px;
   font-family: "neo";
   transition: 0.25s;
   float: left;

+ 92 - 18
src/util/util.js

@@ -1,4 +1,6 @@
-import {validatenull} from './validate'
+import {
+  validatenull
+} from './validate'
 //表单序列化
 export const serialize = data => {
   let list = [];
@@ -54,16 +56,83 @@ export const deepClone = data => {
   }
   return obj;
 };
+
 /**
- * 设置灰度模式
+ * 生成随机数
  */
-export const toggleGrayMode = (status) => {
-  if (status) {
-    document.body.className = document.body.className + ' grayMode';
+export const guid = (len = 32, firstU = true, radix = null) => {
+    let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
+    let uuid = [];
+    radix = radix || chars.length;
+
+    if (len) {
+      // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+      for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
+    } else {
+      let r;
+      // rfc4122标准要求返回的uuid中,某些位为固定的字符
+      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
+      uuid[14] = '4';
+
+      for (let i = 0; i < 36; i++) {
+        if (!uuid[i]) {
+          r = 0 | Math.random() * 16;
+          uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
+        }
+      }
+    }
+    // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
+    if (firstU) {
+      uuid.shift();
+      return 'u' + uuid.join('');
+    } else {
+      return uuid.join('');
+    }
+  };
+
+/**
+ * 生成随机ID
+ */
+export const guidId = (len = 19, first = true, radix = null) => {
+  let chars = '0123456789'.split('');
+  let uuid = [];
+  radix = radix || chars.length;
+
+  if (len) {
+    // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+    for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
   } else {
-    document.body.className = document.body.className.replace(' grayMode', '');
+    let r;
+    // rfc4122标准要求返回的uuid中,某些位为固定的字符
+    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
+    uuid[14] = '4';
+
+    for (let i = 0; i < 36; i++) {
+      if (!uuid[i]) {
+        r = 0 | Math.random() * 16;
+        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
+      }
+    }
+  }
+  // 是否以1作为首字母
+  if (first) {
+    uuid.shift();
+    return '1' + uuid.join('');
+  } else {
+    return uuid.join('');
   }
 };
+
+  /**
+   * 设置灰度模式
+   */
+  export const toggleGrayMode = (status) => {
+    if (status) {
+      document.body.className = document.body.className + ' grayMode';
+    } else {
+      document.body.className = document.body.className.replace(' grayMode', '');
+    }
+  };
 /**
  * 设置主题
  */
@@ -114,16 +183,16 @@ export const listenfullscreen = (callback) => {
     callback()
   }
 
-  document.addEventListener("fullscreenchange", function () {
+  document.addEventListener("fullscreenchange", function() {
     listen();
   });
-  document.addEventListener("mozfullscreenchange", function () {
+  document.addEventListener("mozfullscreenchange", function() {
     listen();
   });
-  document.addEventListener("webkitfullscreenchange", function () {
+  document.addEventListener("webkitfullscreenchange", function() {
     listen();
   });
-  document.addEventListener("msfullscreenchange", function () {
+  document.addEventListener("msfullscreenchange", function() {
     listen();
   });
 };
@@ -201,7 +270,8 @@ export const diff = (obj1, obj2) => {
   delete obj1.close;
   var o1 = obj1 instanceof Object;
   var o2 = obj2 instanceof Object;
-  if (!o1 || !o2) { /*  判断不是对象  */
+  if (!o1 || !o2) {
+    /*  判断不是对象  */
     return obj1 === obj2;
   }
 
@@ -227,7 +297,7 @@ export const diff = (obj1, obj2) => {
 export const findByvalue = (dic, value) => {
   let result = '';
   if (validatenull(dic)) return value;
-  if (typeof (value) == 'string' || typeof (value) == 'number' || typeof (value) == 'boolean') {
+  if (typeof(value) == 'string' || typeof(value) == 'number' || typeof(value) == 'boolean') {
     let index = 0;
     index = findArray(dic, value);
     if (index != -1) {
@@ -278,12 +348,16 @@ export const openWindow = (url, title, w, h) => {
   const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
   const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
 
-  const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width
-  const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height
+  const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document
+    .documentElement.clientWidth : screen.width
+  const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document
+    .documentElement.clientHeight : screen.height
 
   const left = ((width / 2) - (w / 2)) + dualScreenLeft
   const top = ((height / 2) - (h / 2)) + dualScreenTop
-  const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left)
+  const newWindow = window.open(url, title,
+    'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' +
+    w + ', height=' + h + ', top=' + top + ', left=' + left)
 
   // Puts focus on the newWindow
   if (window.focus) {
@@ -319,7 +393,7 @@ export const downloadFileBlob = (path, name) => {
   xhr.open('get', path);
   xhr.responseType = 'blob';
   xhr.send();
-  xhr.onload = function () {
+  xhr.onload = function() {
     if (this.status === 200 || this.status === 304) {
       // 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob
       if ('msSaveOrOpenBlob' in navigator) {
@@ -349,11 +423,11 @@ export const downloadFileBase64 = (path, name) => {
   xhr.open('get', path);
   xhr.responseType = 'blob';
   xhr.send();
-  xhr.onload = function () {
+  xhr.onload = function() {
     if (this.status === 200 || this.status === 304) {
       const fileReader = new FileReader();
       fileReader.readAsDataURL(this.response);
-      fileReader.onload = function () {
+      fileReader.onload = function() {
         const a = document.createElement('a');
         a.style.display = 'none';
         a.href = this.result;

+ 354 - 0
src/views/dashboard/parkingmng/comps/operate-list.vue

@@ -0,0 +1,354 @@
+<template>
+  <div style="margin-top: 0.625rem;" >
+    <div class="add" @click="$refs.crud.rowAdd()" v-if="$isEmpty(parkList)">
+      <i class="el-icon-circle-plus-outline" style="color: #3b8ff4;font-size: 3.125rem;"></i>
+      <span>添加车场</span>
+    </div>
+
+    <div class="operate_list" v-else>
+      <div @click="parkingClick(item,index)" v-for="(item,index) in parkList" :key="index"
+        style="padding-right: 1.25rem;">
+        <el-popover placement="bottom" title="" width="300" trigger="hover">
+          <div class="tips" style="position: relative;">
+            <div style="position: absolute;right: 0rem;top: -10px">
+              <i class="el-icon-edit-outline" style="margin-left: 0.25rem;font-weight: 800;" @click="rowEdit(item)"></i>
+            </div>
+            <div style="margin-top: 0.625rem;">
+              <label>车场名称:</label>
+              {{item.parkName}}
+            </div>
+            <div>
+              <label>车场编号:</label>
+              {{item.parkKey}}
+            </div>
+            <div>
+              <label>所在区域:</label>
+              {{item.residentialName || '暂无信息'}}
+            </div>
+            <div>
+              <label>车位总数:</label>
+              {{item.spaceTotal}}
+            </div>
+            <div>
+              <label>联系人姓名:</label>
+              {{item.parkLinkman}}
+            </div>
+            <div>
+              <label>联系人电话:</label>
+              {{item.parkTel}}
+            </div>
+          </div>
+          <el-button slot="reference" :type="activedIndex==index?'primary':''" size="medium">{{item.parkName}}
+          </el-button>
+        </el-popover>
+      </div>
+
+      <div @click="$refs.crud.rowAdd()" v-if="$isNotEmpty(parkList)"
+        style="color: #3b8ff4;display: flex;justify-content: center;align-items: center;font-size: 30px;">
+        <i class="el-icon-circle-plus-outline"></i>
+      </div>
+
+
+      <div class="edit-list center">
+        <div class="center">
+          <div v-show="editShow" style="display: flex;margin-right: 0.625rem;overflow: hidden;">
+            <el-button v-for="(item,index) in operateBtnList" :key="index" @click="operateClick(item,index)" size="mini"
+              :type="operateIndex==index?'primary':''" class="animate__animated animate__faster animate__fadeInRight">
+              {{item.name}}
+            </el-button>
+          </div>
+          <el-button @click="editShow=!editShow" size="mini" icon="el-icon-edit" type="primary" circle></el-button>
+        </div>
+
+        <div class="center" style="margin-left: 0.625rem;">
+          <div v-show="searchshow" style="margin-right: 0.625rem;overflow: hidden;">
+            <el-input placeholder="请输入车位编号/车牌号码" class="animate__animated animate__faster animate__fadeInRight"
+              style="width: 260px;" v-model="searchKey" >
+              <el-button size="mini" slot="append" icon="el-icon-search" @click="search"></el-button>
+            </el-input>
+          </div>
+          <el-button size="mini" icon="el-icon-search" type="primary" circle @click="searchshow=!searchshow">
+          </el-button>
+        </div>
+      </div>
+    </div>
+
+
+
+    <!-- 添加车场 -->
+    <avue-crud v-show="false" :option="option" @row-update="rowUpdate" :table-loading="loading" :data="data"
+      :page.sync="page" v-model="form" ref="crud" @row-save="rowSave">
+      <template slot="mapSelectForm" slot-scope="scope">
+        <div>
+          <el-button @click="mapVisible = true"> 选择地址</el-button>
+          <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false"
+            :visible.sync="mapVisible" title="编辑地址" width="80%">
+            <editPolygonMap v-if="mapVisible" :editForm.sync="scope.row" :region.sync="scope.row.parkAdd"
+              :latitude.sync="scope.row.parkLatitude" :longitude.sync="scope.row.parkLongitude"
+              :visible.sync="mapVisible"></editPolygonMap>
+          </el-dialog>
+        </div>
+      </template>
+    </avue-crud>
+
+
+    <!-- 添加区域 -->
+    <el-dialog title="添加区域" :visible.sync="addLayoutVisible" :append-to-body="true">
+      <el-form>
+        <el-form-item label="区域名称" required>
+          <el-input v-model="parkingAreaName" autocomplete="off" placeholder="请输入区域名称"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="addLayoutVisible = false">取 消</el-button>
+        <el-button type="primary" @click="addLayout">确 定</el-button>
+      </div>
+    </el-dialog>
+
+
+
+  </div>
+</template>
+
+<script>
+  import {
+    deepClone
+  } from "@/util/util.js"
+  import {
+    getList,
+    add,
+    remove,
+    update
+  } from "@/api/estate/parkinglot";
+  import option from "@/views/parkingmng/option/parkinglotmng-option.js"
+  import editPolygonMap from "@/components/residential/editPolygonMap";
+  export default {
+    name: '',
+    inject: ['parkingLayout'],
+    components: {
+      editPolygonMap
+    },
+    data() {
+      return {
+        //搜索
+        searchKey: '',
+        searchshow: false,
+        //区域名称
+        addLayoutVisible: false,
+        parkingAreaName: '',
+        //停车场
+        parkList: [],
+        activedIndex: 0,
+        //操作
+        editShow: true,
+        //操作按钮组
+        operateIndex: -1,
+        operateBtnList: [{
+            name: '网格显隐',
+            event: this.showGrid
+          },
+          {
+            name: '添加区域',
+            event: () => {
+              this.addLayoutVisible = true
+            }
+          },
+          {
+            name: '编辑区域',
+            event: this.editLayout
+          },
+          {
+            name: '保存布局',
+            event: null
+          }
+        ],
+        // 新增车场
+        mapVisible: false,
+        option: option(this)
+      };
+    },
+    async created() {
+      await this.getParkingLot()
+      this.$emit('initDone')
+    },
+    methods: {
+      search() {
+        if (this.$isEmpty(this.searchKey)) {
+          this.$message.error('请输入车位编号或者车牌号码')
+          return
+        }
+        this.$emit('search', this.searchKey)
+      },
+      async getParkingLot() {
+        let records = (await getList()).data.data.records
+        if (this.$isNotEmpty(records)) {
+          this.parkList = records
+          this.parkingLayout.parkingLotObj = this.parkList[0]
+        }
+      },
+      showEdit() {
+        this.editShow = true
+      },
+      //添加车场
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.getParkingLot()
+          this.$message({
+            type: "success",
+            message: "添加成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      //删除车场
+      rowDel(id) {
+        this.$confirm("确定将选择数据删除?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return remove(id);
+          })
+          .then(() => {
+            this.getParkingLot()
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      //更新车场
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.getParkingLot()
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowEdit(item) {
+        this.$refs.crud.rowEdit(item)
+      },
+      parkingClick(item, index) {
+        this.activedIndex = index
+        this.parkingLayout.parkingLotObj = this.parkList[index]
+      },
+      operateClick(item, index) {
+        if (item.name == '保存布局') {
+          this.$emit('save')
+          return
+        }
+        if (this.operateIndex == index) {
+          this.operateIndex = -1
+        } else {
+          this.operateIndex = index
+        }
+        item.event(item)
+      },
+      //网格显隐
+      showGrid() {
+        let msg = this.parkingLayout.gridShow ? '已隐藏网格' : '已显示网格'
+        this.$message.success(msg)
+        this.parkingLayout.gridShow = !this.parkingLayout.gridShow
+      },
+      //添加布局
+      addLayout() {
+        if (this.$isEmpty(this.parkingAreaName)) {
+          this.$message.error('请输入区域名称')
+          return
+        }
+        let tmp = deepClone(this.parkingLayout.obj)
+        tmp.name = this.parkingAreaName
+        tmp.parkingLotId = this.parkingLayout.parkingLotObj.id
+        this.parkingLayout.parkingAreaList.push(tmp)
+        this.$message.success("添加成功")
+        this.parkingAreaName = ''
+        this.addLayoutVisible = false
+        this.operateIndex = 1
+        this.editShow = true
+        this.parkingLayout.disabled = true
+      },
+      //删除布局
+      delLayout(item) {
+        item.name = item.name == '删除布局' ? '取消删除' : '删除布局'
+        this.parkingLayout.delLayoutShow = !this.parkingLayout.delLayoutShow
+        if (this.parkingLayout.delLayoutShow) {
+          this.$message.success("请点击删除图标删除相应布局")
+        }
+      },
+      //编辑布局
+      editLayout() {
+        let msg = !this.parkingLayout.disabled ? '已启用拖拽布局' : '已禁止拖拽布局'
+        this.parkingLayout.disabled = !this.parkingLayout.disabled
+        this.$message.success(msg)
+      },
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .center {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .tips {
+    padding: 5px;
+
+    div {
+      display: flex;
+      padding-top: 0.625rem;
+      font-size: 14px;
+    }
+  }
+
+  .func {
+    margin-bottom: -0.625rem;
+    margin-top: 0.625rem;
+    box-sizing: border-box;
+    display: flex;
+    justify-content: flex-end;
+  }
+
+  .add {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin: 1.875rem;
+    color: #3b8ff4;
+
+    i {
+      font-size: 3.125rem;
+    }
+
+    i:active {
+      transform: scale(1.05);
+    }
+
+    span {
+      padding-left: 0.625rem;
+    }
+  }
+
+  .operate_list {
+    position: relative;
+    padding-top: 0.625rem;
+    display: flex;
+  }
+
+  .edit-list {
+    position: absolute;
+    right: 0;
+    bottom: -10px;
+  }
+</style>

+ 218 - 0
src/views/dashboard/parkingmng/comps/paking-box.vue

@@ -0,0 +1,218 @@
+<template>
+  <div style="width: 100%;height: 100%;position: relative;z-index: 9999999999999999;">
+    <el-button class="delLayoutClass" @click.stop="delLayout(item)" type="danger" icon="el-icon-close" size="mini"
+      style="padding: 0.26rem;" circle></el-button>
+    <div class="paking-box" style="position:relative;">
+      <div v-if="$isNotEmpty(item.pakingSpaceList)" class="car" :style="changePakingSpaceParams(item)"
+        v-for="(item1,index1) in item.pakingSpaceList" :key="index1">
+        <el-popover placement="bottom" title="" width="200" trigger="click">
+          <div class="tips" style="position: relative;">
+            <div style="position: absolute;right: 0rem;top: -10px">
+              <i class="el-icon-delete" style="font-weight: 800;"></i>
+              <i class="el-icon-edit-outline" style="margin-left: 0.25rem;font-weight: 800;"></i>
+            </div>
+            <div>
+              <label>停车场:</label>
+              {{item1.parkingLotName}}
+            </div>
+            <div>
+              <label>车位号:</label>
+              {{item1.pakingSpaceNo}}
+            </div>
+            <div>
+              <label>车牌号:</label>
+              <span v-if="item1.carNo">{{item1.carNo}}</span>
+              <span style="color: red;" v-else>车位为空</span>
+            </div>
+            <div>
+              <label>车位类型:</label>
+              {{item1.pakingSpaceType}}
+            </div>
+          </div>
+          <div slot="reference" :style="changePakingSpaceParams(item)">
+            <img :src="carEmptyImg(item)">
+          </div>
+        </el-popover>
+      </div>
+
+      <div class="car" :style="changePakingSpaceParams(item)">
+        <i class="el-icon-circle-plus-outline" @click.stop="addPakingSpace(item)"></i>
+        <i class="el-icon-edit-outline" @click.stop="editPopoverVisible(item)"></i>
+      </div>
+    </div>
+
+    <el-dialog style="z-index: 99999;" :close-on-click-modal="false" :append-to-body="true"
+      :visible.sync="popoverVisible" width="20.5%">
+      <div class="popoverContent" style="justify-content: flex-start;">
+        <el-button style="margin:0.25rem" v-for="(item2,index2) in tipsBtnList" :key="index2"
+          @click="popoverClick(item,item2)" type="primary" size="mini" plain>{{item2.name}}</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  export default {
+    props: {
+      item: Object
+    },
+    computed: {
+      carEmptyImg() {
+        return item => {
+          let arr = item.pakingSpaceParams.split(",")
+          let img = arr[0] > arr[1] ? '/img/test/paking2-empty.png' : '/img/test/paking-empty.png'
+          console.log(img);
+          return img
+        }
+      }
+    },
+    data() {
+      return {
+        popoverVisible: false,
+        operatePopoverItem: {},
+        tipsBtnList: [{
+            name: '批量添加',
+            event: () => {
+              this.operateType = 0
+              this.operateDialogShow = true
+            }
+          },
+          {
+            name: '修改宽高',
+            event: () => {
+              this.$message.success('操作成功')
+            }
+          },
+          {
+            name: '车位翻转',
+            event: () => {
+              this.changePakingSpaceParams(this.operatePopoverItem, true)
+            }
+          },
+          {
+            name: '重置车位',
+            event: (item) => {
+              this.num = 0
+              item.pakingSpaceCount = 0
+              this.$message.success('操作成功')
+            }
+          },
+        ]
+      };
+    },
+    methods: {
+      addPakingSpace(item) {
+        let tmp = deepClone(this.pakingSpaceObj)
+        tmp.pakingAreaId = item.id
+        tmp.parkingLotId = this.parkingLotObj.id
+        tmp.parkingLotName = this.parkingLotObj.parkName
+        tmp.pakingSpaceNo = guid(12)
+        item.pakingSpaceList.push(tmp)
+      },
+      delLayout(item) {
+        item.show = false
+      },
+      
+      changePakingSpaceParams(item, flag = false) {
+        let arr = item.pakingSpaceParams.split(',')
+        if (flag) {
+          let tmp = arr[0]
+          arr[0] = arr[1]
+          arr[1] = tmp
+          item.pakingSpaceParams = arr.join(',')
+        }
+        let flexStyle = arr[0] > arr[1] ? 'flex-direction: row' : 'flex-direction: column'
+        let pakingSpaceStyle = `width:${arr[0]}px;height:${arr[1]}px;${flexStyle}`
+        return pakingSpaceStyle
+      },
+      popoverClick(item, item2) {
+        item2.event(item)
+        this.popoverVisible = false
+      },
+      editPopoverVisible(item) {
+        this.popoverVisible = true
+        this.operatePopoverItem = item
+      },
+      operateDialogConfirm() {
+        let num = parseInt(this.num)
+        for (var i = 0; i < num; i++) {
+          let tmp = this.pakingSpaceObj
+          if (i % 2 == 0) {
+            tmp.carNo = guid(6)
+          }
+          tmp.parkingLotId = this.parkingLotObj.id
+          tmp.parkingLotName = this.parkName.name
+          tmp.pakingSpaceNo = guid(12)
+          this.operatePopoverItem.pakingSpaceList.push(tmp)
+          tmp.carNo = ''
+        }
+        this.operateDialogShow = false
+        this.$forceUpdate()
+        this.$message.success('操作成功')
+      },
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .delLayoutClass {
+    position: absolute;
+    right: -20px;
+    top: -20px;
+    font-weight: 800;
+  }
+
+  .tips {
+    padding: 10px;
+
+    div {
+      display: flex;
+      padding-top: 0.625rem;
+      font-size: 14px;
+    }
+
+    label {
+      width: 70px;
+    }
+  }
+
+  .paking-box {
+    z-index: 99;
+    padding: 0.3125rem;
+    position: relative;
+    justify-content: center;
+    align-items: center;
+    box-sizing: border-box;
+    padding: 0.3125rem;
+    display: flex;
+    flex-wrap: wrap;
+    width: 100%;
+    height: 100%;
+    background: #f5f5f5;
+    overflow: scroll;
+  }
+
+  .car {
+    box-sizing: border-box;
+    margin-right: 0.3125rem;
+    background-color: #c4e1ff;
+    color: #052252;
+    z-index: 99999999;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-around;
+    align-items: center;
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .popoverContent {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: center;
+    align-items: center;
+  }
+</style>

+ 593 - 0
src/views/dashboard/parkingmng/comps/paking-layout.vue

@@ -0,0 +1,593 @@
+<template>
+  <div class="page animate__animated animate__faster animate__fadeInLeft">
+    <more title="车位使用情况" nomore></more>
+    <operateList @save="save" @search="search" ref="operateList" @initDone="initDone"></operateList>
+
+    <div v-show="$isNotEmpty(parkingLotObj)" class="parking-layout" @click="activedIndex=-1;closePopover"
+      id="parkingLayout"
+      :style="$isEmpty(parkingAreaList)?'display: flex;justify-content: center;align-items: center;':''">
+      <div class="parking-grid" v-if="gridShow"></div>
+
+      <div class="addParkingArea" style="z-index: 999999999999999999999;"
+        @click="$refs.operateList.addLayoutVisible=true" v-if="$isEmpty(parkingAreaList)">
+        <i class="el-icon-circle-plus-outline" style="color: #3b8ff4;font-size: 3.125rem;"></i>
+        <span>添加区域</span>
+      </div>
+      <VueDragResize class="animate__animated animate__faster animate__zoomIn" v-if="item.show&&!enlarge"
+        :isDraggable="disabled" :isResizable="disabled" v-for="(item, index) in parkingAreaList" :key="index"
+        :w="item.width" :h="item.height" :x="item.x" :y="item.y" :z="(index+1)" :parentW="listWidth"
+        :parentH="listHeight" :parentLimitation="true" :snapToGrid="true" :gridX="10" :gridY="10"
+        @resizestop="rectStop($event, index)" @dragstop="rectStop($event, index)">
+        <div @click.stop="activedIndex=index"
+          style="width: 100%;height: 100%;position: relative;z-index: 9999999999999999;">
+          <el-button class="delLayoutClass" @click.stop="delLayout(item)" v-if="delLayoutShow" type="danger"
+            icon="el-icon-close" size="mini" style="padding: 0.26rem;" circle></el-button>
+          <el-button v-if="activedIndex==index&&!delLayoutShow&&!disabled" class="delLayoutClass"
+            @click.stop="enlarge=true;enlargeItem=item;" type="primary" icon="el-icon-zoom-in" size="mini"
+            style="padding: 0.26rem;" circle></el-button>
+
+          <div id="parkingBox" class="parking-box" style="position:relative;">
+            <div class="watermark">
+              {{item.name}}
+            </div>
+            <div @click.stop="showPopover(item1)" 
+              v-if="$isNotEmpty(item.parkingSpaceList)" class="car" :style="changeParkingSpaceParams(item)"
+              v-for="(item1,index1) in item.parkingSpaceList" :key="index1">
+              <el-popover placement="bottom" title="" width="230" v-model="item1.popoverShow" trigger="manual">
+                <div class="tips" style="position: relative;">
+                  <div style="position: absolute;right: 0rem;top: -10px">
+                    <i class="el-icon-delete" style="font-weight: 800;"></i>
+                    <i class="el-icon-edit-outline" style="margin-left: 0.25rem;font-weight: 800;"></i>
+                  </div>
+                  <div>
+                    <label>停车场:</label>
+                    {{parkingLotObj.parkName}}
+                  </div>
+                  <div>
+                    <label>车位编号:</label>
+                    {{item1.number}}
+                  </div>
+                  <div style="display: flex;">
+                    <label>车牌号码:</label>
+                    <span v-if="item1.carNo">{{item1.carNo}}
+                      <span v-if="$isNotEmpty(item1.id)" class="bind" @click.stop="parkingSpaceItem=item1;tableShow=true">换绑</span>
+                    </span>
+                    <span style="color: red;justify-content: center;display: flex;align-items: center;" v-else>
+                      车位为空
+                      <span v-if="$isNotEmpty(item1.id)" class="bind" @click.stop="parkingSpaceItem=item1;tableShow=true">绑定</span>
+                    </span>
+                  </div>
+                </div>
+                <div slot="reference" :style="changeParkingSpaceParams(item)">
+                  <img :src="carEmptyImg(item,item1)">
+                </div>
+              </el-popover>
+            </div>
+
+            <div class="car" :style="changeParkingSpaceParams(item)">
+              <i class="el-icon-circle-plus-outline" @click.stop="addParkingSpace(item)"></i>
+              <el-popover placement="bottom" title="" width="270" trigger="hover">
+                <div class="popoverContent" style="justify-content: center;">
+                  <el-button style="margin:0.25rem" v-for="(item2,index2) in tipsBtnList" :key="index2"
+                    @click="popoverClick(item,item2)" type="primary" size="mini" plain>{{item2.name}}</el-button>
+                </div>
+                <i slot="reference" class="el-icon-edit-outline"></i>
+                <!-- <i slot="reference" class="el-icon-edit-outline" @click.stop="editPopoverVisible(enlargeItem)"></i> -->
+              </el-popover>
+            </div>
+          </div>
+        </div>
+      </VueDragResize>
+
+      <VueDragResize class="animate__animated animate__faster "
+        :class="enlargeAreaShow()?'animate__zoomIn':'animate__zoomOut'" v-if="enlargeAreaShow()" :isDraggable="false"
+        :isResizable="false" :w="(listWidth - 20)" :h="(listHeight - 20)" :x="10" :y="10" :parentW="listWidth"
+        :parentH="listHeight" :parentLimitation="true" :snapToGrid="true" :gridX="20" :gridY="20"
+        @resizestop="rectStop($event, index)" @dragstop="rectStop($event, index)">
+        <div style="width: 100%;height: 100%;position: relative;z-index: 9999999999999999;">
+          <el-button class="delLayoutClass" @click.stop="enlarge=false;enlargeItem={}" type="primary"
+            icon="el-icon-zoom-out" size="mini" style="padding: 0.26rem;" circle></el-button>
+          <div class="parking-box" style="position:relative;">
+            <div v-if="$isNotEmpty(enlargeItem.parkingSpaceList)" class="car"
+              :style="changeParkingSpaceParams(enlargeItem)" v-for="(item1,index1) in enlargeItem.parkingSpaceList"
+              :key="index1">
+              <el-popover placement="bottom" title="" width="230" trigger="hover">
+                <div class="tips" style="position: relative;">
+                  <div style="position: absolute;right: 0rem;top: -10px">
+                    <i class="el-icon-delete" style="font-weight: 800;"></i>
+                    <i class="el-icon-edit-outline" style="margin-left: 0.25rem;font-weight: 800;"></i>
+                  </div>
+                  <div>
+                    <label>停车场:</label>
+                    {{parkingLotObj.parkName}}
+                  </div>
+                  <div>
+                    <label>车位编号:</label>
+                    {{item1.number}}
+                  </div>
+                  <div style="display: flex;">
+                    <label>车牌号码:</label>
+                    <span v-if="item1.carNo">{{item1.carNo}}
+                      <span v-if="item1.id" class="bind" @click="parkingSpaceItem=item1;tableShow=true">换绑</span>
+                    </span>
+                    <span style="color: red;justify-content: center;display: flex;align-items: center;" v-else>
+                      车位为空
+                      <span v-if="item1.id" class="bind" @click="parkingSpaceItem=item1;tableShow=true">绑定</span>
+                    </span>
+                  </div>
+                </div>
+                <div slot="reference" :style="changeParkingSpaceParams(enlargeItem)">
+                  <img :src="carEmptyImg(enlargeItem,item1)">
+                </div>
+              </el-popover>
+            </div>
+          </div>
+        </div>
+      </VueDragResize>
+
+    </div>
+
+    <el-dialog style="z-index: 99999;" :close-on-click-modal="false" :append-to-body="true"
+      :visible.sync="popoverVisible" width="20.5%">
+      <div class="popoverContent" style="justify-content: flex-start;">
+        <el-button style="margin:0.25rem" v-for="(item2,index2) in tipsBtnList" :key="index2"
+          @click="popoverClick(item,item2)" type="primary" size="mini" plain>{{item2.name}}</el-button>
+      </div>
+    </el-dialog>
+
+
+    <el-dialog title="批量添加车位" style="z-index: 99999;" :close-on-click-modal="false" :append-to-body="true"
+      :visible.sync="operateDialogShow">
+      <el-form>
+        <el-form-item label="添加数量">
+          <el-input v-model="num" autocomplete="off" type="number"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="operateDialogShow = false">取 消</el-button>
+        <el-button type="primary" @click="operateDialogConfirm">确 定</el-button>
+      </div>
+    </el-dialog>
+
+
+    <!-- 绑定车辆 -->
+    <el-dialog v-if="$isNotEmpty(parkingSpaceItem)" title="绑定车辆" @close="tableShow=false" append-to-body width="50%"
+      :close-on-click-modal="false" :visible.sync="tableShow">
+      <car-table ref="car" @bindCar="bindCar"></car-table>
+    </el-dialog>
+
+
+  </div>
+</template>
+<script>
+  import {
+    deepClone,
+    guid,
+  } from '@/util/util.js'
+  import {
+    saveLayout,
+    getLayout
+  } from '@/api/estate/parkingarea.js'
+  import VueDragResize from 'vue-drag-resize';
+  import operateList from "./operate-list.vue"
+  import more from "@/components/more.vue"
+  import carTable from "../dialog/car-table.vue"
+  import {
+    bindCar
+  } from '@/api/estate/parkingspace.js'
+  export default {
+    components: {
+      VueDragResize,
+      operateList,
+      more,
+      carTable
+    },
+    provide() {
+      return {
+        parkingLayout: this
+      };
+    },
+    data() {
+      return {
+        //搜索匹配的项
+        searchList: [],
+        //绑定车辆
+        tableShow: false,
+        parkingSpaceItem: '',
+
+        //激活的项
+        activedIndex: -1,
+        enlarge: false,
+        enlargeItem: {},
+
+        listWidth: 0,
+        listHeight: 0,
+        //当前车场
+        parkingLotObj: {},
+        //是否显示网格
+        gridShow: true,
+        //是否允许拖拽布局
+        disabled: false,
+        //是否显示删除布局按钮
+        delLayoutShow: false,
+        //停车区域
+        originalParkingAreaList: "",
+        parkingAreaList: [],
+        obj: {
+          id: '',
+          name: '',
+          //车场id
+          parkingLotId: '',
+          parkingSpaceParams: '35,60',
+          parkingSpaceList: [],
+          show: true,
+          width: 200,
+          height: 200,
+          x: 10,
+          y: 10
+        },
+        //车位
+        parkingSpaceObj: {
+          id: '',
+          //车场区域id
+          parkingAreaId: '',
+          //车场id
+          parkingLotId: '',
+          //车场名
+          parkingLotName: '',
+          //车位编号
+          number: '',
+          //车辆id
+          carId: '',
+          //车牌号
+          carNo: '',
+          popoverShow: false
+        },
+        // 操作栏
+        num: 0,
+        operatePopoverItem: {},
+        operateDialogShow: false,
+        popoverVisible: false,
+        tipsBtnList: [{
+            name: '批量添加',
+            event: () => {
+              this.operateType = 0
+              this.operateDialogShow = true
+            }
+          },
+          {
+            name: '修改宽高',
+            event: () => {
+              this.$message.success('操作成功')
+            }
+          },
+          {
+            name: '车位翻转',
+            event: () => {
+              this.changeParkingSpaceParams(this.operatePopoverItem, true)
+            }
+          }
+        ]
+      }
+    },
+    computed: {
+      carEmptyImg() {
+        return (item, item1) => {
+          let arr = item.parkingSpaceParams.split(",")
+          let flag = arr[0] > arr[1]
+          let carEmpty = this.$isEmpty(item1.carNo)
+          if (flag) {
+            if (carEmpty) {
+              return '/img/test/parking2-empty.png'
+            } else {
+              return '/img/test/parking2.png'
+            }
+          } else {
+            if (carEmpty) {
+              return '/img/test/parking1-empty.png'
+            } else {
+              return '/img/test/parking1.png'
+            }
+          }
+        }
+      },
+    },
+    methods: {
+      editPopoverShow() {
+        this.parkingAreaList.forEach(item => {
+          item.parkingSpaceList.forEach(item1 => item1.popoverShow = false)
+        })
+      },
+      showPopover(data) {
+        let flag=data.popoverShow
+        this.editPopoverShow()
+        data.popoverShow=!flag
+        setTimeout(()=>{
+          data.popoverShow=false
+        },3000)
+      },
+      search(searchKey) {
+        this.searchList = []
+        this.parkingAreaList.forEach((item, index) => {
+          item.parkingSpaceList.forEach((item1, index1) => {
+            if (item1.number.indexOf(searchKey) >= 0 || item1.carNo.indexOf(searchKey) >= 0) {
+              let arr = [index, index1]
+              this.searchList.push(arr)
+              item1.popoverShow = true
+            } else {
+              item1.popoverShow = false
+            }
+          })
+        })
+        if (this.$isEmpty(this.searchList)) {
+          this.$message.info('没用找到匹配结果')
+          return
+        }
+        setTimeout(() => {
+          this.editPopoverShow()
+        }, 3000)
+      },
+      async bindCar(car) {
+        if (this.$isEmpty(this.parkingSpaceItem)) {
+          this.$message.error('车位信息为空')
+          return
+        }
+        let res = await bindCar(car.id, this.parkingSpaceItem.id)
+        if (res.data.success) {
+          this.$message.success('绑定成功')
+          this.parkingSpaceItem.carId = car.id
+          this.parkingSpaceItem.carNo = car.number
+          this.parkingSpaceItem.isUsed = 1
+        } else {
+          this.$message.error('绑定失败')
+        }
+        this.parkingSpaceItem = null
+        this.tableShow = false
+      },
+      enlargeAreaShow() {
+        let flag = false
+        if (this.enlarge && this.$isNotEmpty(this.enlargeItem) && this.enlargeItem.show) {
+          flag = true
+        }
+        return flag
+      },
+      initDone() {
+        this.$nextTick(function() {
+          this.initLayout()
+        })
+        this.getParkingArealist()
+      },
+      initLayout() {
+        let listEl = document.getElementById('parkingLayout');
+        this.listWidth = listEl.clientWidth;
+        this.listHeight = listEl.clientHeight;
+        window.addEventListener('resize', () => {
+          this.listWidth = listEl.clientWidth;
+        })
+      },
+      getParkingArealist() {
+        getLayout(this.parkingLotObj.id).then(res => {
+          if (this.$isNotEmpty(res.data.data)) {
+            this.parkingAreaList = res.data.data
+            this.parkingAreaList.forEach(item => {
+              item.show = true;
+            })
+          }
+        })
+      },
+      save() {
+        saveLayout(this.parkingAreaList).then(res => {
+          if (res.data.success) {
+            this.$message.success('保存成功')
+            this.getParkingArealist()
+          } else {
+            this.$message.success('保存失败')
+          }
+        })
+      },
+      delLayout(item) {
+        this.$confirm("确定删除该区域?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            item.show = false
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          })
+      },
+      addParkingSpace(item) {
+        let tmp = deepClone(this.parkingSpaceObj)
+        tmp.parkingAreaId = item.id
+        tmp.parkingLotId = this.parkingLotObj.id
+        tmp.parkingLotName = this.parkingLotObj.parkName
+        tmp.number = guid(8)
+        item.parkingSpaceList.push(tmp)
+      },
+      changeParkingSpaceParams(item, flag = false) {
+        let arr = item.parkingSpaceParams.split(',')
+        if (flag) {
+          let tmp = arr[0]
+          arr[0] = arr[1]
+          arr[1] = tmp
+          item.parkingSpaceParams = arr.join(',')
+        }
+        let flexStyle = arr[0] > arr[1] ? 'flex-direction: row' : 'flex-direction: column'
+        let parkingSpaceStyle = `width:${arr[0]}px;height:${arr[1]}px;${flexStyle}`
+        return parkingSpaceStyle
+      },
+      popoverClick(item, item2) {
+        this.operatePopoverItem = item
+        item2.event(item)
+        this.popoverVisible = false
+      },
+      operateDialogConfirm() {
+        let num = parseInt(this.num)
+        for (var i = 0; i < num; i++) {
+          let tmp = deepClone(this.parkingSpaceObj)
+          tmp.parkingLotId = this.parkingLotObj.id
+          tmp.parkingLotName = this.parkingLotObj.parkName
+          tmp.number = guid(8)
+          tmp.popoverShow = false
+          tmp.carNo = ''
+          this.operatePopoverItem.parkingSpaceList.push(tmp)
+        }
+        this.operateDialogShow = false
+        this.$forceUpdate()
+        this.$message.success('操作成功')
+      },
+      rectStop(newRect, index) {
+        this.parkingAreaList[index].width = newRect.width
+        this.parkingAreaList[index].height = newRect.height
+        this.parkingAreaList[index].x = newRect.left
+        this.parkingAreaList[index].y = newRect.top
+      },
+    }
+  }
+</script>
+
+
+<style lang="scss" scoped>
+  .page {
+    background-color: #FFFFFF;
+    padding: 1.25rem;
+    position: relative;
+    box-sizing: border-box;
+    margin: 0;
+  }
+
+  .watermark {
+    width: 100%;
+    height: 30px;
+    position: absolute;
+    left: 0;
+    right: 0;
+    top: 45%;
+    color: #3b8ff4;
+    ;
+    text-align: center;
+    opacity: 0.15;
+    z-index: 9999999999;
+    font-size: 22px;
+    pointer-events: none;
+  }
+
+  .addParkingArea {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin: 1.875rem;
+    color: #3b8ff4;
+
+    i {
+      font-size: 3.125rem;
+    }
+
+    i:active {
+      transform: scale(1.05);
+    }
+
+    span {
+      padding-left: 0.625rem;
+    }
+  }
+
+  .bind {
+    margin-left: 0.625rem;
+    color: #3b8ff4;
+    text-decoration: underline;
+    cursor: pointer;
+  }
+
+  .bind:active {
+    transform: scale(1.05);
+  }
+
+
+
+  .delLayoutClass {
+    position: absolute;
+    right: -20px;
+    top: -20px;
+    font-weight: 800;
+  }
+
+  .tips {
+    padding: 10px;
+
+    div {
+      display: flex;
+      padding-top: 0.625rem;
+      font-size: 14px;
+    }
+
+    label {
+      width: 70px;
+    }
+  }
+
+
+  .parking-grid {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-size: 20px 20px, 20px 20px;
+    background-image: linear-gradient(rgba(245, 245, 245, .2) 1px, transparent 0), linear-gradient(90deg, rgba(245, 245, 245, .2) 1px, transparent 0);
+    overflow: hidden;
+    cursor: pointer;
+  }
+
+  .parking-layout {
+    margin-top: 1.25rem;
+    width: 100%;
+    height: 660px;
+    position: relative;
+    border: 1px solid #e5e5e5;
+    background-color: #052252;
+  }
+
+
+  .parking-box {
+    z-index: 99;
+    position: relative;
+    justify-content: center;
+    align-items: center;
+    box-sizing: border-box;
+    display: flex;
+    padding: 0.3125rem 0;
+    flex-wrap: wrap;
+    width: 100%;
+    height: 100%;
+    background: #f5f5f5;
+    overflow: scroll;
+  }
+
+  .car {
+    box-sizing: border-box;
+    margin: 0.3125rem;
+    background-color: #c4e1ff;
+    color: #052252;
+    z-index: 99999999;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-around;
+    align-items: center;
+
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .popoverContent {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: center;
+    align-items: center;
+  }
+</style>

+ 526 - 0
src/views/dashboard/parkingmng/dialog/car-table.vue

@@ -0,0 +1,526 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @row-dblclick="rowDblclick"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+
+      <template slot="auditStatus" scope="{row}">
+        <el-tag v-if="row.auditStatus == 1" type="success">
+          审核通过
+        </el-tag>
+        <el-tag v-else-if="row.auditStatus == -1" type="info">
+          审核不通过
+        </el-tag>
+        <el-tag v-else type="danger">
+          待审核
+        </el-tag>
+      </template>
+    </avue-crud>
+    <el-dialog title="人员画像" :visible.sync="dialogOpen" :fullscreen="true" :modal-append-to-body="false" center>
+      <cy-person-file :personId="personId"></cy-person-file>
+    </el-dialog>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/estate/car";
+  import {mapGetters} from "vuex";
+  import {validateLicense, validatePhone} from "@/util/validator";
+  import {getList as getAgencyList} from "@/api/community/agency";
+  import {getList as getResidentialList} from "@/api/community/residential";
+
+  export default {
+    data() {
+      return {
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        dialogOpen: false,
+        personId: '',
+        option: {
+          dialogWidth:'100%',
+          height:'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: false,
+          addBtn:false,
+          editBtn:false,
+          delBtn:false,
+          menu:false,
+          selection: false,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "车牌号",
+              prop: "number",
+              width: 200,
+              rules: [{
+                required: true,
+                message: "请输入车牌号",
+              },{
+                validator: validateLicense,
+                trigger: "blur"
+              }]
+            }, {
+              label: "车辆类型",
+              prop: "type",
+              type: "select",
+              width: 150,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=car-type",
+              props: {
+                label: "dictValue",
+                value: "dictKey",
+              },
+              dataType: "number",
+              rules: [{
+                required: true,
+                message: "请输入车辆类型",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属园区",
+              prop: "agencyId",
+              hide:true,
+              searchFilterable: true,
+              filterable: true,
+              cascaderItem: ['residentialId'],
+              type: "select",
+              // remote: true,
+              dicUrl: "/api/cyzh-community/agency/list?size=9999",
+              dicFormatter:(res)=>{
+                return res.data.records;//返回字典的层级结构
+              },
+              props: {
+                label: "name",
+                value: "id"
+              },
+              rules: [{
+                required: true,
+                message: "请选择所属园区",
+                trigger: "blur"
+              }],
+              viewDisplay: false,
+            },
+            {
+              label: "所属区域",
+              prop: "residentialName",
+              hide: true,
+              editDisplay: false,
+              addDisplay: false
+            },
+            {
+              label: "所属区域",
+              prop: "residentialId",
+              type: "select",
+              search: false,
+              // dataType:'string',
+              cascaderItem: ["parkingLotId"],
+              dicUrl: "/api/cyzh-community/residential/list?agencyId={{key}}",
+              dicFormatter:(res)=>{
+                return res.data.records;//返回字典的层级结构
+              },
+              // dicFlag: false,
+              filterable: true,
+              props: {
+                label: "name",
+                value: "id"
+              },
+              rules: [{
+                required: true,
+                message: "请选择所属区域",
+                trigger: "blur"
+              }],
+              hide: true,
+              viewDisplay: false,
+            },
+            {
+              label: "车主姓名",
+              prop: "personName",
+              search: true,
+              width: 150,
+              searchSpan: 8,
+              rules: [{
+                required: true,
+                message: "请输入车主姓名",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "车主电话",
+              prop: "personPhone",
+              search: true,
+              width: 200,
+              searchSpan: 8,
+              rules: [{
+                required: true,
+                message: "请输入车主电话",
+              },{
+                validator: validatePhone,
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属车场",
+              prop: "parkingLotId",
+              type: "select",
+              hide: false,
+              search: false,
+              // overHidden: true,
+              // remote: true,
+              dicUrl: "/api/cyzh-estate/parkinglot/list?size=500&residentialId={{key}}",
+              props: {
+                label: 'parkName',
+                value: 'id'
+              },
+              dicFormatter: (res) => {
+                return res.data.records;
+              },
+
+              rules: [{
+                require: true,
+                message: "请选择所属车场",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "车辆性质",
+              prop: "properties",
+              type: "select",
+              hide: true,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=car_properties",
+              props: {
+                label: "dictValue",
+                value: "dictKey",
+              },
+              dataType: "number",
+              rules: [{
+                required: false,
+                message: "请选择车辆性质",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "车辆型号",
+              prop: "model",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入车辆型号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "车身颜色",
+              prop: "color",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入车身颜色",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "审核状态",
+              prop: "auditStatus",
+              type: "select",
+              slot: true,
+              hide:true,
+              dicData:[
+                {
+                  label: "审核通过",
+                  value: 1
+                },
+                {
+                  label: "审核不通过",
+                  value: -1
+                },
+                {
+                  label: "待审核",
+                  value: 0
+                }
+              ],
+              rules: [{
+                required: true,
+                message: "请选择审核状态",
+                trigger: "blur"
+              }],
+              addDisplay: false
+            },
+            {
+              label: "车辆照片",
+              prop: "carImg",
+              listType: 'picture-img',
+              type: "upload",
+              hide: true,
+              propsHttp: {
+                res: "data",
+                url: "link"
+              },
+              //加水印
+              // canvasOption: {
+              //   text: 'bladex',
+              //   ratio: 0.1
+              // },
+              action: "/api/blade-resource/oss/endpoint/put-file",
+              tip: "只能上传jpg/png图片,且不超过500kb",
+              rules: [{
+                required: true,
+                message: "请上传车辆照片",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "行驶证正面照",
+              prop: "vehicleDrivingLicense1",
+              listType: 'picture-img',
+              type: "upload",
+              labelWidth: 100,
+              hide: true,
+              propsHttp: {
+                res: "data",
+                url: "link"
+              },
+              //加水印
+              // canvasOption: {
+              //   text: 'bladex',
+              //   ratio: 0.1
+              // },
+              action: "/api/blade-resource/oss/endpoint/put-file",
+              tip: "只能上传jpg/png图片,且不超过500kb",
+              rules: [{
+                required: true,
+                message: "请上传行驶证正面照",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "行驶证反面照",
+              prop: "vehicleDrivingLicense2",
+              listType: 'picture-img',
+              type: "upload",
+              labelWidth: 100,
+              hide: true,
+              propsHttp: {
+                res: "data",
+                url: "link"
+              },
+              //加水印
+              // canvasOption: {
+              //   text: 'bladex',
+              //   ratio: 0.1
+              // },
+              action: "/api/blade-resource/oss/endpoint/put-file",
+              tip: "只能上传jpg/png图片,且不超过500kb",
+              rules: [{
+                required: true,
+                message: "请上传行驶证反面照",
+                trigger: "blur"
+              }],
+            }
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.car_add, false),
+          viewBtn: this.vaildData(this.permission.car_view, false),
+          delBtn: this.vaildData(this.permission.car_delete, false),
+          editBtn: this.vaildData(this.permission.car_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    watch: {
+      "form.agencyId"() {
+        getAgencyList(1, 10, {id: this.form.agencyId}).then(res => {
+          this.form.agencyName = res.data.data.records[0].name;
+        })
+      },
+      "form.residentialId"() {
+        getResidentialList(1, 10, {id: this.form.residentialId}).then(res => {
+          this.form.residentialName = res.data.data.records[0].name;
+          console.log(JSON.stringify(this.form))
+        })
+      },
+      "form.parkingLotId"() {
+          console.log(JSON.stringify(this.form))
+      }
+    },
+    mounted() {
+      let tenantType = localStorage.getItem("tenantType");
+      const agencyColumn = this.findObject(this.option.column, "agencyId");
+      const residentialColumn = this.findObject(this.option.column, "residentialId");
+      const agencyNameColumn = this.findObject(this.option.column, "agencyName");
+      const residentialNameColumn = this.findObject(this.option.column, "residentialName");
+      if (tenantType == 1) { //园区
+        agencyColumn.label = "所属园区";
+        residentialColumn.label = "所属区域";
+        agencyNameColumn.label = "所属园区";
+        residentialNameColumn.label = "所属区域";
+      } else { //园区
+        agencyColumn.label = "所属园区";
+        residentialColumn.label = "所属区域";
+        agencyNameColumn.label = "所属园区";
+        residentialNameColumn.label = "所属区域";
+      }
+    },
+    methods: {
+      async rowDblclick(row){
+        this.$emit('bindCar',row)
+      },
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        //审核通过
+        this.query.auditStatus="1"
+        //未绑定车辆的
+        this.query.parkingLotId=null
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 3 - 3
src/views/dashboard/parkingmng/parkingmng.vue

@@ -4,7 +4,7 @@
       <!-- 左容器 -->
       <el-col :span="18">
         <div style="box-sizing: border-box;margin: 0.625rem;margin-top: 0rem;">
-          <parking-usage></parking-usage>
+          <paking-layout></paking-layout>
           <paking-capture></paking-capture>
           <paking-charts></paking-charts>
         </div>
@@ -25,13 +25,13 @@
   import pakingCapture from "./comps/paking-capture.vue"
   import pakingData from './comps/parking-data.vue'
   import parkingStatistics from "./comps/parking-statistics.vue"
-  import parkingUsage from "./comps/parking-usage.vue"
+  import pakingLayout from "./comps/paking-layout.vue"
   export default {
     components: {
       pakingCharts,
       pakingCapture,
       pakingData,
-      parkingUsage,
+      pakingLayout,
       parkingStatistics
     },
     data() {

+ 57 - 0
src/views/dashboard/parkingmng/parkingmng1.vue

@@ -0,0 +1,57 @@
+<template>
+  <div class="body">
+    <el-row>
+      <!-- 左容器 -->
+      <el-col :span="18">
+        <div style="box-sizing: border-box;margin: 0.625rem;margin-top: 0rem;">
+          <parking-usage></parking-usage>
+          <paking-capture></paking-capture>
+          <paking-charts></paking-charts>
+        </div>
+      </el-col>
+      <!-- 右容器 -->
+      <el-col :span="6">
+        <parking-statistics></parking-statistics>
+        <paking-data></paking-data>
+      </el-col>
+    </el-row>
+
+    <div style="height: 1.25rem;"></div>
+  </div>
+</template>
+
+<script>
+  import pakingCharts from "./comps/paking-charts.vue"
+  import pakingCapture from "./comps/paking-capture.vue"
+  import pakingData from './comps/parking-data.vue'
+  import parkingStatistics from "./comps/parking-statistics.vue"
+  import parkingUsage from "./comps/parking-usage.vue"
+  export default {
+    components: {
+      pakingCharts,
+      pakingCapture,
+      pakingData,
+      parkingUsage,
+      parkingStatistics
+    },
+    data() {
+      return {
+
+      };
+    }
+  };
+</script>
+
+<style>
+  .avue-main {
+    background-color: #F5F5F5 !important;
+  }
+</style>
+
+<style lang="scss" scoped>
+  .body {
+    background-color: #F5F5F5;
+    height: 100%;
+    margin-bottom: 1.9rem;
+  }
+</style>

+ 283 - 0
src/views/parkingmng/option/parkinglotmng-option.js

@@ -0,0 +1,283 @@
+import {
+  validatePhone
+} from "@/util/validator";
+export default (safe) => {
+  return {
+    height: 'auto',
+    calcHeight: 30,
+    labelWidth: 120,
+    tip: false,
+    searchShow: true,
+    searchMenuSpan: 6,
+    border: true,
+    index: true,
+    viewBtn: true,
+    selection: true,
+    dialogClickModal: false,
+    column: [{
+        label: "索引ID",
+        prop: "indexId",
+        hide: true,
+        display: false,
+        rules: [{
+          required: true,
+          message: "请输入索引ID",
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "停车场名称",
+        prop: "parkName",
+        search: true,
+        searchLabelWidth: 100,
+        rules: [{
+          required: true,
+          message: "请输入停车场名称",
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "车场编号",
+        prop: "parkKey",
+        rules: [{
+          required: true,
+          message: "请输入车场唯一编号",
+          trigger: "blur"
+        }],
+        hide: true
+      },
+      {
+        label: "所属园区",
+        prop: "agencyId",
+        search: true,
+        searchFilterable: true,
+        filterable: true,
+        cascaderItem: ["residentialId"],
+        type: "select",
+        // remote: true,
+        dicUrl: "/api/cyzh-community/agency/list?size=500&name={{key}}",
+        dicFormatter: (res) => {
+          return res.data.records; //返回字典的层级结构
+        },
+        props: {
+          label: "name",
+          value: "id"
+        },
+        rules: [{
+          required: true,
+          message: "请输入所属园区",
+          trigger: "change"
+        }],
+        hide: true,
+        viewDisplay: false,
+      },
+      {
+        label: "所属园区",
+        prop: "agencyName",
+        editDisplay: false,
+        addDisplay: false,
+      },
+      {
+        label: "所属区域",
+        prop: "residentialName",
+        editDisplay: false,
+        addDisplay: false
+      },
+      {
+        label: "所属区域",
+        prop: "residentialId",
+        type: "select",
+        dicUrl: "/api/cyzh-community/residential/list?size=500&agencyId={{key}}",
+        dicFormatter: (res) => {
+          return res.data.records; //返回字典的层级结构
+        },
+        // dicFlag: false,
+        filterable: true,
+        filter: true,
+        props: {
+          label: "name",
+          value: "id"
+        },
+        rules: [{
+          required: true,
+          message: "请输入所属区域",
+          trigger: "blur"
+        }],
+        hide: true,
+        viewDisplay: false
+      },
+      {
+        label: '',
+        prop: 'mapSelect',
+        // row: true,
+        // span: 20,
+        formslot: true,
+        hide: true,
+      },
+      {
+        label: "车场纬度",
+        prop: "parkLatitude",
+        hide: true,
+        rules: [{
+          required: false,
+          message: "请输入车场纬度",
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "车场经度",
+        prop: "parkLongitude",
+        hide: true,
+        rules: [{
+          required: false,
+          message: "请输入车场经度",
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "车场地址",
+        prop: "parkAdd",
+        overHidden: true,
+        rules: [{
+          required: false,
+          message: "请输入车场地址",
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "车场联系方式",
+        prop: "parkTel",
+        hide: true,
+        rules: [{
+          required: false,
+          message: "请输入车场联系方式",
+          trigger: "blur"
+        }, {
+          validator: validatePhone,
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "车场联系人",
+        prop: "parkLinkman",
+        hide: true,
+        rules: [{
+          required: false,
+          message: "请输入车场联系人",
+          trigger: "blur"
+        }]
+      },
+      // {
+      //   label: "免费分钟数	",
+      //   prop: "parkFreeTime",
+      //   hide: true,
+      //   rules: [{
+      //     required: false,
+      //     message: "请输入免费分钟数	",
+      //     trigger: "blur"
+      //   }]
+      // },
+      // {
+      //   label: "免费超时分钟数	",
+      //   prop: "parkFreeTimeout",
+      //   hide: true,
+      //   rules: [{
+      //     required: false,
+      //     message: "请输入免费超时分钟数	",
+      //     trigger: "blur"
+      //   }]
+      // },
+      {
+        label: "车场收费说明	",
+        prop: "chargesDesc",
+        hide: true,
+        rules: [{
+          required: false,
+          message: "请输入车场收费说明	",
+          trigger: "blur"
+        }]
+      },
+      // {
+      //   label: "停车场是否启用预定功能",
+      //   prop: "reserveStatus",
+      //   hide: true,
+      //   rules: [{
+      //     required: false,
+      //     message: "请输入停车场是否启用预定功能",
+      //     trigger: "blur"
+      //   }]
+      // },
+      {
+        label: "创建时间	",
+        prop: "createTime",
+        type: 'date',
+        valueFormat: 'yyyy-MM-dd',
+        rules: [{
+          required: false,
+          message: "创建时间	",
+          trigger: "blur"
+        }],
+        disabled: true,
+        addDisplay: false,
+        editDisplay: false,
+      },
+      // {
+      //   label: "注册时间	",
+      //   prop: "regTime",
+      //   type: 'date',
+      //   valueFormat: 'yyyy-MM-dd',
+      //   rules: [{
+      //     required: false,
+      //     message: "请输入注册时间	",
+      //     trigger: "blur"
+      //   }]
+      // },
+      // {
+      //   label: "停车场有效期止日	",
+      //   prop: "validTime",
+      //   hide: true,
+      //   type: 'date',
+      //   valueFormat: 'yyyy-MM-dd',
+      //   rules: [{
+      //     required: false,
+      //     message: "请输入停车场有效期止日	",
+      //     trigger: "blur"
+      //   }]
+      // },
+      {
+        label: "车位总数",
+        prop: "spaceTotal",
+        hide: true,
+        rules: [{
+          required: false,
+          message: "请输入车位总数",
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "车牌地区简称	",
+        prop: "cityShortName",
+        hide: true,
+        display: false,
+        rules: [{
+          required: false,
+          message: "请输入车牌地区简称	",
+          trigger: "blur"
+        }]
+      },
+      {
+        label: "空余车位",
+        prop: "remainSpace",
+        hide: true,
+        rules: [{
+          required: false,
+          message: "请输入空余车位",
+          trigger: "blur"
+        }],
+        disabled: true,
+        editDisplay: false,
+        addDisplay: false,
+      }
+    ]
+  }
+}

+ 2 - 280
src/views/parkingmng/parkinglotmng.vue

@@ -45,9 +45,9 @@
   import {getList, getDetail, add, update, remove} from "@/api/estate/parkinglot";
   import {mapGetters} from "vuex";
   import editPolygonMap from "@/components/residential/editPolygonMap";
-  import {validatePhone} from "../../util/validator";
   import {getList as getAgencyList} from "@/api/community/agency";
   import {getList as getResidentialList} from "@/api/community/residential";
+  import option from "./option/parkinglotmng-option.js"
 
   export default {
     components: {
@@ -65,285 +65,7 @@
           total: 0
         },
         selectionList: [],
-        option: {
-          height:'auto',
-          calcHeight: 30,
-          labelWidth: 120,
-          tip: false,
-          searchShow: true,
-          searchMenuSpan: 6,
-          border: true,
-          index: true,
-          viewBtn: true,
-          selection: true,
-          dialogClickModal: false,
-          column: [
-            {
-              label: "索引ID",
-              prop: "indexId",
-              hide: true,
-              display: false,
-              rules: [{
-                required: true,
-                message: "请输入索引ID",
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "停车场名称",
-              prop: "parkName",
-              search: true,
-              searchLabelWidth: 100,
-              rules: [{
-                required: true,
-                message: "请输入停车场名称",
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "车场编号",
-              prop: "parkKey",
-              rules: [{
-                required: true,
-                message: "请输入车场唯一编号",
-                trigger: "blur"
-              }],
-              hide: true
-            },
-            {
-              label: "所属园区",
-              prop: "agencyId",
-              search: true,
-              searchFilterable: true,
-              filterable: true,
-              cascaderItem: ["residentialId"],
-              type: "select",
-              // remote: true,
-              dicUrl: "/api/cyzh-community/agency/list?size=500&name={{key}}",
-              dicFormatter:(res)=>{
-                return res.data.records;//返回字典的层级结构
-              },
-              props: {
-                label: "name",
-                value: "id"
-              },
-              rules: [{
-                required: true,
-                message: "请输入所属园区",
-                trigger: "change"
-              }],
-              hide: true,
-              viewDisplay: false,
-            },
-            {
-              label: "所属园区",
-              prop: "agencyName",
-              editDisplay: false,
-              addDisplay: false,
-            },
-            {
-              label: "所属区域",
-              prop: "residentialName",
-              editDisplay: false,
-              addDisplay: false
-            },
-            {
-              label: "所属区域",
-              prop: "residentialId",
-              type: "select",
-              dicUrl: "/api/cyzh-community/residential/list?size=500&agencyId={{key}}",
-              dicFormatter:(res)=>{
-                return res.data.records;//返回字典的层级结构
-              },
-              // dicFlag: false,
-              filterable: true,
-              filter: true,
-              props: {
-                label: "name",
-                value: "id"
-              },
-              rules: [{
-                required: true,
-                message: "请输入所属区域",
-                trigger: "blur"
-              }],
-              hide: true,
-              viewDisplay: false
-            },
-            {
-              label:'',
-              prop:'mapSelect',
-              // row: true,
-              // span: 20,
-              formslot: true,
-              hide: true,
-            },
-            {
-              label: "车场纬度",
-              prop: "parkLatitude",
-              hide: true,
-              rules: [{
-                required: false,
-                message: "请输入车场纬度",
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "车场经度",
-              prop: "parkLongitude",
-              hide: true,
-              rules: [{
-                required: false,
-                message: "请输入车场经度",
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "车场地址",
-              prop: "parkAdd",
-              overHidden: true,
-              rules: [{
-                required: false,
-                message: "请输入车场地址",
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "车场联系方式",
-              prop: "parkTel",
-              hide: true,
-              rules: [{
-                required: false,
-                message: "请输入车场联系方式",
-                trigger: "blur"
-              },{
-                validator: validatePhone,
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "车场联系人",
-              prop: "parkLinkman",
-              hide: true,
-              rules: [{
-                required: false,
-                message: "请输入车场联系人",
-                trigger: "blur"
-              }]
-            },
-            // {
-            //   label: "免费分钟数	",
-            //   prop: "parkFreeTime",
-            //   hide: true,
-            //   rules: [{
-            //     required: false,
-            //     message: "请输入免费分钟数	",
-            //     trigger: "blur"
-            //   }]
-            // },
-            // {
-            //   label: "免费超时分钟数	",
-            //   prop: "parkFreeTimeout",
-            //   hide: true,
-            //   rules: [{
-            //     required: false,
-            //     message: "请输入免费超时分钟数	",
-            //     trigger: "blur"
-            //   }]
-            // },
-            {
-              label: "车场收费说明	",
-              prop: "chargesDesc",
-              hide: true,
-              rules: [{
-                required: false,
-                message: "请输入车场收费说明	",
-                trigger: "blur"
-              }]
-            },
-            // {
-            //   label: "停车场是否启用预定功能",
-            //   prop: "reserveStatus",
-            //   hide: true,
-            //   rules: [{
-            //     required: false,
-            //     message: "请输入停车场是否启用预定功能",
-            //     trigger: "blur"
-            //   }]
-            // },
-            {
-              label: "创建时间	",
-              prop: "createTime",
-              type: 'date',
-              valueFormat: 'yyyy-MM-dd',
-              rules: [{
-                required: false,
-                message: "创建时间	",
-                trigger: "blur"
-              }],
-              disabled: true,
-              addDisplay: false,
-              editDisplay: false,
-            },
-            // {
-            //   label: "注册时间	",
-            //   prop: "regTime",
-            //   type: 'date',
-            //   valueFormat: 'yyyy-MM-dd',
-            //   rules: [{
-            //     required: false,
-            //     message: "请输入注册时间	",
-            //     trigger: "blur"
-            //   }]
-            // },
-            // {
-            //   label: "停车场有效期止日	",
-            //   prop: "validTime",
-            //   hide: true,
-            //   type: 'date',
-            //   valueFormat: 'yyyy-MM-dd',
-            //   rules: [{
-            //     required: false,
-            //     message: "请输入停车场有效期止日	",
-            //     trigger: "blur"
-            //   }]
-            // },
-            {
-              label: "车位总数",
-              prop: "spaceTotal",
-              hide: true,
-              rules: [{
-                required: false,
-                message: "请输入车位总数",
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "车牌地区简称	",
-              prop: "cityShortName",
-              hide: true,
-              display: false,
-              rules: [{
-                required: false,
-                message: "请输入车牌地区简称	",
-                trigger: "blur"
-              }]
-            },
-            {
-              label: "空余车位",
-              prop: "remainSpace",
-              hide: true,
-              rules: [{
-                required: false,
-                message: "请输入空余车位",
-                trigger: "blur"
-              }],
-              disabled: true,
-              editDisplay: false,
-              addDisplay: false,
-            },
-          ]
-        },
+        option:option(this),
         data: []
       };
     },

Некоторые файлы не были показаны из-за большого количества измененных файлов