liujt 2 месяцев назад
Родитель
Сommit
c8fccf6cbb

+ 75 - 0
src/api/‌doorSecurity‌/index.js

@@ -0,0 +1,75 @@
+import request from '@/utils/request';
+
+/**
+ * 绑定列表
+ * @param params 查询条件
+ */
+export async function listDoorUsers(params) {
+  const res = await request.get('/mms/acs/bind/list', {
+    params
+  });
+  if (res.data.code == 0 && res.data.data) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}  
+
+/**
+ * 设备台账
+ * @param params 菜单信息
+ */
+export async function listDevice(params) {
+  const res = await request.post(`/mms/access/device/list`, params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 绑定
+ * @param params 菜单信息
+ */
+export async function bindDevice(params) {
+  const res = await request.post(`/mms/acs/bind/bind`, params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 绑定
+ * @param params 菜单信息
+ */
+export async function editBind(params) {
+  const res = await request.post(`/mms/acs/bind/edit`, params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+} 
+
+/**
+ * 同步
+ * @param params 菜单信息
+ */
+export async function syncDevice(id) {
+  const res = await request.post(`/mms/acs/bind/sync-pull/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 同步
+ * @param params 菜单信息
+ */
+export async function unbindDevice(id) {
+  const res = await request.post(`/mms/acs/bind/unbind/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 0 - 0
src/views/‌doorSecurity‌/doorLedger/index.vue


+ 0 - 0
src/views/‌doorSecurity‌/entryExitRecords/index.vue


+ 305 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/door-authorize.vue

@@ -0,0 +1,305 @@
+<!-- 用户编辑弹窗 -->
+<template>
+  <ele-modal
+    width="600px"
+    :visible="visible"
+    :append-to-body="true"
+    :close-on-click-modal="false"
+    custom-class="ele-dialog-form"
+    title="授权"
+    @update:visible="updateVisible"
+    :maxable="true"
+  >
+    <el-form
+      ref="form"
+      :autoComplete="false"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="授权类型:" prop="isPermanent">
+            <el-radio-group v-model="form.isPermanent">
+              <el-radio :label="0">临时授权</el-radio>
+              <el-radio :label="1">长期授权</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24" v-if="form.isPermanent == 0">
+          <el-form-item label="授权有效期:" prop="validTime">
+            <el-date-picker
+                v-model="form.validTime"
+                type="daterange"
+                range-separator="至"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                value-format="yyyy-MM-dd HH:mm:ss"
+                style="width: 100%"
+              >
+              </el-date-picker>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+    <template v-slot:footer>
+      <el-button @click="updateVisible(false)">取消</el-button>
+      <el-button type="primary" :loading="loading" @click="submitForm">
+        确定
+      </el-button>
+    </template>
+  </ele-modal>
+</template>
+
+<script>
+  import { listDevice, bindDevice, editBind } from '@/api/‌doorSecurity‌'
+  import tabMixins from '@/mixins/tableColumnsMixin';
+  export default {
+    components: {  },
+    mixins: [tabMixins],
+    props: {
+      // 弹窗是否打开
+      visible: Boolean,
+      // isUpdate: Boolean,
+      // 修改回显的数据
+      current: Object,
+      list: Array,
+      deviceInfo: Object,
+    },
+    data() {
+      const defaultForm = {
+        isPermanent: 0,
+        validStart: '',
+        validEnd: '',
+        validTime: [],
+      };
+      return {
+        cacheKeyUrl: 'eos-64acd1e7-202605281106-user-door-authorize',
+        selection: [],
+        defaultForm,
+        // 表单数据
+        form: { ...defaultForm },
+        // 表单验证规则
+        rules: {
+          isPermanent: [{ required: true, message: '请选择授权类型', trigger: 'blur' }],
+          validTime: [{ required: true, message: '请选择授权时间', trigger: 'blur' }],
+        },
+        // 提交状态
+        loading: false,
+        // 是否是修改
+        isUpdate: false,
+        userInfo: {
+          postName: '',
+        },
+        // datasource: [],
+        deviceOptions: [],
+        bindDeviceData: [],
+      };
+    },
+    computed: {
+      // 是否开启响应式布局
+      styleResponsive() {
+        return this.$store.state.theme.styleResponsive;
+      },
+      columns() {
+        return [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            prop: 'deviceName',
+            label: '设备名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 200
+          },
+          {
+            prop: 'ipAddress',
+            label: '设备IP',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 160
+          },
+          {
+            prop: 'port',
+            label: '端口',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 130
+          },
+          {
+            prop: 'doorCount',
+            label: '门数',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+          },
+          {
+            prop: 'model',
+            label: '型号',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 200,
+          },
+          {
+            prop: 'isBind',
+            label: '是否绑定',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+            formatter: (row) => {
+              return row.isBind ? '已绑定' : '未绑定';
+            }
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+            formatter: (row) => {
+              return row.status == 1 ? '在线' : '离线';
+            }
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 120,
+            align: 'center',
+            resizable: false,
+            slot: 'action',
+            showOverflowTooltip: true,
+            fixed: 'right'
+          }
+        ]
+      }
+    },
+    mounted() {
+
+    },
+    methods: {
+      async datasource({ page, limit, where, order }) {
+        console.log(this.list, 'this.list');
+        const res = await listDevice({ ...where, ...order, pageNum: page, size: limit });
+        // 与已绑定设备对比,标记绑定状态
+        if (res.list && this.list.length > 0) {
+          console.log(this.list, 'this.list~~~');
+          const bindDeviceIds = this.list.map(item => item.deviceId);
+          console.log(bindDeviceIds, 'bindDeviceIds');
+          res.list = res.list.map(item => ({
+            ...item,
+            isBind: bindDeviceIds.includes(item.id) ? true : false
+          }));
+        }
+        console.log(res, 'res');
+        return res;
+      },
+ 
+      bindUserDevice(row) {
+        console.log(row, 'row');
+        bindDevice({
+          deviceId: row.id,
+          userId: this.current.id,
+          jobNumber: this.current.jobNumber,
+        }).then(res => {
+          console.log(res, 'res');
+          this.$message({
+            message: '绑定成功',
+            type: 'success'
+          });
+          row.isBind = true;
+     
+          this.$emit('success');
+        }).catch(err => {
+          console.log(err, 'err');
+          // this.$message({
+          //   message: '绑定失败',
+          //   type: 'error'
+          // });
+        })
+      },
+
+      submitForm() {
+        this.$refs.form?.validate(valid => {
+          if (valid) {
+            this.loading = true;
+            editBind({
+              deviceId: this.deviceInfo.deviceId,
+              id: this.deviceInfo.id,
+              isPermanent: this.form.isPermanent,
+              jobNumber: this.current.jobNumber,
+              userId: this.current.id,
+              validEnd: this.form.validTime.length > 0 ? this.form.validTime[1] : '',
+              validStart: this.form.validTime.length > 0 ? this.form.validTime[0] : '',
+            }).then(res => {
+              this.loading = false;
+              this.$message({
+                message: '操作成功',
+                type: 'success'
+              });
+              this.$emit('success');
+              this.updateVisible(false);
+            }).catch(err => {
+              this.loading = false;
+              // this.$message({
+                //   message: '绑定失败',
+                //   type: 'error'
+                // });
+            })
+          }
+        })
+      },
+      /* 保存编辑 */
+      /* 更新visible */
+      updateVisible(value) {
+        this.$emit('update:visible', value);
+      },
+    },
+    watch: {
+      visible(visible) {
+        console.log(visible, 'visible');
+        if (visible) {
+        
+        } else {
+          this.$refs.form?.clearValidate();
+          this.form = { ...this.defaultForm };
+        }
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  :deep(.el-input--medium .el-input__inner) {
+    height: auto !important;
+  }
+  :deep(.el-table) {
+    .el-form-item {
+      margin-bottom: 0;
+    }
+  }
+  :deep(.organizationList .el-input__inner) {
+    border: 0;
+    background: none;
+  }
+  :deep(.organizationList .el-input__suffix) {
+    display: none;
+  }
+  :deep(.organizationList .el-tag) {
+    background: none;
+  }
+</style>

+ 352 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/door-bind.vue

@@ -0,0 +1,352 @@
+<!-- 用户编辑弹窗 -->
+<template>
+  <ele-modal
+    width="1100px"
+    :visible="visible"
+    :append-to-body="true"
+    :close-on-click-modal="false"
+    custom-class="ele-dialog-form"
+    title="添加设备"
+    @update:visible="updateVisible"
+    :maxable="true"
+  >
+    <el-form
+      ref="form"
+      :autoComplete="false"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="设备名称:" prop="deviceName">
+            <el-input
+              clearable
+              :maxlength="200"
+              v-model="form.deviceName"
+              placeholder="请输入设备名称"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="" prop="deviceName">
+            <!-- <el-input
+              clearable
+              :maxlength="200"
+              v-model="form.deviceName"
+              placeholder="请输入设备名称"
+            /> -->
+            <el-button type="primary" @click="handleSearch">
+              查询
+            </el-button>
+            <el-button type="primary" @click="handleReset">
+              重置
+            </el-button>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <ele-pro-table
+            ref="table"
+            :columns="columns"
+            :datasource="datasource"
+            height="calc(100vh - 405px)"
+            style="margin-bottom: 10px"
+            full-height="calc(100vh - 116px)"
+            tool-class="ele-toolbar-form"
+            :selection.sync="selection"
+            :page-size="20"
+            @columns-change="handleColumnChange"
+            :cache-key="cacheKeyUrl"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+
+            </template>
+
+            <!-- 操作列 -->
+            <template v-slot:action="{ row }">
+              <el-link
+                v-if="!row.isBind"
+                type="primary"
+                :underline="false"
+                icon="el-icon-edit"
+                @click="bindUserDevice(row)"
+              >
+                绑定
+              </el-link>
+              <!-- <el-popconfirm
+                class="ele-action"
+                title="确定要删除此信息吗?"
+                v-if="
+                  (isNeed_process_is_close &&
+                    [0, 3].includes(row.reviewStatus)) ||
+                  !isNeed_process_is_close
+                "
+                @confirm="remove([row.id])"
+              >
+                <template v-slot:reference>
+                  <el-link type="danger" :underline="false" icon="el-icon-delete">
+                    删除
+                  </el-link>
+                </template>
+              </el-popconfirm> -->
+            </template>
+          </ele-pro-table>
+        </el-col>
+      </el-row>
+    </el-form>
+    <template v-slot:footer>
+      <el-button @click="updateVisible(false)">取消</el-button>
+      <el-button type="primary" :loading="loading" @click="updateVisible(false)">
+        确定
+      </el-button>
+    </template>
+  </ele-modal>
+</template>
+
+<script>
+  import { getUserDetail } from '@/api/system/organization';
+  import { listDoorUsers, listDevice, bindDevice } from '@/api/‌doorSecurity‌'
+  import tabMixins from '@/mixins/tableColumnsMixin';
+  export default {
+    components: {  },
+    mixins: [tabMixins],
+    props: {
+      // 弹窗是否打开
+      visible: Boolean,
+      // isUpdate: Boolean,
+      // 修改回显的数据
+      current: Object,
+      list: Array,
+    },
+    data() {
+      const defaultForm = {
+        deviceName: '',
+      };
+      return {
+        cacheKeyUrl: 'eos-64acd1e7-202605281106-user-door-bind',
+        selection: [],
+        statusOptions: [
+          { 
+            label: '待同步',
+            value: 0
+
+          },
+          {
+            label: '已同步',
+            value: 1
+          },
+          {
+            label: '失败',
+            value: 2
+          }
+        ],
+        defaultForm,
+        // 表单数据
+        form: { ...defaultForm },
+        // 表单验证规则
+        rules: {},
+        // 提交状态
+        loading: false,
+        // 是否是修改
+        isUpdate: false,
+        userInfo: {
+          postName: '',
+        },
+        // datasource: [],
+        deviceOptions: [],
+        bindDeviceData: []
+      };
+    },
+    computed: {
+      // 是否开启响应式布局
+      styleResponsive() {
+        return this.$store.state.theme.styleResponsive;
+      },
+      columns() {
+        return [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            prop: 'deviceName',
+            label: '设备名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 200
+          },
+          {
+            prop: 'ipAddress',
+            label: '设备IP',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 160
+          },
+          {
+            prop: 'port',
+            label: '端口',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 130
+          },
+          {
+            prop: 'doorCount',
+            label: '门数',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+          },
+          {
+            prop: 'model',
+            label: '型号',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 200,
+          },
+          {
+            prop: 'isBind',
+            label: '是否绑定',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+            formatter: (row) => {
+              return row.isBind ? '已绑定' : '未绑定';
+            }
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+            formatter: (row) => {
+              return row.status == 1 ? '在线' : '离线';
+            }
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 120,
+            align: 'center',
+            resizable: false,
+            slot: 'action',
+            showOverflowTooltip: true,
+            fixed: 'right'
+          }
+        ]
+      }
+    },
+    mounted() {
+
+    },
+    methods: {
+      handleSearch() {
+        this.reload(this.form);
+      },
+      handleReset() {
+        this.form = { ...this.defaultForm };
+        this.reload(this.form);
+      },
+      async datasource({ page, limit, where, order }) {
+        console.log(this.list, 'this.list');
+        const res = await listDevice({ ...where, ...order, pageNum: page, size: limit });
+        // 与已绑定设备对比,标记绑定状态
+        if (res.list && this.list.length > 0) {
+          console.log(this.list, 'this.list~~~');
+          const bindDeviceIds = this.list.map(item => item.deviceId);
+          console.log(bindDeviceIds, 'bindDeviceIds');
+          res.list = res.list.map(item => ({
+            ...item,
+            isBind: bindDeviceIds.includes(item.id) ? true : false
+          }));
+        }
+        console.log(res, 'res');
+        return res;
+      },
+      reload(where) {
+        this.$refs.table.reload({ pageNum: 1, where: where });
+      },
+      bindUserDevice(row) {
+        console.log(row, 'row');
+        bindDevice({
+          deviceId: row.id,
+          userId: this.current.id,
+          jobNumber: this.current.jobNumber,
+        }).then(res => {
+          console.log(res, 'res');
+          this.$message({
+            message: '绑定成功',
+            type: 'success'
+          });
+          row.isBind = true;
+          this.reload();
+          this.$emit('success');
+        }).catch(err => {
+          console.log(err, 'err');
+          // this.$message({
+          //   message: '绑定失败',
+          //   type: 'error'
+          // });
+        })
+      },
+
+      async getUserDetail() {
+        if (!this.current.id) {
+          return;
+        }
+        this.userInfo = await getUserDetail(this.current.id);
+      },
+      /* 保存编辑 */
+      /* 更新visible */
+      updateVisible(value) {
+        this.$emit('update:visible', value);
+      },
+    },
+    watch: {
+      visible(visible) {
+        console.log(visible, 'visible');
+        if (visible) {
+          this.reload();
+        } else {
+          this.$refs.form?.clearValidate();
+          this.form = { ...this.defaultForm };
+        }
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  :deep(.el-input--medium .el-input__inner) {
+    height: auto !important;
+  }
+  :deep(.el-table) {
+    .el-form-item {
+      margin-bottom: 0;
+    }
+  }
+  :deep(.organizationList .el-input__inner) {
+    border: 0;
+    background: none;
+  }
+  :deep(.organizationList .el-input__suffix) {
+    display: none;
+  }
+  :deep(.organizationList .el-tag) {
+    background: none;
+  }
+</style>

+ 375 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/door-modal.vue

@@ -0,0 +1,375 @@
+<!-- 用户编辑弹窗 -->
+<template>
+  <ele-modal
+    width="1100px"
+    :visible="visible"
+    :append-to-body="true"
+    :close-on-click-modal="false"
+    custom-class="ele-dialog-form"
+    title="门禁"
+    @update:visible="updateVisible"
+    :maxable="true"
+  >
+    <el-form
+      ref="form"
+      :autoComplete="false"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-row>
+        <el-col :span="24" style="margin-bottom: 20px;">
+          <!-- <el-form-item label="设备:" prop="deviceId">
+            <el-select
+              v-model="form.deviceId"
+              placeholder="请选择"
+              style="width: 100%"
+              @change="handleDeviceChange"
+            >
+              <el-option
+                v-for="item in deviceOptions"
+                :key="item.id"
+                :label="item.deviceName"
+                :value="item.id"
+              >
+              </el-option>
+            </el-select>
+            
+          </el-form-item> -->
+          <!-- <el-form-item label="" prop="deviceId"> -->
+            <!-- <el-select
+              v-model="form.deviceId"
+              placeholder="请选择"
+              style="width: 100%"
+              @change="handleDeviceChange"
+            >
+              <el-option
+                v-for="item in deviceOptions"
+                :key="item.id"
+                :label="item.deviceName"
+                :value="item.id"
+              >
+              </el-option>
+            </el-select> -->
+            <el-button type="primary" @click="handleBindDevice">添加设备</el-button>
+          <!-- </el-form-item> -->
+        </el-col>
+        <el-col :span="24">
+          <ele-pro-table
+            ref="table"
+            :columns="columns"
+            :datasource="datasource"
+            height="calc(100vh - 405px)"
+            style="margin-bottom: 10px"
+            full-height="calc(100vh - 116px)"
+            tool-class="ele-toolbar-form"
+            :selection.sync="selection"
+            :page-size="20"
+            @columns-change="handleColumnChange"
+            :cache-key="cacheKeyUrl"
+            :needPage="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+
+            </template>
+
+            <!-- 操作列 -->
+            <template v-slot:action="{ row }">
+              <el-link
+                type="primary"
+                :underline="false"
+                @click="handleAuthorize(row)"
+              >
+                授权
+              </el-link>
+              <el-link
+                type="primary"
+                :underline="false"
+                @click="handleSync(row)"
+              >
+                同步
+              </el-link>
+              <el-popconfirm
+                class="ele-action"
+                title="确定要解绑吗?"
+                @confirm="unbind(row)"
+              >
+                <template v-slot:reference>
+                  <el-link type="danger" :underline="false">
+                    解绑
+                  </el-link>
+                </template>
+              </el-popconfirm>
+            </template>
+          </ele-pro-table>
+        </el-col>
+      </el-row>
+    </el-form>
+    <template v-slot:footer>
+      <el-button @click="updateVisible(false)">取消</el-button>
+      <el-button type="primary" :loading="loading" @click="updateVisible(false)">
+        确定
+      </el-button>
+    </template>
+    <!-- 授权 -->
+    <doorAuthorize ref="doorAuthorizeRef" :current="current" :deviceInfo="deviceInfo" :list="datasource" :visible.sync="showAuthorize" @success="getData"></doorAuthorize>
+    <!-- 绑定 -->
+    <doorBind ref="doorBindRef" :current="current" :list="datasource" :visible.sync="showBind" @success="getData"></doorBind>
+  </ele-modal>
+</template>
+
+<script>
+  // import { emailReg, phoneReg } from 'ele-admin';
+  import doorAuthorize from './door-authorize.vue';
+  import doorBind from './door-bind.vue';
+  import { getUserDetail } from '@/api/system/organization';
+  import { listDoorUsers, listDevice, syncDevice, unbindDevice } from '@/api/‌doorSecurity‌'
+  import tabMixins from '@/mixins/tableColumnsMixin';
+  export default {
+    components: { doorAuthorize, doorBind },
+    mixins: [tabMixins],
+    props: {
+      // 弹窗是否打开
+      visible: Boolean,
+      // 修改回显的数据
+      current: Object,
+    },
+    data() {
+      const defaultForm = {
+        deviceId: '',
+      };
+      return {
+        showAuthorize: false,
+        deviceInfo: {},
+        cacheKeyUrl: 'eos-64acd1e7-202605271646-user-door',
+        selection: [],
+        statusOptions: [
+          { 
+            label: '待同步',
+            value: 0
+
+          },
+          {
+            label: '已同步',
+            value: 1
+          },
+          {
+            label: '失败',
+            value: 2
+          }
+        ],
+        defaultForm,
+        // 表单数据
+        form: { ...defaultForm },
+        // 表单验证规则
+        rules: {},
+        // 提交状态
+        loading: false,
+        // 是否是修改
+        userInfo: {
+          postName: '',
+        },
+        datasource: [],
+        deviceOptions: [],
+        showBind: false,
+      };
+    },
+    computed: {
+      // 是否开启响应式布局
+      styleResponsive() {
+        return this.$store.state.theme.styleResponsive;
+      },
+      columns() {
+        return [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            prop: 'deviceName',
+            label: '设备名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 200
+          },
+          {
+            prop: 'ipAddress',
+            label: '设备IP',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 160
+          },
+          {
+            prop: 'port',
+            label: '端口',
+            align: 'center',
+            showOverflowTooltip: true,
+            sortable: true,
+            minWidth: 130
+          },
+          {
+            prop: 'isPermanent',
+            label: '是否长期授权',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+            formatter: (row) => {
+              return row.isPermanent === 1 ? '是' : '否';
+            }
+          },
+          {
+            prop: 'validStart',
+            label: '有效期',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 200,
+            formatter: (row) => {
+              return row.validStart ? row.validStart + '~' + row.validEnd : '';
+            }
+          },
+          {
+            prop: 'syncStatus',
+            label: '状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 130,
+            formatter: (row) => {
+              return this.statusOptions.find(item => item.value === row.syncStatus)?.label || '';
+            }
+          },
+          {
+            prop: 'syncMsg',
+            label: '同步日志',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 150
+          },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 170
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 200,
+            align: 'center',
+            resizable: false,
+            slot: 'action',
+            showOverflowTooltip: true,
+            fixed: 'right'
+          }
+        ]
+      }
+    },
+    mounted() {
+      console.log('mounted~~~');
+      // this.getData();
+    },
+    methods: {
+      unbind(row) {
+        unbindDevice(row.id).then(res => {
+          this.$message({
+            message: '解绑成功',
+            type: 'success'
+          });
+          this.getData();
+        }).catch(err => {
+        })
+      },
+      handleBindDevice() {
+        this.showBind = true;
+      },
+      async handleSync(row) {
+        await syncDevice(row.id);
+        this.$message({
+          message: '同步成功',
+          type: 'success'
+        });
+        this.getData();
+      },
+      handleAuthorize(row) {
+        this.deviceInfo = row;
+        this.showAuthorize = true;
+        console.log(row, 'row');
+      },
+      handleDeviceChange(val) {
+        console.log(val, 'val');
+        this.getData();
+      },
+      getData() {
+        listDoorUsers({ userId: this.current.id, ...this.form }).then(res => {
+          console.log(res, 'res');
+          this.datasource = res;
+        })
+      },
+      getDeviceList() {
+        listDevice({
+          size: 9999,
+          pageNum: 1,
+        }).then(res => {
+          console.log(res, 'res');
+          this.deviceOptions = res.list;
+        })
+      },
+      async getUserDetail() {
+        if (!this.form.mainUserId) {
+          return;
+        }
+        this.userInfo = await getUserDetail(this.form.mainUserId);
+      },
+      /* 更新visible */
+      updateVisible(value) {
+        this.$emit('update:visible', value);
+      },
+    },
+    watch: {
+      visible(visible) {
+        console.log(visible, 'visible');
+        if (visible) {
+          this.getDeviceList();
+          this.getData();
+        } else {
+          this.$refs.form?.clearValidate();
+          this.form = { ...this.defaultForm };
+        }
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  :deep(.el-input--medium .el-input__inner) {
+    height: auto !important;
+  }
+  :deep(.el-table) {
+    .el-form-item {
+      margin-bottom: 0;
+    }
+  }
+  :deep(.organizationList .el-input__inner) {
+    border: 0;
+    background: none;
+  }
+  :deep(.organizationList .el-input__suffix) {
+    display: none;
+  }
+  :deep(.organizationList .el-tag) {
+    background: none;
+  }
+</style>

+ 621 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/org-user-list.vue

@@ -0,0 +1,621 @@
+<template>
+  <div>
+    <!-- 数据表格 -->
+    <org-user-search @search="reload" ref="searchRef"></org-user-search>
+    <ele-pro-table
+      ref="table"
+      :columns="columns"
+      :datasource="datasource"
+      height="calc(100vh - 265px)"
+      full-height="calc(100vh - 116px)"
+      tool-class="ele-toolbar-form"
+      :page-size="pageSize"
+      row-key="id"
+      :selection.sync="selection"
+      @columns-change="handleColumnChange"
+      :cache-key="cacheKeyUrl"
+      @update:selection="handleSelectionChange"
+    >
+      <!-- 表头工具栏 -->
+      <template v-slot:toolbar>
+        <el-button
+          size="small"
+          type="primary"
+          icon="el-icon-plus"
+          class="ele-btn-icon"
+          @click="openEdit()"
+          v-if="$hasPermission('main:user:save')"
+        >
+          添加
+        </el-button>
+        <el-button
+          type="primary"
+          size="mini"
+          icon="el-icon-upload2"
+          plain
+          @click="uploadFile"
+          v-if="$hasPermission('main:user:save')"
+          >导入</el-button
+        >
+        <el-button
+          type="primary"
+          size="mini"
+          icon="el-icon-download"
+          plain
+          @click="exportUsers"
+          >导出</el-button
+        >
+        <el-button
+          type="success"
+          size="mini"
+          icon="el-icon-guide"
+          plain
+          @click="bindingProcess"
+          >绑定关键工序</el-button
+        >
+        <el-button
+          v-if="$hasPermission('main:user:push')"
+          :disabled="selection?.length === 0"
+          type="primary"
+          size="mini"
+          plain
+          @click="allPushBtn"
+          >批量推送</el-button
+        >
+      </template>
+      <!-- 角色列 -->
+      <template v-slot:roles="{ row }">
+        <el-tag
+          v-for="item in row.roles"
+          :key="item.roleId"
+          type="primary"
+          size="mini"
+          :disable-transitions="true"
+        >
+          {{ item.roleName }}
+        </el-tag>
+      </template>
+
+      <template v-slot:name="{ row }">
+        <el-link type="primary" :underline="false" @click="openEdit(row, true)">
+          {{ row.name }}</el-link
+        >
+      </template>
+      <!-- 状态列 -->
+      <!--      <template v-slot:status="{ row }">
+        <el-switch
+          :active-value="0"
+          :inactive-value="1"
+          v-model="row.status"
+          @change="editStatus(row)"
+        />
+      </template> -->
+      <!-- 操作列 -->
+      <template v-slot:action="{ row }">
+        <el-link
+          type="primary"
+          :underline="false"
+          icon="el-icon-edit"
+          @click="openEdit(row)"
+          v-if="$hasPermission('main:user:save')"
+        >
+          修改
+        </el-link>
+        <el-link
+          v-if="row.loginName && $hasPermission('main:user:save')"
+          type="primary"
+          :underline="false"
+          icon="el-icon-unlock"
+          @click="toUnBind(row)"
+        >
+          解绑
+        </el-link>
+        <el-link
+          v-if="!row.loginName && $hasPermission('main:user:save')"
+          type="primary"
+          :underline="false"
+          icon="el-icon-add"
+          @click="addUsers(row)"
+        >
+          新建账号
+        </el-link>
+        <el-link
+          type="primary"
+          :underline="false"
+          icon="el-icon-key"
+          @click="openDoor(row)"
+        >
+          门禁
+        </el-link>
+        <el-popconfirm
+          class="ele-action"
+          title="确定要删除此用户吗?"
+          @confirm="remove(row)"
+          v-if="!row.loginName && $hasPermission('main:user:delete')"
+        >
+          <template v-slot:reference>
+            <el-link type="danger" :underline="false" icon="el-icon-delete">
+              删除
+            </el-link>
+          </template>
+        </el-popconfirm>
+      </template>
+    </ele-pro-table>
+    <!-- 编辑弹窗 -->
+    <org-user-edit
+      :data="current"
+      :visible.sync="showEdit"
+      :organization-list="organizationList"
+      :institutionList="institutionList"
+      :organization-id="organizationId"
+      @done="reload"
+      ref="userEditRef"
+    />
+    <addUsers
+      :visible.sync="showEdit1"
+      @done="reload"
+      :data="null"
+      ref="userEdit"
+      :organizationList="organizationList"
+    />
+    <importDialog
+      :defModule="moudleName"
+      ref="importDialogRef"
+      @success="reload"
+    />
+    <el-dialog
+      title="提示"
+      :visible.sync="dialogVisible"
+      @close="dialogVisible = false"
+      width="400px"
+    >
+      <span>是否绑定已有用户?</span>
+      <el-radio v-model="radio" label="1">是</el-radio>
+      <el-radio v-model="radio" label="2">否</el-radio>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="setUser">确 定</el-button>
+      </span>
+    </el-dialog>
+
+    <DoorModal ref="doorModalRef" :visible.sync="showDoor" :current="current" />
+  </div>
+</template>
+
+<script>
+  import tabMixins from '@/mixins/tableColumnsMixin';
+
+  import OrgUserSearch from './org-user-search.vue';
+  import importDialog from '@/components/upload/import-dialog.vue';
+  import {
+    getUserPage,
+    removePersonnel,
+    unbindLoginName,
+    employeePush
+  } from '@/api/system/organization';
+  import { pageUsers, exportUsers } from '@/api/system/user';
+  import dictMixins from '@/mixins/dictMixins';
+  import { getFactoryarea } from '@/api/factoryModel';
+  import DoorModal from './door-modal.vue';
+
+  export default {
+    mixins: [tabMixins, dictMixins],
+    components: {
+      importDialog,
+      OrgUserSearch,
+      DoorModal
+    },
+    props: {
+      // 机构id
+      organizationId: [Number, String],
+      // 全部机构
+      organizationList: Array,
+      institutionList: Array
+    },
+    created() {
+      this.requestDict('岗位');
+      getFactoryarea({
+        pageNum: 1,
+        size: 999,
+        type: 1
+      }).then((res) => {
+        this.factoryList = res.list || [];
+      });
+    },
+    computed: {
+      // 表格列配置
+      columns() {
+        let columnsVersion = this.columnsVersion;
+        return [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            prop: 'name',
+            label: '姓名',
+            slot: 'name',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'groupName',
+            label: '所属机构',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'deptNames',
+            label: '隶属部门',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+
+          {
+            prop: 'jobNumber',
+            label: '工号',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'phone',
+            label: '手机号',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'postName',
+            label: '岗位',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'factoryId',
+            label: '所属工厂',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row, _column, cellValue) => {
+              return this.factoryList.find((item) => item.id == cellValue)
+                ?.name;
+            }
+          },
+          {
+            prop: 'loginName',
+            label: '用户账号',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'sex',
+            label: '性别',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 80,
+            formatter: (_row, _column, cellValue) => {
+              return cellValue == 1 ? '男' : cellValue == 2 ? '女' : '';
+            }
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            align: 'center',
+            sortable: 'custom',
+            width: 80,
+            formatter: (_row, _column, cellValue) => {
+              const dom = this.statusOptions.find((item) => {
+                return item.value == cellValue;
+              });
+              return dom ? dom.label : '';
+            }
+          },
+          {
+            prop: 'code',
+            label: '是否推送',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120,
+            formatter: (_row, _column, cellValue) => {
+              return _row.code ? '已推送' : '未推送';
+            }
+          },
+          {
+            prop: 'isEnabled',
+            align: 'center',
+            label: '是否启用',
+            showOverflowTooltip: true,
+            formatter: (row, column) => {
+              return row.isEnabled === 0
+                ? '停用'
+                : row.isEnabled === 1
+                ? '启用'
+                : '';
+            }
+          },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row, _column, cellValue) => {
+              return this.$util.toDateString(cellValue);
+            }
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 260,
+            align: 'left',
+            resizable: false,
+            fixed: 'right',
+            slot: 'action',
+            showOverflowTooltip: true
+          }
+        ];
+      }
+    },
+    data() {
+      return {
+        showDoor: false,
+        moudleName: 'mainUser',
+        showEdit1: false,
+        userShow: false,
+        userRow: null,
+        currentRow: null,
+        dialogVisible: false,
+        radio: '2',
+        columnsVersion: 0,
+        factoryList: [],
+        // 表格列配置
+        columns1: [
+          {
+            columnKey: 'index',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left',
+            label: '序号'
+          },
+          {
+            prop: 'loginName',
+            label: '用户账号',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'jobNumber',
+            label: '工号',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'name',
+            label: '姓名',
+
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'phone',
+            label: '手机号',
+
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+
+          {
+            columnKey: 'groupRoleList',
+            label: '角色',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row, _column, cellValue) => {
+              let names = [];
+              _row.groupRoleList.forEach((item) => {
+                names.push(...item.roleVOList.map((val) => val.name));
+              });
+              return names.toString();
+            }
+          },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            // sortable: 'custom',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row, _column, cellValue) => {
+              return this.$util.toDateString(cellValue);
+            }
+          }
+        ],
+        // 当前编辑数据
+        current: null,
+        // 是否显示编辑弹窗
+        showEdit: false,
+        statusOptions: [
+          { value: 1, label: '全职' },
+          { value: 2, label: '兼职' },
+          { value: 3, label: '实习' },
+          { value: 4, label: '正式' },
+          { value: 5, label: '试用' },
+          { value: 6, label: '离职' }
+        ],
+        pageSize: this.$store.state.tablePageSize,
+        cacheKeyUrl: 'ef00833a-system-organization',
+        selection: []
+      };
+    },
+    methods: {
+      openDoor(row) {
+        console.log(row);
+        this.current = row;
+        this.showDoor = true;
+      },
+      allPushBtn() {
+        const dataId = this.selection.map((v) => v.id);
+        employeePush(dataId)
+          .then((res) => {
+            this.$message.success('推送成功!');
+            this.reload();
+          })
+          .catch(() => {
+            console.log('推送失败!');
+          });
+      },
+      async addUsers(row) {
+        // this.userRow = null;
+        this.currentRow = row;
+        this.dialogVisible = true;
+      },
+      setUser() {
+        this.dialogVisible = false;
+        if (this.radio == 1) {
+          this.userShow = true;
+        } else {
+          this.showEdit1 = true;
+          this.$refs.userEdit.userBk(this.currentRow);
+        }
+      },
+      getUser() {
+        if (!this.userRow) {
+          this.$message.warning('请选择一条数据!');
+          return;
+        }
+        this.userShow = false;
+        this.showEdit1 = true;
+        this.$refs.userEdit.getByData(this.userRow, this.currentRow);
+      },
+
+      /* 表格数据源 */
+      datasource({ page, limit, where, order }) {
+        return getUserPage({
+          ...where,
+          pageNum: page,
+          orderName: order.order || '',
+          sortBy: order.sort || '',
+          size: limit,
+          groupId: this.organizationId,
+          isQueryLZ: 1,
+          affiDeptId: 1
+        });
+      },
+      /* 表格数据源 */
+      datasource1({ page, limit, where, order }) {
+        return pageUsers({
+          ...where,
+          ...order,
+          pageNum: page,
+          size: limit
+        });
+      },
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ pageNum: 1, where: where });
+      },
+      reload1(where) {
+        this.$refs.table1.reload({ pageNum: 1, where: where });
+      },
+      exportUsers() {
+        let where = this.$refs.searchRef.geValue();
+        this.reload(where);
+
+        exportUsers({
+          ...where,
+          pageNum: 1,
+          size: 10000,
+          groupId: this.organizationId
+        });
+      },
+      /* 显示编辑 */
+      openEdit(row, disabled) {
+        this.current = row;
+        this.showEdit = true;
+        this.$refs.userEditRef.setDisabled(disabled);
+      },
+
+      bindingProcess() {
+        if (this.selection.length == 0) {
+          return this.$message.warning('请至少选择一名需要绑定的人员');
+        }
+
+        this.$refs.criticalProcessRef.open(this.selection, 'batch');
+      },
+
+      chooseProcess() {
+        this.reload();
+      },
+
+      handleSelectionChange(data) {
+        this.selection = data;
+      },
+
+      // 解除绑定
+      toUnBind(row) {
+        const loading = this.$loading({ lock: true });
+        unbindLoginName(row.id)
+          .then((res) => {
+            loading.close();
+            this.$message.success('解绑成功');
+            this.reload();
+          })
+          .catch((e) => {
+            loading.close();
+            // this.$message.error(e.message);
+          });
+      },
+      /* 删除 */
+      remove(row) {
+        const loading = this.$loading({ lock: true });
+        removePersonnel([row.id])
+          .then((msg) => {
+            loading.close();
+            this.$message.success(msg);
+            this.reload();
+          })
+          .catch((e) => {
+            loading.close();
+            // this.$message.error(e.message);
+          });
+      },
+      /* 更改状态 */
+      editStatus(row) {
+        const loading = this.$loading({ lock: true });
+        updateUserStatus(row.userId, row.status)
+          .then((msg) => {
+            loading.close();
+            this.$message.success(msg);
+          })
+          .catch((e) => {
+            loading.close();
+            row.status = !row.status ? 1 : 0;
+            // this.$message.error(e.message);
+          });
+      },
+      uploadFile() {
+        this.$refs.importDialogRef.open();
+      }
+    },
+    watch: {
+      // 监听机构id变化
+      organizationId() {
+        this.reload();
+      }
+    }
+  };
+</script>

+ 73 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/org-user-search.vue

@@ -0,0 +1,73 @@
+<!-- 搜索表单 -->
+<template>
+  <seekPage :seekList="seekList" :formLength="3" @search="search"></seekPage>
+</template>
+
+<script>
+  export default {
+    data() {
+      return { where: { jobNumber: '', loginName: '', name: '' } };
+    },
+    computed: {
+      seekList() {
+        return [
+          {
+            label: '工号:',
+            value: 'jobNumber',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '用户账号:',
+            value: 'loginName',
+            type: 'input',
+            placeholder: '请输入'
+          },
+
+          {
+            label: '姓名:',
+            value: 'name',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '手机号:',
+            value: 'phone',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '岗位:',
+            value: 'postId',
+            type: 'DictSelection',
+            dictName: '岗位',
+            placeholder: '请输入'
+          },
+          {
+            label: '状态:',
+            value: 'status',
+            type: 'select',
+            planList: [
+              { value: 1, label: '全职' },
+              { value: 2, label: '兼职' },
+              { value: 3, label: '实习' },
+              { value: 4, label: '正式' },
+              { value: 5, label: '试用' },
+              { value: 6, label: '离职' }
+            ],
+            placeholder: '请选择'
+          }
+        ];
+      }
+    },
+    methods: {
+      search(e) {
+        this.where = e;
+        this.$emit('search', { ...e });
+      },
+      geValue() {
+        return this.where;
+      }
+    }
+  };
+</script>

+ 189 - 0
src/views/‌doorSecurity‌/personnelAuthorization/index.vue

@@ -0,0 +1,189 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never" v-loading="loading">
+      <ele-split-layout
+        width="266px"
+        allow-collapse
+        :right-style="{ overflow: 'hidden' }"
+      >
+        <div>
+          <!-- 操作按钮 -->
+          <ele-toolbar class="ele-toolbar-actions">
+            <div style="margin: 5px 0">
+              <el-button
+                size="small"
+                type="primary"
+                icon="el-icon-plus"
+                class="ele-btn-icon"
+                @click="openEdit()"
+                v-if="$hasPermission('main:group:save')"
+              >
+                添加
+              </el-button>
+              <el-button
+                size="small"
+                type="warning"
+                icon="el-icon-edit"
+                class="ele-btn-icon"
+                :disabled="!current"
+                @click="openEdit(current)"
+                v-if="$hasPermission('main:group:update')"
+              >
+                修改
+              </el-button>
+              <el-button
+                size="small"
+                type="danger"
+                icon="el-icon-delete"
+                class="ele-btn-icon"
+                :disabled="!current"
+                @click="remove"
+                v-if="$hasPermission('main:group:delete')"
+              >
+                删除
+              </el-button>
+            </div>
+          </ele-toolbar>
+          <div class="ele-border-lighter sys-organization-list">
+            <el-tree
+              ref="tree"
+              :data="data"
+              highlight-current
+              node-key="id"
+              :props="{ label: 'name' }"
+              :expand-on-click-node="false"
+              :default-expand-all="true"
+              @node-click="onNodeClick"
+            />
+          </div>
+        </div>
+        <template v-slot:content>
+          <org-user-list
+            v-if="current"
+            :organization-list="data"
+            :organization-id="current.id"
+            :institutionList="institutionList"
+          />
+        </template>
+      </ele-split-layout>
+    </el-card>
+  </div>
+</template>
+
+<script>
+  import {
+    listOrganizations,
+    removeOrganization
+  } from '@/api/system/organization';
+  
+  import OrgUserList from './components/org-user-list.vue';
+
+  export default {
+    name: 'PersonnelAuthorization',
+    components: { OrgUserList },
+    data() {
+      return {
+        // 加载状态
+        loading: true,
+        // 列表数据
+        data: [],
+        institutionList: [],
+        // 选中数据
+        current: null,
+        // 是否显示表单弹窗
+        showEdit: false,
+        // 编辑回显数据
+        editData: null,
+        // 上级id
+        parentId: null
+      };
+    },
+    created() {
+      this.query();
+    },
+    methods: {
+      /* 查询 */
+      query() {
+        this.loading = true;
+        listOrganizations()
+          .then((list) => {
+            let _list = list.filter((i) => i.name != '超级管理员');
+            // let _institutionList = _list.filter((i) => [10, 20].includes(i.type));
+            console.log(this.institutionList);
+            this.loading = false;
+            this.data = this.$util.toTreeData({
+              data: _list,
+              idField: 'id',
+              parentIdField: 'parentId'
+            });
+            this.institutionList = this.$util.toTreeData({
+              data: _list,
+              idField: 'id',
+              parentIdField: 'parentId'
+            });
+            this.$nextTick(() => {
+              this.onNodeClick(this.data[0]);
+            });
+          })
+          .catch((e) => {
+            this.loading = false;
+            // this.$message.error(e.message);
+          });
+      },
+      /* 选择数据 */
+      onNodeClick(row) {
+        if (row) {
+          this.current = row;
+          this.parentId = row.id;
+          this.$refs.tree.setCurrentKey(row.id);
+        } else {
+          this.current = null;
+          this.parentId = null;
+        }
+      },
+      /* 显示编辑 */
+      openEdit(item) {
+        this.editData = item;
+        this.showEdit = true;
+      },
+      /* 删除 */
+      remove() {
+        this.$confirm('确定要删除选中的机构吗?', '提示', {
+          type: 'warning'
+        })
+          .then(() => {
+            const loading = this.$loading({ lock: true });
+            removeOrganization([this.current.id])
+              .then((msg) => {
+                loading.close();
+                this.$message.success(msg);
+                this.query();
+              })
+              .catch((e) => {
+                loading.close();
+                // this.$message.error(e.message);
+              });
+          })
+          .catch(() => {});
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .sys-organization-list {
+    height: calc(100vh - 264px);
+    box-sizing: border-box;
+    border-width: 1px;
+    border-style: solid;
+    overflow: auto;
+  }
+
+  .sys-organization-list :deep(.el-tree-node__content) {
+    height: 30px;
+
+    & > .el-tree-node__expand-icon {
+      margin-left: 10px;
+    }
+  }
+</style>