From 3a02d6a0f7c5d2dfb2df2e1635315304b85695eb Mon Sep 17 00:00:00 2001
From: 唐耀东 <18861537@qq.com>
Date: 星期二, 10 五月 2022 17:49:39 +0800
Subject: [PATCH] 提交代码

---
 src/views/components/school/index.vue              |  120 ++++
 src/views/construction/constructionBatch/index.vue |  323 ++++++++++++
 src/assets/styles/custom.scss                      |    0 
 src/views/construction/reserveIp/index.vue         |  305 +++++++++++
 src/views/basics/building/index.vue                |  297 +++++++++++
 src/views/components/building/buildList.vue        |  129 ++++
 src/api/oa/building.js                             |   44 +
 src/views/components/building/index.vue            |   54 ++
 src/views/basics/school/index.vue                  |   28 
 src/views/construction/constructionList/index.vue  |   77 ++
 src/api/oa/constructionBatch.js                    |   44 +
 src/main.js                                        |    2 
 src/views/components/building/form.vue             |   82 +++
 src/api/common/common.js                           |    5 
 src/api/oa/reserveIp.js                            |   44 +
 15 files changed, 1,545 insertions(+), 9 deletions(-)

diff --git a/src/api/common/common.js b/src/api/common/common.js
index 053b140..ec14bac 100644
--- a/src/api/common/common.js
+++ b/src/api/common/common.js
@@ -17,10 +17,11 @@
 }
 
 // 楂樻牎涓嬫媺鍒楄〃
-export function listSchool() {
+export function listSchool(query) {
   return request({
     url: '/oa/school/select',
-    method: 'get'
+    method: 'get',
+    params: query
   })
 }
 
diff --git a/src/api/oa/building.js b/src/api/oa/building.js
new file mode 100644
index 0000000..7c081db
--- /dev/null
+++ b/src/api/oa/building.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ寤虹瓚鍗曞厓鍒楄〃
+export function listBuilding(query) {
+  return request({
+    url: '/oa/building/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ寤虹瓚鍗曞厓璇︾粏
+export function getBuilding(id) {
+  return request({
+    url: '/oa/building/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板寤虹瓚鍗曞厓
+export function addBuilding(data) {
+  return request({
+    url: '/oa/building',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼寤虹瓚鍗曞厓
+export function updateBuilding(data) {
+  return request({
+    url: '/oa/building',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎寤虹瓚鍗曞厓
+export function delBuilding(id) {
+  return request({
+    url: '/oa/building/' + id,
+    method: 'delete'
+  })
+}
diff --git a/src/api/oa/constructionBatch.js b/src/api/oa/constructionBatch.js
new file mode 100644
index 0000000..5a589d6
--- /dev/null
+++ b/src/api/oa/constructionBatch.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ鏂藉伐鎵规鍒楄〃
+export function listConstructionBatch(query) {
+  return request({
+    url: '/oa/constructionBatch/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ鏂藉伐鎵规璇︾粏
+export function getConstructionBatch(id) {
+  return request({
+    url: '/oa/constructionBatch/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板鏂藉伐鎵规
+export function addConstructionBatch(data) {
+  return request({
+    url: '/oa/constructionBatch',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼鏂藉伐鎵规
+export function updateConstructionBatch(data) {
+  return request({
+    url: '/oa/constructionBatch',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎鏂藉伐鎵规
+export function delConstructionBatch(id) {
+  return request({
+    url: '/oa/constructionBatch/' + id,
+    method: 'delete'
+  })
+}
diff --git a/src/api/oa/reserveIp.js b/src/api/oa/reserveIp.js
new file mode 100644
index 0000000..c3a2280
--- /dev/null
+++ b/src/api/oa/reserveIp.js
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ棰勭暀IP鍒楄〃
+export function listReserveIp(query) {
+  return request({
+    url: '/oa/reserveIp/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏌ヨ棰勭暀IP璇︾粏
+export function getReserveIp(id) {
+  return request({
+    url: '/oa/reserveIp/' + id,
+    method: 'get'
+  })
+}
+
+// 鏂板棰勭暀IP
+export function addReserveIp(data) {
+  return request({
+    url: '/oa/reserveIp',
+    method: 'post',
+    data: data
+  })
+}
+
+// 淇敼棰勭暀IP
+export function updateReserveIp(data) {
+  return request({
+    url: '/oa/reserveIp',
+    method: 'put',
+    data: data
+  })
+}
+
+// 鍒犻櫎棰勭暀IP
+export function delReserveIp(id) {
+  return request({
+    url: '/oa/reserveIp/' + id,
+    method: 'delete'
+  })
+}
diff --git a/src/assets/styles/custom.scss b/src/assets/styles/custom.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/assets/styles/custom.scss
diff --git a/src/main.js b/src/main.js
index 02e2329..1b818cf 100644
--- a/src/main.js
+++ b/src/main.js
@@ -4,7 +4,7 @@
 
 import Element from 'element-ui'
 import './assets/styles/element-variables.scss'
-
+import '@/assets/styles/custom.scss' // 鑷畾涔夋牱寮�
 import '@/assets/styles/index.scss' // global css
 import '@/assets/styles/ruoyi.scss' // ruoyi css
 import App from './App'
diff --git a/src/views/basics/building/index.vue b/src/views/basics/building/index.vue
new file mode 100644
index 0000000..294d29d
--- /dev/null
+++ b/src/views/basics/building/index.vue
@@ -0,0 +1,297 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <!--      <el-form-item label="鍗曞厓缂栧彿" prop="code">-->
+      <!--        <el-input-->
+      <!--          v-model="queryParams.code"-->
+      <!--          placeholder="璇疯緭鍏ュ崟鍏冪紪鍙�"-->
+      <!--          clearable-->
+      <!--          size="small"-->
+      <!--          @keyup.enter.native="handleQuery"-->
+      <!--        />-->
+      <!--      </el-form-item>-->
+      <el-form-item label="鍗曞厓鍚嶇О" prop="name">
+        <el-input
+            v-model="queryParams.name"
+            placeholder="璇疯緭鍏ュ崟鍏冨悕绉�"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+            type="primary"
+            plain
+            icon="el-icon-plus"
+            size="mini"
+            @click="handleAdd"
+            v-hasPermi="['oa:building:add']"
+        >鏂板
+        </el-button>
+      </el-col>
+    </el-row>
+
+    <el-table
+        v-loading="loading"
+        :data="buildingList"
+        row-key="id"
+        default-expand-all
+        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+      <el-table-column label="鍗曞厓鍚嶇О" align="center" prop="name"/>
+      <el-table-column label="鍗曞厓缂栧彿" prop="code"/>
+      <el-table-column label="鏄剧ず椤哄簭" align="center" prop="orderNum"/>
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-edit"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['oa:building:edit']"
+          >淇敼
+          </el-button>
+          <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-plus"
+              @click="handleAdd(scope.row)"
+              v-hasPermi="['oa:building:add']"
+          >鏂板
+          </el-button>
+          <el-button
+              size="mini"
+              type="text"
+              class="del-btn"
+              icon="el-icon-delete"
+              @click="handleDelete(scope.row)"
+              v-hasPermi="['oa:building:remove']"
+          >鍒犻櫎
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 娣诲姞鎴栦慨鏀瑰缓绛戝崟鍏冨璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="涓婄骇鍗曞厓" prop="parentId">
+          <treeselect v-model="form.parentId" :options="buildingOptions" :normalizer="normalizer"
+                      placeholder="璇烽�夋嫨涓婄骇鍗曞厓"/>
+        </el-form-item>
+        <el-form-item label="鍗曞厓鍚嶇О" prop="name">
+          <el-input v-model="form.name" placeholder="璇疯緭鍏ュ崟鍏冨悕绉�"/>
+        </el-form-item>
+        <el-form-item label="鍗曞厓缂栧彿" prop="code">
+          <el-input v-model="form.code" placeholder="璇疯緭鍏ュ崟鍏冪紪鍙�"/>
+        </el-form-item>
+        <el-form-item label="鏄剧ず椤哄簭" prop="orderNum">
+          <el-input-number v-model="form.orderNum" controls-position="right" :min="0"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button :loading="buttonLoading" type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {listBuilding, getBuilding, delBuilding, addBuilding, updateBuilding} from "@/api/oa/building";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "Building",
+  props: {
+    schoolId: {
+      type: Number,
+      default: undefined
+    }
+  },
+  components: {
+    Treeselect
+  },
+  data() {
+    return {
+      // 鎸夐挳loading
+      buttonLoading: false,
+      // 閬僵灞�
+      loading: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 寤虹瓚鍗曞厓琛ㄦ牸鏁版嵁
+      buildingList: [],
+      // 寤虹瓚鍗曞厓鏍戦�夐」
+      buildingOptions: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        code: null,
+        name: null,
+        schoolId: this.schoolId
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        code: [
+          {required: true, message: "鍗曞厓缂栧彿涓嶈兘涓虹┖", trigger: "blur"}
+        ],
+        name: [
+          {required: true, message: "鍗曞厓鍚嶇О涓嶈兘涓虹┖", trigger: "blur"}
+        ],
+        orderNum: [
+          {required: true, message: "鏄剧ず椤哄簭涓嶈兘涓虹┖", trigger: "change"}
+        ],
+        parentId: [
+          {required: true, message: "涓婄骇鍗曞厓涓嶈兘涓虹┖", trigger: "blur"}
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ寤虹瓚鍗曞厓鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listBuilding(this.queryParams).then(response => {
+        this.buildingList = this.handleTree(response.data, "id", "parentId");
+        this.loading = false;
+      });
+    },
+    /** 杞崲寤虹瓚鍗曞厓鏁版嵁缁撴瀯 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.id,
+        label: node.name,
+        children: node.children
+      };
+    },
+    /** 鏌ヨ寤虹瓚鍗曞厓涓嬫媺鏍戠粨鏋� */
+    getTreeselect() {
+      listBuilding({schoolId: this.schoolId}).then(response => {
+        this.buildingOptions = [];
+        const data = {id: 0, name: '椤剁骇鑺傜偣', children: []};
+        data.children = this.handleTree(response.data, "id", "parentId");
+        this.buildingOptions.push(data);
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: null,
+        code: null,
+        name: null,
+        schoolId: null,
+        parentId: null,
+        ancestors: null,
+        orderNum: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null,
+        delFlag: null
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd(row) {
+      this.reset();
+      this.getTreeselect();
+      if (row != null && row.id) {
+        this.form.parentId = row.id;
+      } else {
+        this.form.parentId = 0;
+      }
+      this.open = true;
+      this.title = "娣诲姞寤虹瓚鍗曞厓";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.loading = true;
+      this.reset();
+      this.getTreeselect();
+      if (row != null) {
+        this.form.parentId = row.id;
+      }
+      getBuilding(row.id).then(response => {
+        this.loading = false;
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼寤虹瓚鍗曞厓";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        this.form.schoolId = this.schoolId;
+        if (valid) {
+          this.buttonLoading = true;
+          if (this.form.id != null) {
+            updateBuilding(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            }).finally(() => {
+              this.buttonLoading = false;
+            });
+          } else {
+            addBuilding(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            }).finally(() => {
+              this.buttonLoading = false;
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      this.$modal.confirm('鏄惁纭鍒犻櫎"' + row.detailedName + '"锛�').then(() => {
+        this.loading = true;
+        return delBuilding(row.id);
+      }).then(() => {
+        this.loading = false;
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).finally(() => {
+        this.loading = false;
+      });
+    }
+  }
+};
+</script>
diff --git a/src/views/basics/school/index.vue b/src/views/basics/school/index.vue
index 5c76ac7..11578c7 100644
--- a/src/views/basics/school/index.vue
+++ b/src/views/basics/school/index.vue
@@ -137,9 +137,16 @@
           <dict-tag :options="dict.type.DICT106" :value="scope.row.disciplineScope"/>
         </template>
       </el-table-column>
-      <el-table-column label="澶囨敞" align="center" prop="remarks"/>
-      <el-table-column label="鎿嶄綔" fixed="right" width="120" align="center" class-name="small-padding fixed-width">
+<!--      <el-table-column label="澶囨敞" align="center" prop="remarks"/>-->
+      <el-table-column label="鎿嶄綔" fixed="right" width="220" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
+          <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-office-building"
+              @click="handleBuild(scope.row)"
+          >寤虹瓚
+          </el-button>
           <el-button
             size="mini"
             type="text"
@@ -228,16 +235,24 @@
         <el-button @click="cancel">鍙� 娑�</el-button>
       </div>
     </Dialog>
+    <!-- 寤虹瓚 -->
+    <el-drawer title="寤虹瓚鍗曞厓" :visible.sync="buildOpen" size="50%" :append-to-body="true" :destroy-on-close="true">
+      <building :schoolId="id"></building>
+    </el-drawer>
   </div>
 </template>
 
 <script>
 import {listSchool, getSchool, delSchool, addSchool, updateSchool} from "@/api/oa/school";
 import {listProvince, listCity} from "@/api/common/common";
+import building from '../building'
 
 export default {
   name: "School",
   dicts: ['DICT105', 'DICT106'],
+  components: {
+    building
+  },
   data() {
     return {
       // 鎸夐挳loading
@@ -307,7 +322,9 @@
       // 鐪佷唤
       provinceFormList: [],
       // 鍩庡競
-      cityFormList: []
+      cityFormList: [],
+      buildOpen: false,
+      id: undefined
     };
   },
   created() {
@@ -467,6 +484,11 @@
       this.getCity(v).then(res => {
         this.cityFormList = res
       })
+    },
+    // 寤虹瓚
+    handleBuild(r) {
+      this.id = r.id;
+      this.buildOpen = true;
     }
   }
 };
diff --git a/src/views/components/building/buildList.vue b/src/views/components/building/buildList.vue
new file mode 100644
index 0000000..dfaeccf
--- /dev/null
+++ b/src/views/components/building/buildList.vue
@@ -0,0 +1,129 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鍗曞厓鍚嶇О" prop="name">
+        <el-input
+            v-model="queryParams.name"
+            placeholder="璇疯緭鍏ュ崟鍏冨悕绉�"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table
+        ref="singleTable"
+        v-loading="loading"
+        :data="buildingList"
+        row-key="id"
+        default-expand-all
+        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+        highlight-current-row
+        @current-change="handleCurrentChange"
+    >
+      <el-table-column label="鍗曞厓鍚嶇О" align="center" prop="name"/>
+      <el-table-column label="鍗曞厓缂栧彿" prop="code"/>
+      <el-table-column label="鏄剧ず椤哄簭" align="center" prop="orderNum"/>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import {listBuilding} from "@/api/oa/building";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "BuildingList",
+  props: {
+    schoolId: {
+      type: Number,
+      default: undefined
+    }
+  },
+  components: {
+    Treeselect
+  },
+  data() {
+    return {
+      // 鎸夐挳loading
+      buttonLoading: false,
+      // 閬僵灞�
+      loading: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 寤虹瓚鍗曞厓琛ㄦ牸鏁版嵁
+      buildingList: [],
+      // 寤虹瓚鍗曞厓鏍戦�夐」
+      buildingOptions: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        name: undefined,
+        schoolId: this.schoolId
+      },
+      currentRow: undefined
+    };
+  },
+  watch: {
+    'schoolId': function (v) {
+      this.getList()
+    }
+  },
+  methods: {
+    /** 鏌ヨ寤虹瓚鍗曞厓鍒楄〃 */
+    getList() {
+      this.loading = true;
+      // 娓呯┖閫変腑鐘舵�佸拰鏁版嵁
+      if (this.currentRow) {
+        this.$refs.singleTable.setCurrentRow();
+        this.currentRow = undefined;
+      }
+      listBuilding(Object.assign({}, this.queryParams, {schoolId: this.schoolId})).then(response => {
+        this.buildingList = this.handleTree(response.data, "id", "parentId");
+        this.loading = false;
+      });
+    },
+    /** 杞崲寤虹瓚鍗曞厓鏁版嵁缁撴瀯 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.id,
+        label: node.name,
+        children: node.children
+      };
+    },
+    /** 鏌ヨ寤虹瓚鍗曞厓涓嬫媺鏍戠粨鏋� */
+    getTreeselect() {
+      listBuilding({schoolId: this.schoolId}).then(response => {
+        this.buildingOptions = [];
+        const data = {id: 0, name: '椤剁骇鑺傜偣', children: []};
+        data.children = this.handleTree(response.data, "id", "parentId");
+        this.buildingOptions.push(data);
+      });
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    handleCurrentChange(v) {
+      this.currentRow = v;
+    }
+  }
+};
+</script>
diff --git a/src/views/components/building/form.vue b/src/views/components/building/form.vue
new file mode 100644
index 0000000..c6314d2
--- /dev/null
+++ b/src/views/components/building/form.vue
@@ -0,0 +1,82 @@
+<template>
+  <div>
+    <div class="app-container">
+      <div class="tree-view">
+        <div class="tree-list">
+          <school ref="schoolRef" @schoolChange="schoolChange"></school>
+        </div>
+        <div class="right-view">
+          <build-list ref="buildRef" :schoolId="schoolId"></build-list>
+        </div>
+      </div>
+    </div>
+    <div slot="footer" class="dialog-footer">
+      <el-button :loading="buttonLoading" type="primary" @click="submitForm">纭� 瀹�</el-button>
+<!--      <el-button @click="cancel">鍙� 娑�</el-button>-->
+    </div>
+  </div>
+</template>
+
+<script>
+/**
+ * 閫夋嫨寤虹瓚鍗曞厓
+ */
+import school from '../../components/school'
+import buildList from "./buildList";
+
+export default {
+  name: "BuildingForm",
+  components: {
+    school,
+    buildList
+  },
+  data() {
+    return {
+      buttonLoading: false,
+      activeName: 'second',
+      batchOpen: false,
+      ipOpen: false,
+      schoolId: undefined
+    }
+  },
+  methods: {
+    // 閫夋嫨楂樻牎
+    schoolChange(v) {
+      this.schoolId = v;
+      // this.$refs.buildRef.getList();
+    },
+    submitForm() {
+      this.buttonLoading = true;
+      if (!this.$refs.buildRef.currentRow) {
+        this.$message.warning("璇烽�夋嫨涓�鏉℃暟鎹�")
+        this.buttonLoading = false;
+        return;
+      }
+      this.$emit('choice', this.$refs.buildRef.currentRow);
+    }
+  }
+}
+</script>
+
+<style scoped>
+.tree-view {
+  display: flex;
+  flex-direction: row;
+  flex: 1;
+}
+.tree-list {
+  margin-right: 10px;
+}
+.right-view {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  flex: 1;
+}
+.right-view-title-icon {
+  display: flex;
+  flex-direction: row;
+  height: 40px;
+  align-items: center;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/components/building/index.vue b/src/views/components/building/index.vue
new file mode 100644
index 0000000..964dcf6
--- /dev/null
+++ b/src/views/components/building/index.vue
@@ -0,0 +1,54 @@
+<template>
+  <div>
+    <el-input placeholder="璇烽�夋嫨閫傜敤鍦扮偣" :value="buildingName" disabled>
+      <el-button slot="append" icon="el-icon-thumb" @click="handleBuilding"></el-button>
+    </el-input>
+    <el-dialog title="寤虹瓚鍗曞厓" :visible.sync="open" width="800px" :append-to-body="true" :destroy-on-close="true">
+      <building-form @choice="choice"></building-form>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import buildingForm from './form'
+
+export default {
+  name: "BuildInput",
+  components: {
+    buildingForm
+  },
+  model: {
+    prop: 'value',
+    event: 'change'
+  },
+  props: {
+    value: {
+      type: [Number],
+      default: undefined
+    },
+  },
+  data() {
+    return {
+      message: undefined,
+      open: false,
+      buildingName: ''
+    }
+  },
+  methods: {
+    // 閫夋嫨寤虹瓚鍗曞厓
+    handleBuilding() {
+      this.open = true;
+    },
+    // 閫変腑寤虹瓚鍗曞厓
+    choice(r) {
+      this.buildingName = r.name;
+      this.open = false;
+      this.$emit("change", r.id);
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/components/school/index.vue b/src/views/components/school/index.vue
new file mode 100644
index 0000000..1679ecd
--- /dev/null
+++ b/src/views/components/school/index.vue
@@ -0,0 +1,120 @@
+<template>
+  <div class="tree-list-main">
+    <div class="tree-search">
+      <div class="main-search" style="margin-bottom: 0;">
+        <input class="search-input" v-model="queryParams.name" @keyup.enter.prevent="getList" placeholder="璇疯緭鍏ュ悕绉�"/>
+      </div>
+    </div>
+
+    <div class="main-tree">
+      <div class="question-list" v-for="item in list" :key="item.id">
+        <div class="question-item text-ellipsis" :class="item.id === id ? 'question-current' : ''">
+          <div class="question-item-text text-ellipsis" @click="handleClick(item.id)">{{item.name}}</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import {listSchool} from "@/api/common/common";
+
+export default {
+  name: "QuestionType",
+  watch: {
+    'queryParams.name': function (val) {
+      this.getList()
+    }
+  },
+  data() {
+    return {
+      id: undefined,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        name: undefined
+      },
+      list: []
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    getList() {
+      this.loading = true;
+      listSchool(this.queryParams).then(r => {
+        this.list = r.data;
+        if (this.list.length > 0) {
+          this.id = this.list[0].id;
+          this.$emit('schoolChange', this.id)
+        }
+      })
+    },
+    // 閫変腑
+    handleClick(id) {
+      if (this.id === id) return
+      this.$emit('schoolChange', id)
+      this.id = id
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.tree-search {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  height: 32px;
+  margin-bottom: 10px;
+  .search-add {
+    width: 60px;
+    text-align: center;
+    cursor: pointer;
+    line-height: 32px;
+    font-size: 14px;
+    height: 100%;
+    background-color: #3CA2E0;
+    color: #ffffff;
+  }
+}
+
+.question-list {
+  display: flex;
+  flex-direction: column;
+
+  .question-item {
+    height: 30px;
+    line-height: 30px;
+    width: 100%;
+    color: #333333;
+    font-size: 14px;
+    padding: 0 5px;
+    cursor: pointer;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .question-item-text {
+      flex: 1;
+    }
+  }
+
+  .question-current {
+    background: #53A3FF;
+    color: #ffffff !important;
+  }
+
+  .operation-region {
+    display: none;
+    cursor: pointer;
+  }
+
+  .question-item:hover .operation-region {
+    display: block;
+  }
+  .question-item:hover {
+    background: #F5F7FA;
+    color: #333333!important;
+  }
+}
+</style>
diff --git a/src/views/construction/constructionBatch/index.vue b/src/views/construction/constructionBatch/index.vue
new file mode 100644
index 0000000..946b5c3
--- /dev/null
+++ b/src/views/construction/constructionBatch/index.vue
@@ -0,0 +1,323 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="鏂藉伐鎵规" prop="batch">
+        <el-input
+          v-model="queryParams.batch"
+          placeholder="璇疯緭鍏ユ柦宸ユ壒娆�"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['oa:constructionBatch:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['oa:constructionBatch:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['oa:constructionBatch:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+    </el-row>
+
+    <el-table v-loading="loading" :data="constructionBatchList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="搴忓彿" type="index" align="center">
+        <template slot-scope="scope">
+          <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="鏂藉伐鎵规" align="center" prop="batch" />
+      <el-table-column label="鏂藉伐鍛ㄦ湡" align="center" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') + ' - ' + parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="璐熻矗浜�" align="center" prop="userId_dictText" />
+      <el-table-column label="鍥㈤槦鎴愬憳" align="center" prop="teamMembers" />
+      <el-table-column label="澶囨敞" align="center" prop="remarks" />
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['oa:constructionBatch:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            class="del-btn"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['oa:constructionBatch:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀规柦宸ユ壒娆″璇濇 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body :close-on-click-modal="false">
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="鏂藉伐鎵规" prop="batch">
+          <el-input v-model="form.batch" maxlength="64" show-word-limit placeholder="璇疯緭鍏ユ柦宸ユ壒娆�" />
+        </el-form-item>
+        <el-form-item label="鏂藉伐鍛ㄦ湡" prop="date">
+          <el-date-picker
+              v-model="form.date"
+              type="daterange"
+              range-separator="鑷�"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="鎴嚦鏃ユ湡">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="璐熻矗浜�" prop="userId">
+          <el-select v-model="form.userId" filterable placeholder="璇烽�夋嫨璐熻矗浜�">
+            <el-option
+                v-for="item in userList"
+                :key="item.userId"
+                :label="item.nickName"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍥㈤槦鎴愬憳" prop="teamMembers">
+          <el-input v-model="form.teamMembers" type="textarea" rows="4" maxlength="64" show-word-limit placeholder="璇疯緭鍏ュ洟闃熸垚鍛�" />
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" type="textarea" rows="6" maxlength="512" show-word-limit placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button :loading="buttonLoading" type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listConstructionBatch, getConstructionBatch, delConstructionBatch, addConstructionBatch, updateConstructionBatch } from "@/api/oa/constructionBatch";
+import {listUser} from '@/api/common/common'
+
+export default {
+  name: "ConstructionBatch",
+  data() {
+    return {
+      // 鎸夐挳loading
+      buttonLoading: false,
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 鏂藉伐鎵规琛ㄦ牸鏁版嵁
+      constructionBatchList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        batch: undefined,
+        startDate: undefined,
+        endDate: undefined,
+        userId: undefined,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        id: [
+          { required: true, message: "涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        batch: [
+          { required: true, message: "鏂藉伐鎵规涓嶈兘涓虹┖", trigger: "blur" }
+        ],
+        userId: [
+          { required: true, message: "璐熻矗浜轰笉鑳戒负绌�", trigger: "blur" }
+        ],
+        date: [
+          { required: true, message: "鏂藉伐鍛ㄦ湡涓嶈兘涓虹┖", trigger: "blur" }
+        ]
+      },
+      userList: []
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ鏂藉伐鎵规鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listConstructionBatch(this.queryParams).then(response => {
+        this.constructionBatchList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    getUser() {
+      listUser().then(r => {
+        this.userList = r.data;
+      })
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: undefined,
+        batch: undefined,
+        startDate: undefined,
+        endDate: undefined,
+        userId: undefined,
+        teamMembers: undefined,
+        remarks: undefined,
+        createTime: undefined,
+        createBy: undefined,
+        updateBy: undefined,
+        updateTime: undefined,
+        delFlag: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.getUser();
+      this.open = true;
+      this.title = "娣诲姞鏂藉伐鎵规";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.loading = true;
+      this.reset();
+      const id = row.id || this.ids
+      getConstructionBatch(id).then(response => {
+        this.loading = false;
+        this.form = response.data;
+        this.form.date = [this.form.startDate, this.form.endDate]
+        this.open = true;
+        this.title = "淇敼鏂藉伐鎵规";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        console.log(this.form.date)
+        this.form.startDate = this.form.date[0];
+        this.form.endDate = this.form.date[1];
+        if (valid) {
+          this.buttonLoading = true;
+          if (this.form.id != null) {
+            updateConstructionBatch(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            }).finally(() => {
+              this.buttonLoading = false;
+            });
+          } else {
+            addConstructionBatch(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            }).finally(() => {
+              this.buttonLoading = false;
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎锛�').then(() => {
+        this.loading = true;
+        return delConstructionBatch(ids);
+      }).then(() => {
+        this.loading = false;
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).finally(() => {
+        this.loading = false;
+      });
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('oa/constructionBatch/export', {
+        ...this.queryParams
+      }, `constructionBatch_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/src/views/construction/constructionList/index.vue b/src/views/construction/constructionList/index.vue
index d0207e0..6020d32 100644
--- a/src/views/construction/constructionList/index.vue
+++ b/src/views/construction/constructionList/index.vue
@@ -1,15 +1,86 @@
 <template>
-  <div>
+  <div class="app-container">
+    <div class="tree-view">
+      <div class="tree-list">
+        <school ref="schoolRef" @schoolChange="schoolChange"></school>
+      </div>
+      <div class="right-view">
+        <el-tabs v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="鏂藉伐姒傚喌" name="first">鏂藉伐姒傚喌</el-tab-pane>
+          <el-tab-pane label="IPC璁惧" name="second">IPC璁惧</el-tab-pane>
+          <el-tab-pane label="NVR璁惧" name="third">NVR璁惧</el-tab-pane>
+          <el-tab-pane label="IoT璁惧" name="fourth">IoT璁惧</el-tab-pane>
+          <el-tab-pane label="AI璁惧" name="five">AI璁惧</el-tab-pane>
+          <el-tab-pane label="浜ゆ崲璁惧" name="six">浜ゆ崲璁惧</el-tab-pane>
+          <el-tab-pane label="鏈嶅姟鍣�" name="seven">鏈嶅姟鍣�</el-tab-pane>
+          <el-tab-pane label="杞欢绯荤粺" name="eight">杞欢绯荤粺</el-tab-pane>
+        </el-tabs>
+        <div class="right-view-title-icon">
+          <i class="el-icon-search" @click="batchOpen = true"></i>
+          <i class="el-icon-search" @click="ipOpen = true"></i>
+        </div>
+      </div>
+    </div>
+    <el-drawer title="鏂藉伐鎵规" :visible.sync="batchOpen" size="70%" :append-to-body="true" :destroy-on-close="true">
+      <construction-batch></construction-batch>
+    </el-drawer>
 
+    <el-drawer title="棰勭暀IP" :visible.sync="ipOpen" size="70%" :append-to-body="true" :destroy-on-close="true">
+      <reserve-ip></reserve-ip>
+    </el-drawer>
   </div>
 </template>
 
 <script>
+import school from '../../components/school'
+import constructionBatch from '../constructionBatch'
+import reserveIp from '../reserveIp'
+
 export default {
-  name: "constructionList"
+  name: "constructionList",
+  components: {
+    school,
+    constructionBatch,
+    reserveIp
+  },
+  data() {
+    return {
+      activeName: 'second',
+      batchOpen: false,
+      ipOpen: false
+    }
+  },
+  methods: {
+    // 閫夋嫨楂樻牎
+    schoolChange(v) {
+
+    },
+    handleClick(tab, event) {
+      console.log(tab, event);
+    }
+  }
 }
 </script>
 
 <style scoped>
-
+.tree-view {
+  display: flex;
+  flex-direction: row;
+  flex: 1;
+}
+.tree-list {
+  margin-right: 10px;
+}
+.right-view {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  flex: 1;
+}
+.right-view-title-icon {
+  display: flex;
+  flex-direction: row;
+  height: 40px;
+  align-items: center;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/construction/reserveIp/index.vue b/src/views/construction/reserveIp/index.vue
new file mode 100644
index 0000000..673999a
--- /dev/null
+++ b/src/views/construction/reserveIp/index.vue
@@ -0,0 +1,305 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="IP鍦板潃" prop="ip">
+        <el-input
+          v-model="queryParams.ip"
+          placeholder="璇疯緭鍏p鍦板潃"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['oa:reserveIp:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['oa:reserveIp:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['oa:reserveIp:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+    </el-row>
+
+    <el-table v-loading="loading" :data="reserveIpList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="搴忓彿" type="index" align="center">
+        <template slot-scope="scope">
+          <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="IP鍦板潃" align="center" prop="ip" />
+      <el-table-column label="MAC鍦板潃" align="center" prop="mac" />
+      <el-table-column label="閫傜敤鍦扮偣" align="center" prop="buildingId_dictText" />
+      <el-table-column label="鐢宠鏃ユ湡" align="center" prop="applicationDate" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.applicationDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="澶囨敞" align="center" prop="remarks" />
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['oa:reserveIp:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            class="del-btn"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['oa:reserveIp:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀归鐣橧P瀵硅瘽妗� -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" :append-to-body="true" :destroy-on-close="true" :close-on-click-modal="false">
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="IP鍦板潃" prop="ip">
+          <el-input v-model="form.ip" placeholder="璇疯緭鍏p鍦板潃" />
+        </el-form-item>
+        <el-form-item label="MAC鍦板潃" prop="mac">
+          <el-input v-model="form.mac" placeholder="璇疯緭鍏AC鍦板潃" />
+        </el-form-item>
+        <el-form-item label="閫傜敤鍦扮偣" prop="buildingId">
+          <building v-model="form.buildingId"></building>
+        </el-form-item>
+        <el-form-item label="鐢宠鏃ユ湡" prop="applicationDate">
+          <el-date-picker clearable size="small"
+            v-model="form.applicationDate"
+            type="date"
+            placeholder="閫夋嫨鐢宠鏃ユ湡">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="澶囨敞" prop="remarks">
+          <el-input v-model="form.remarks" type="textarea" :rows="8" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button :loading="buttonLoading" type="primary" @click="submitForm">纭� 瀹�</el-button>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+      </div>
+    </el-dialog>
+
+
+  </div>
+</template>
+
+<script>
+import { listReserveIp, getReserveIp, delReserveIp, addReserveIp, updateReserveIp } from "@/api/oa/reserveIp";
+import building from '../../components/building'
+
+export default {
+  name: "ReserveIp",
+  components: {
+    building
+  },
+  data() {
+    return {
+      // 鎸夐挳loading
+      buttonLoading: false,
+      // 閬僵灞�
+      loading: true,
+      // 閫変腑鏁扮粍
+      ids: [],
+      // 闈炲崟涓鐢�
+      single: true,
+      // 闈炲涓鐢�
+      multiple: true,
+      // 鏄剧ず鎼滅储鏉′欢
+      showSearch: true,
+      // 鎬绘潯鏁�
+      total: 0,
+      // 棰勭暀IP琛ㄦ牸鏁版嵁
+      reserveIpList: [],
+      // 寮瑰嚭灞傛爣棰�
+      title: "",
+      // 鏄惁鏄剧ず寮瑰嚭灞�
+      open: false,
+      // 鏌ヨ鍙傛暟
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        ip: undefined,
+        buildingId: undefined,
+      },
+      // 琛ㄥ崟鍙傛暟
+      form: {},
+      // 琛ㄥ崟鏍¢獙
+      rules: {
+        ip: [
+          { required: true, message: "ip鍦板潃涓嶈兘涓虹┖", trigger: "blur" },
+          { pattern: /^(\d|[1-9]\d|1\d{2}|2[0-5][0-5])\.(\d|[1-9]\d|1\d{2}|2[0-5][0-5])\.(\d|[1-9]\d|1\d{2}|2[0-5][0-5])\.(\d|[1-9]\d|1\d{2}|2[0-5][0-5])$/, message: "璇疯緭鍏ユ纭殑ip鍦板潃", trigger: "blur" }
+        ],
+        mac: [
+          { required: true, message: "MAC鍦板潃涓嶈兘涓虹┖", trigger: "blur" },
+          { pattern: /^[A-F0-9]{2}(-[A-F0-9]{2}){5}$|^[A-F0-9]{2}(:[A-F0-9]{2}){5}$|^[A-F0-9]{12}$|^[A-F0-9]{4}(\.[A-F0-9]{4}){2}$/, message: "璇疯緭鍏ユ纭殑MAC鍦板潃", trigger: "blur" }
+        ],
+        buildingId: [
+          { required: true, message: "寤虹瓚鍗曞厓涓嶈兘涓虹┖", trigger: "change" }
+        ],
+      },
+      buildOpen: false
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 鏌ヨ棰勭暀IP鍒楄〃 */
+    getList() {
+      this.loading = true;
+      listReserveIp(this.queryParams).then(response => {
+        this.reserveIpList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 鍙栨秷鎸夐挳
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        id: undefined,
+        ip: undefined,
+        mac: undefined,
+        buildingId: undefined,
+        applicationDate: undefined,
+        remarks: undefined,
+        createTime: undefined,
+        createBy: undefined,
+        updateBy: undefined,
+        updateTime: undefined,
+        delFlag: undefined
+      };
+      this.resetForm("form");
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 鏂板鎸夐挳鎿嶄綔 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "娣诲姞棰勭暀IP";
+    },
+    /** 淇敼鎸夐挳鎿嶄綔 */
+    handleUpdate(row) {
+      this.loading = true;
+      this.reset();
+      const id = row.id || this.ids
+      getReserveIp(id).then(response => {
+        this.loading = false;
+        this.form = response.data;
+        this.open = true;
+        this.title = "淇敼棰勭暀IP";
+      });
+    },
+    /** 鎻愪氦鎸夐挳 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          this.buttonLoading = true;
+          if (this.form.id != null) {
+            updateReserveIp(this.form).then(response => {
+              this.$modal.msgSuccess("淇敼鎴愬姛");
+              this.open = false;
+              this.getList();
+            }).finally(() => {
+              this.buttonLoading = false;
+            });
+          } else {
+            addReserveIp(this.form).then(response => {
+              this.$modal.msgSuccess("鏂板鎴愬姛");
+              this.open = false;
+              this.getList();
+            }).finally(() => {
+              this.buttonLoading = false;
+            });
+          }
+        }
+      });
+    },
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('鏄惁纭鍒犻櫎锛�').then(() => {
+        this.loading = true;
+        return delReserveIp(ids);
+      }).then(() => {
+        this.loading = false;
+        this.getList();
+        this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      }).finally(() => {
+        this.loading = false;
+      });
+    },
+    /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+    handleExport() {
+      this.download('oa/reserveIp/export', {
+        ...this.queryParams
+      }, `reserveIp_${new Date().getTime()}.xlsx`)
+    },
+  }
+};
+</script>

--
Gitblit v1.9.1