Przeglądaj źródła

feat: 门禁台账,出入记录, 绑定设备

liujt 2 miesięcy temu
rodzic
commit
f41647d8ef

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

@@ -72,4 +72,78 @@ export async function unbindDevice(id) {
     return res.data.data;
   }
   return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 门禁台账 - 列表
+ * @param params 查询条件
+ */
+export async function listDoorLedger(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 getDeviceDetail(id) {
+  const res = await request.get(`/mms/access/device/get/${id}`);
+  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 saveDevice(params) {
+  const res = await request.post(`/mms/access/device/save`, params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 门禁台账 - 删除
+ * @param id id字符串
+ */
+export async function removeDoorLedger(id) {
+  const res = await request.get(`/mms/access/device/del/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 门禁台账 - 更新状态
+ * @param id id字符串
+ */
+export async function enableDoorLedger(id, params) {
+  const res = await request.get(`/mms/access/device/enable/${id}`, {params});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 出入口记录 - 列表
+ * @param params 查询条件
+ */
+export async function listEntryExitRecords(params) {
+  const res = await request.get(`/mms/acs/record/list`, {
+    params: params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
 }

+ 86 - 0
src/api/‌doorSecurity‌/production/index.js

@@ -0,0 +1,86 @@
+import request from '@/utils/request';
+
+export default {
+  //列表
+  list: async (params) => {
+    const res = await request.get('/main/producetask/page', { params });
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  },
+  //获取工艺所属参数列表
+  paramList: async (params) => {
+    const res = await request.get('/main/producetask/param/page', { params });
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  },
+  //保存工艺所属参数列表
+  paramSave: async (data) => {
+    const res = await request.post('/main/producetask/param/save', data);
+    if (res.data.code == 0) {
+      return res.data.message;
+    }
+  },
+  //详情
+  getById: async (id) => {
+    const res = await request.get(`/main/producetask/getById/${id}`);
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  },
+  //详情
+  getCode: async () => {
+    const res = await request.get(
+      `/main/codemanage/getCode/process_management`
+    );
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  },
+  //保存
+  save: async (data) => {
+    const res = await request.post('/main/producetask/save', data);
+    if (res.data.code == 0) {
+      return res.data;
+    }
+  },
+  //删除
+  delete: async (data) => {
+    const res = await request.delete('/main/producetask/delete', { data });
+    if (res.data.code == 0) {
+      return res.data.message;
+    }
+    // return Promise.reject(new Error(res.data.message));
+  },
+
+  // 工序质检参数保存
+  saveBatch: async (data) => {
+    const res = await request.post('/main/taskqualityparam/saveBatch', data);
+    if (res.data.code == 0) {
+      return res.data;
+    }
+  },
+
+  //批量修改工作中心
+  bacthUpdate: async (data) => {
+    console.log(data, 'data');
+    const res = await request.put(`/main/producetask/batchUpdate`, data);
+
+    console.log(res, 'res');
+    if (res.data.code == 0) {
+      return res.data;
+    }
+
+    // return Promise.reject(new Error(res.data.message));
+  },
+
+  byTaskId: async (taskId) => {
+    const res = await request.get(
+      `/main/taskqualityparam/listByTaskId/${taskId}`
+    );
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  }
+};

+ 54 - 0
src/api/‌doorSecurity‌/work/index.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request';
+
+export default {
+  //列表
+  list: async (params) => {
+    const res = await request.get('/main/workcenter/page', { params });
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  },
+  //获取人员列表
+  getUserPage: async () => {
+    const res = await request.get('/main/user/getUserPage', {
+      params: {
+        pageNum: 1,
+        size: -1
+      }
+    });
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+  },
+
+  //保存
+  save: async (data) => {
+    const res = await request.post('/main/workcenter/save', data);
+    if (res.data.code == 0) {
+      return res.data.message;
+    }
+  },
+  //保存
+  update: async (data) => {
+    const res = await request.put('/main/workcenter/update', data);
+    if (res.data.code == 0) {
+      return res.data.message;
+    }
+  },
+  //删除
+  delete: async (data) => {
+    const res = await request.delete('/main/workcenter/delete', { data });
+    if (res.data.code == 0) {
+      return res.data.message;
+    }
+  },
+
+  centerCodeExists: async (code) => {
+    const res = await request.get(`/main/workcenter/codeExists/${code}`,);
+    if (res.data.code == 0) {
+      return res.data;
+    }
+  }
+
+
+};

+ 190 - 0
src/views/‌doorSecurity‌/doorLedger/components/addOrEditDialog.vue

@@ -0,0 +1,190 @@
+<template>
+  <el-dialog
+    :title="isEdit ? '修改设备' : '新增设备'"
+    :visible.sync="dialogVisible"
+    width="550px"
+    @close="handleClose"
+  >
+    <el-form
+      ref="editForm"
+      :model="formData"
+      :rules="formRules"
+      label-width="100px"
+    >
+      <el-form-item label="设备名称" prop="deviceName">
+        <el-input v-model="formData.deviceName" placeholder="请输入设备名称" clearable />
+      </el-form-item>
+      <el-form-item label="设备IP地址" prop="ipAddress">
+        <el-input v-model="formData.ipAddress" placeholder="请输入设备IP地址" clearable />
+      </el-form-item>
+      <el-form-item label="设备端口号" prop="port">
+        <el-input v-model="formData.port" placeholder="请输入设备端口号" clearable />
+      </el-form-item>
+      <el-form-item label="设备型号" prop="model">
+        <el-input v-model="formData.model" placeholder="请输入设备型号" clearable />
+      </el-form-item>
+      <el-form-item label="账号" prop="account">
+        <el-input v-model="formData.account" placeholder="请输入账号" clearable />
+      </el-form-item>
+      <el-form-item label="密码" prop="password">
+        <el-input v-model="formData.password" placeholder="请输入密码" clearable show-password />
+      </el-form-item>
+      <el-form-item label="门数量" prop="doorCount">
+        <el-input-number v-model="formData.doorCount" :min="0" :max="999" placeholder="请输入门数量" />
+      </el-form-item>
+      <el-form-item label="流名称" prop="stream">
+        <el-input v-model="formData.stream" placeholder="请输入流名称" clearable />
+      </el-form-item>
+      <!-- <el-form-item label="启用禁用" prop="enable">
+        <el-radio-group v-model="formData.enable">
+          <el-radio :label="0">启用</el-radio>
+          <el-radio :label="1">禁用</el-radio>
+        </el-radio-group>
+      </el-form-item> -->
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button type="primary" :loading="submitLoading" @click="handleSubmit">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import { getDeviceDetail, saveDevice } from '@/api/‌doorSecurity‌';
+
+  export default {
+    props: {
+      visible: {
+        type: Boolean,
+        default: false
+      },
+      // 编辑时的行数据
+      data: {
+        type: Object,
+        default: null
+      }
+    },
+    data() {
+      return {
+        isEdit: false,
+        submitLoading: false,
+        formData: {
+          id: null,
+          deviceName: '',
+          ipAddress: '',
+          port: '',
+          model: '',
+          account: '',
+          password: '',
+          doorCount: 0,
+          stream: '',
+          enable: 'true'
+        },
+        formRules: {
+          deviceName: [
+            { required: true, message: '请输入设备名称', trigger: 'blur' }
+          ],
+          ipAddress: [
+            { required: true, message: '请输入设备IP地址', trigger: 'blur' }
+          ],
+          port: [
+            { required: true, message: '请输入设备端口号', trigger: 'blur' }
+          ],
+          model: [
+            { required: true, message: '请输入设备型号', trigger: 'blur' }
+          ],
+          account: [
+            { required: true, message: '请输入账号', trigger: 'blur' }
+          ],
+          password: [
+            { required: true, message: '请输入密码', trigger: 'blur' }
+          ]
+        }
+      };
+    },
+    computed: {
+      dialogVisible: {
+        get() {
+          return this.visible;
+        },
+        set(val) {
+          this.$emit('update:visible', val);
+        }
+      }
+    },
+    watch: {
+      visible(val) {
+        if (val) {
+          // 确保 prop data 已经传入后再初始化表单
+          this.$nextTick(() => {
+            this.initForm();
+          });
+        }
+      }
+    },
+    methods: {
+      /* 初始化表单数据 */
+      async initForm() {
+        console.log('data~~~', this.data);
+        const row = this.data;
+        this.isEdit = !!row?.id;
+        if (row?.id) {
+          // this.formData = {
+          //   id: row.id,
+          //   deviceName: row.deviceName || '',
+          //   ipAddress: row.ipAddress || '',
+          //   port: row.port || '',
+          //   model: row.model || '',
+          //   account: row.account || '',
+          //   password: row.password || '',
+          //   doorCount: row.doorCount ?? 0,
+          //   stream: row.stream || '',
+          //   enable: row.enable || 'true'
+          // };
+          const res = await getDeviceDetail(row.id);
+          console.log(res, 'res');
+          this.formData = res;
+        } else {
+          this.formData = {
+            id: null,
+            deviceName: '',
+            ipAddress: '',
+            port: '',
+            model: '',
+            account: '',
+            password: '',
+            doorCount: 0,
+            stream: '',
+            enable: 'true'
+          };
+        }
+        this.$nextTick(() => {
+          this.$refs.editForm?.clearValidate();
+        });
+      },
+
+      /* 弹窗关闭 */
+      handleClose() {
+        this.$refs.editForm?.clearValidate();
+      },
+
+      /* 提交表单 */
+      handleSubmit() {
+        this.$refs.editForm.validate((valid) => {
+          if (!valid) return;
+          this.submitLoading = true;
+          // 提交接口 - 可根据实际接口调整
+          const loading = this.$loading({ lock: true });
+          // TODO: 替换为实际的保存接口
+          saveDevice(this.formData).then((res) => {
+            loading.close();
+            this.submitLoading = false;
+            this.$message.success(this.isEdit ? '修改成功' : '新增成功');
+            this.dialogVisible = false;
+            this.$emit('done');
+          });
+        });
+      }
+    }
+  };
+</script>

+ 159 - 0
src/views/‌doorSecurity‌/doorLedger/components/detailDialog.vue

@@ -0,0 +1,159 @@
+<template>
+  <el-dialog
+    title="查看详情"
+    :visible.sync="dialogVisible"
+    width="600px"
+    @close="handleClose"
+  >
+    <el-form
+      ref="detailForm"
+      :model="formData"
+      label-width="100px"
+      v-loading="detailLoading"
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="设备名称">
+            <el-input v-model="formData.deviceName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="设备IP地址">
+            <el-input v-model="formData.ipAddress" disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="设备端口号">
+            <el-input v-model="formData.port" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="设备型号">
+            <el-input v-model="formData.model" disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="账号">
+            <el-input v-model="formData.account" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="门数量">
+            <el-input v-model="formData.doorCount" disabled />
+          </el-form-item>
+        </el-col>
+        <!-- <el-col :span="12">
+          <el-form-item label="密码">
+            <el-input v-model="formData.password" disabled show-password />
+          </el-form-item>
+        </el-col> -->
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="流名称">
+            <el-input v-model="formData.stream" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="是否启用">
+            <el-tag :type="formData.enable == 0 ? 'success' : 'danger'" size="medium">
+              {{ formData.enable == 0 ? '启用' : '禁用' }}
+            </el-tag>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="dialogVisible = false">关 闭</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+  export default {
+    props: {
+      visible: {
+        type: Boolean,
+        default: false
+      },
+      // 行数据
+      data: {
+        type: Object,
+        default: null
+      }
+    },
+    data() {
+      return {
+        detailLoading: false,
+        formData: {
+          deviceName: '',
+          ipAddress: '',
+          port: '',
+          model: '',
+          account: '',
+          password: '',
+          doorCount: '',
+          stream: '',
+          enable: ''
+        }
+      };
+    },
+    computed: {
+      dialogVisible: {
+        get() {
+          return this.visible;
+        },
+        set(val) {
+          this.$emit('update:visible', val);
+        }
+      }
+    },
+    watch: {
+      visible(val) {
+        if (val) {
+          this.$nextTick(() => {
+            this.initForm();
+          });
+        }
+      }
+    },
+    methods: {
+      /* 初始化表单数据 */
+      initForm() {
+        const row = this.data;
+        if (row) {
+          this.formData = {
+            deviceName: row.deviceName || '',
+            ipAddress: row.ipAddress || '',
+            port: row.port || '',
+            model: row.model || '',
+            account: row.account || '',
+            password: row.password || '',
+            doorCount: row.doorCount ?? '',
+            stream: row.stream || '',
+            enable: row.enable ?? ''
+          };
+        }
+      },
+
+      /* 弹窗关闭 */
+      handleClose() {
+        this.formData = {
+          deviceName: '',
+          ipAddress: '',
+          port: '',
+          model: '',
+          account: '',
+          password: '',
+          doorCount: '',
+          stream: '',
+          enable: ''
+        };
+      }
+    }
+  };
+</script>

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

@@ -0,0 +1,330 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never" v-loading="loading" style="width: 100%">
+      <!-- 搜索表单 -->
+      <seekPage :seekList="seekList" :formLength="3" @search="reload"></seekPage>
+      <!-- 数据表格 -->
+      <ele-pro-table
+        ref="table"
+        :columns="columns"
+        :datasource="datasource"
+        height="calc(100vh - 375px)"
+        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>
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-plus"
+            class="ele-btn-icon"
+            @click="openEdit()"
+          >
+            新建
+          </el-button>
+          <!-- <el-popconfirm
+            title="确定要删除选中的数据吗?"
+            @confirm="remove(selection.map(v => v.id))"
+          >
+            <template v-slot:reference>
+              <el-button
+                size="small"
+                type="danger"
+                icon="el-icon-delete"
+                class="ele-btn-icon"
+                :disabled="selection?.length === 0"
+              >
+                批量删除
+              </el-button>
+            </template>
+          </el-popconfirm> -->
+        </template>
+        <!-- 启用禁用列 -->
+        <template v-slot:enable="{ row }">
+          <el-switch
+            :value="row.enable"
+            @change="(val) => handleEnableChange(row, val)"
+          />
+        </template>
+        <!-- 设备名称可点击 -->
+        <template v-slot:deviceName="{ row }">
+          <el-link type="primary" :underline="false" @click="openDetail(row)">
+            {{ row.deviceName }}
+          </el-link>
+        </template>
+        <!-- 操作 -->
+        <template v-slot:action="{ row }">
+          <!-- <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-view"
+            @click="openDetail(row)"
+          >
+            查看详情
+          </el-link> -->
+          <!-- <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-edit"
+            @click="openEdit(row)"
+          >
+            修改
+          </el-link> -->
+          <el-popconfirm
+            class="ele-action"
+            title="确定要删除此信息吗?"
+            @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-card>
+
+    <!-- 新增、修改弹窗 -->
+    <add-or-edit-dialog
+      :visible.sync="editVisible"
+      :data="currentRow"
+      @done="reload"
+    />
+
+    <!-- 查看详情弹窗 -->
+    <detail-dialog
+      :visible.sync="detailVisible"
+      :data="currentRow"
+    />
+  </div>
+</template>
+
+<script>
+  import seekPage from '@/BIZComponents/seekPage.vue';
+  import tabMixins from '@/mixins/tableColumnsMixin';
+  import { listDoorLedger, removeDoorLedger, enableDoorLedger } from '@/api/‌doorSecurity‌';
+  import addOrEditDialog from './components/addOrEditDialog.vue';
+  import detailDialog from './components/detailDialog.vue';
+
+  export default {
+    mixins: [tabMixins],
+    components: {
+      seekPage,
+      addOrEditDialog,
+      detailDialog
+    },
+    data() {
+      return {
+        loading: false,
+        editVisible: false,
+        detailVisible: false,
+        currentRow: null,
+        selection: [],
+        cacheKeyUrl: 'eos-doorLedger-list',
+        columnsVersion: 1
+      };
+    },
+    computed: {
+      columns() {
+        // 当columnsVersion变化时会重新计算,用作更新列配置
+        void this.columnsVersion;
+        return [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            width: 60,
+            label: '序号',
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
+          },
+          {
+            minWidth: 140,
+            prop: 'deviceName',
+            label: '设备名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            slot: 'deviceName'
+          },
+          {
+            minWidth: 140,
+            prop: 'ipAddress',
+            label: '设备IP地址',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 100,
+            prop: 'port',
+            label: '设备端口号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 120,
+            prop: 'model',
+            label: '设备型号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 120,
+            prop: 'account',
+            label: '账号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+        //   {
+        //     minWidth: 100,
+        //     prop: 'password',
+        //     label: '密码',
+        //     align: 'center',
+        //     showOverflowTooltip: true
+        //   },
+          {
+            minWidth: 80,
+            prop: 'doorCount',
+            label: '门数量',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 120,
+            prop: 'stream',
+            label: '流名称',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 100,
+            prop: 'enable',
+            label: '是否启用',
+            slot: 'enable',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (_row, _column, cellValue) => {
+              return cellValue == 0 ? '启用' : '禁用';
+            }
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 150,
+            align: 'center',
+            resizable: false,
+            slot: 'action',
+            fixed: 'right'
+          }
+        ];
+      },
+      seekList() {
+        return [
+          {
+            label: '设备名称:',
+            value: 'deviceName',
+            type: 'input',
+            placeholder: '请输入设备名称'
+          },
+        //   {
+        //     label: '设备IP地址:',
+        //     value: 'ipAddress',
+        //     type: 'input',
+        //     placeholder: '请输入设备IP地址'
+        //   },
+          {
+            label: '设备型号:',
+            value: 'model',
+            type: 'input',
+            placeholder: '请输入设备型号'
+          },
+        //   {
+        //     label: '启用禁用:',
+        //     value: 'enable',
+        //     type: 'select',
+        //     planList: [
+        //       { value: 'true', label: '启用' },
+        //       { value: 'false', label: '禁用' }
+        //     ],
+        //     placeholder: '请选择'
+        //   }
+        ];
+      }
+    },
+    methods: {
+      /* 表格数据源 */
+      datasource({ page, limit, where }) {
+        return listDoorLedger({
+          pageNum: page,
+          size: limit,
+          ...where
+        });
+      },
+
+      /* 刷新表格 */
+      reload(where = {}) {
+        this.$refs.table.reload({ page: 1, where });
+      },
+
+      /* 打开新增/修改弹窗 */
+      openEdit(row) {
+        console.log(row);
+        this.currentRow = row || null;
+        this.editVisible = true;
+      },
+
+      /* 打开查看详情弹窗 */
+      openDetail(row) {
+        this.currentRow = row || null;
+        this.detailVisible = true;
+      },
+
+      /* 启用/禁用切换 */
+      handleEnableChange(_row, val) {
+        // TODO: 替换为实际的启用/禁用接口
+        enableDoorLedger(_row.id, {enable: val})
+          .then(() => {
+            this.$message.success(val ? '已启用' : '已禁用');
+            this.reload();
+          })
+          .catch(() => {
+            this.$message.error('操作失败');
+          });
+      },
+
+      /* 删除 */
+      remove(id) {
+        if (!id) return;
+        const loading = this.$loading({ lock: true });
+        removeDoorLedger(id)
+          .then(() => {
+            loading.close();
+            this.$message.success('删除成功');
+            this.reload();
+          })
+          .catch(() => {
+            loading.close();
+          });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  :deep(.el-link--inner) {
+    margin-left: 0px !important;
+  }
+</style>

+ 151 - 0
src/views/‌doorSecurity‌/entryExitRecords/components/detailDialog.vue

@@ -0,0 +1,151 @@
+<template>
+  <el-dialog
+    title="查看详情"
+    :visible.sync="dialogVisible"
+    width="600px"
+    @close="handleClose"
+  >
+    <el-form
+      ref="detailForm"
+      :model="formData"
+      label-width="100px"
+      v-loading="detailLoading"
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="设备名称">
+            <el-input v-model="formData.deviceName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="门号">
+            <el-input v-model="formData.doorNo" disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="设备IP">
+            <el-input v-model="formData.ipAddress" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="是否正常">
+            <el-tag :type="formData.isAbnormal == 0 ? 'success' : 'danger'" size="medium">
+              {{ formData.isAbnormal == 0 ? '正常通行' : '异常事件' }}
+            </el-tag>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <el-form-item label="事件类型">
+            <el-input v-model="formData.eventType" disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-form-item label="事件描述">
+        <el-input
+          v-model="formData.eventDescription"
+          type="textarea"
+          :rows="3"
+          disabled
+        />
+      </el-form-item>
+      <el-form-item label="触发时间">
+        <el-input v-model="formData.eventTime" disabled />
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="dialogVisible = false">关 闭</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+  export default {
+    props: {
+      visible: {
+        type: Boolean,
+        default: false
+      },
+      // 行数据
+      data: {
+        type: Object,
+        default: null
+      }
+    },
+    data() {
+      return {
+        detailLoading: false,
+        formData: {
+          deviceName: '',
+          doorNo: '',
+          eventMajor: '',
+          eventMinor: '',
+          ipAddress: '',
+          personName: '',
+          isAbnormal: '',
+          eventType: '',
+          eventDescription: '',
+          eventTime: ''
+        }
+      };
+    },
+    computed: {
+      dialogVisible: {
+        get() {
+          return this.visible;
+        },
+        set(val) {
+          this.$emit('update:visible', val);
+        }
+      }
+    },
+    watch: {
+      visible(val) {
+        if (val) {
+          this.$nextTick(() => {
+            this.initForm();
+          });
+        }
+      }
+    },
+    methods: {
+      /* 初始化表单数据 */
+      initForm() {
+        const row = this.data;
+        if (row) {
+          this.formData = {
+            deviceName: row.deviceName || '',
+            doorNo: row.doorNo || '',
+            eventMajor: row.eventMajor || '',
+            eventMinor: row.eventMinor || '',
+            ipAddress: row.ipAddress || '',
+            personName: row.personName || '',
+            isAbnormal: row.isAbnormal ?? '',
+            eventType: row.eventType || '',
+            eventDescription: row.eventDescription || '',
+            eventTime: row.eventTime || ''
+          };
+        }
+      },
+
+      /* 弹窗关闭 */
+      handleClose() {
+        this.formData = {
+          deviceName: '',
+          doorNo: '',
+          eventMajor: '',
+          eventMinor: '',
+          ipAddress: '',
+          personName: '',
+          isAbnormal: '',
+          eventType: '',
+          eventDescription: '',
+          eventTime: ''
+        };
+      }
+    }
+  };
+</script>

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

@@ -0,0 +1,227 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never" v-loading="loading" style="width: 100%">
+      <!-- 搜索表单 -->
+      <seekPage :seekList="seekList" :formLength="3" @search="reload"></seekPage>
+      <!-- 数据表格 -->
+      <ele-pro-table
+        ref="table"
+        :columns="columns"
+        :datasource="datasource"
+        height="calc(100vh - 375px)"
+        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:deviceName="{ row }">
+            <el-link type="primary" :underline="false" @click="openDetail(row)">
+                {{ row.deviceName }}
+            </el-link>
+        </template>
+        <!-- 是否正常列 -->
+        <template v-slot:isAbnormal="{ row }">
+          <el-tag :type="row.isAbnormal == 0 ? 'success' : 'danger'" size="small">
+            {{ row.isAbnormal == 0 ? '正常通行' : '异常事件' }}
+          </el-tag>
+        </template>
+        <!-- 操作 -->
+        <template v-slot:action="{ row }">
+          <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-view"
+            @click="openDetail(row)"
+          >
+            查看详情
+          </el-link>
+        </template>
+      </ele-pro-table>
+    </el-card>
+
+    <!-- 查看详情弹窗 -->
+    <detail-dialog
+      :visible.sync="detailVisible"
+      :data="currentRow"
+    />
+  </div>
+</template>
+
+<script>
+  import seekPage from '@/BIZComponents/seekPage.vue';
+  import tabMixins from '@/mixins/tableColumnsMixin';
+  import { listEntryExitRecords } from '@/api/‌doorSecurity‌';
+  import detailDialog from './components/detailDialog.vue';
+
+  export default {
+    mixins: [tabMixins],
+    components: {
+      seekPage,
+      detailDialog
+    },
+    data() {
+      return {
+        loading: false,
+        detailVisible: false,
+        currentRow: null,
+        selection: [],
+        cacheKeyUrl: 'eos-entryExitRecords-list',
+        columnsVersion: 1
+      };
+    },
+    computed: {
+      columns() {
+        void this.columnsVersion;
+        return [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            width: 60,
+            label: '序号',
+            type: 'index',
+            columnKey: 'index',
+            align: 'center'
+          },
+          {
+            minWidth: 140,
+            prop: 'deviceName',
+            label: '设备名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            slot: 'deviceName'
+          },
+          {
+            minWidth: 100,
+            prop: 'doorNo',
+            label: '门号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 140,
+            prop: 'ipAddress',
+            label: '设备IP',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+        //   {
+        //     minWidth: 120,
+        //     prop: 'personName',
+        //     label: '人员姓名',
+        //     align: 'center',
+        //     showOverflowTooltip: true
+        //   },
+          {
+            minWidth: 110,
+            prop: 'isAbnormal',
+            label: '是否正常',
+            slot: 'isAbnormal',
+            align: 'center',
+            formatter: (_row, _column, cellValue) => {
+              return cellValue == 0 ? '正常通行' : '异常事件';
+            }
+          },
+          {
+            minWidth: 120,
+            prop: 'eventType',
+            label: '事件类型',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 120,
+            prop: 'eventDescription',
+            label: '事件描述',
+            align: 'center',
+            showOverflowTooltip: true
+          }, 
+          {
+            minWidth: 120,
+            prop: 'eventTime',
+            label: '触发时间',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+        //   {
+        //     columnKey: 'action',
+        //     label: '操作',
+        //     width: 120,
+        //     align: 'center',
+        //     resizable: false,
+        //     slot: 'action',
+        //     fixed: 'right'
+        //   }
+        ];
+      },
+      seekList() {
+        return [
+          {
+            label: '设备名称:',
+            value: 'deviceName',
+            type: 'input',
+            placeholder: '请输入设备名称'
+          },
+        //   {
+        //     label: '门号:',
+        //     value: 'doorNo',
+        //     type: 'input',
+        //     placeholder: '请输入门号'
+        //   },
+        //   {
+        //     label: '人员姓名:',
+        //     value: 'personName',
+        //     type: 'input',
+        //     placeholder: '请输入人员姓名'
+        //   },
+          {
+            label: '是否正常:',
+            value: 'isAbnormal',
+            type: 'select',
+            planList: [
+              { value: '0', label: '正常通行' },
+              { value: '1', label: '异常事件' }
+            ],
+            placeholder: '请选择'
+          },
+          {
+            label: '事件类型:',
+            value: 'eventType',
+            type: 'input',
+            placeholder: '请输入事件类型'
+          }
+        ];
+      }
+    },
+    methods: {
+      /* 表格数据源 */
+      async datasource({ page, limit, where }) {
+        const res = await listEntryExitRecords({
+          pageNum: page,
+          size: limit,
+          ...where
+        });
+
+        res.list = res.records || [];
+ 
+        return res
+      },
+
+      /* 刷新表格 */
+      reload(where = {}) {
+        this.$refs.table.reload({ page: 1, where });
+      },
+
+      /* 打开查看详情弹窗 */
+      openDetail(row) {
+        this.currentRow = row || null;
+        this.detailVisible = true;
+      }
+    }
+  };
+</script>

+ 178 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/aptitudeDialog.vue

@@ -0,0 +1,178 @@
+<template>
+  <div>
+    <ele-modal
+      width="960px"
+      :visible="visible"
+      append-to-body
+      :close-on-click-modal="false"
+      custom-class="ele-dialog-form"
+      title="选择工种"
+      @update:visible="updateVisible"
+      :maxable="true"
+    >
+      <div class="main">
+        <ele-pro-table
+          ref="table"
+          :initLoad="false"
+          :columns="columns"
+          :selection.sync="selection"
+          :datasource="datasource"
+          tool-class="ele-toolbar-form"
+        >
+        </ele-pro-table>
+      </div>
+      <template v-slot:footer>
+        <el-button @click="updateVisible(false)">取 消</el-button>
+        <el-button type="primary" @click="handleMine"> 确 定 </el-button>
+      </template>
+    </ele-modal>
+  </div>
+</template>
+
+<script>
+  import dictMixins from '@/mixins/dictMixins';
+  import { getProfessionPageList } from '@/api/factoryModel';
+  export default {
+    mixins: [dictMixins],
+    props: {
+      disabledIds: {
+        default: () => {
+          return [];
+        }
+      }
+    },
+    data() {
+      return {
+        selection: [],
+        visible: false,
+        levelOptions: [
+          {
+            label: '初级',
+            value: '1'
+          },
+          {
+            label: '中级',
+            value: '2'
+          },
+          {
+            label: '高级',
+            value: '3'
+          }
+        ],
+        isView: false,
+        // 表格列配置
+        columns: [
+          {
+            columnKey: 'selection',
+            type: 'selection',
+            width: 45,
+            align: 'center',
+            fixed: 'left',
+            selectable:(row)=>{
+              return !this.disabledIds.includes(row.id);
+            }
+          },
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            slot: 'type',
+            label: '类型',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110,
+            formatter: (_row) => {
+              return this.getDictValue('工种类型', _row.type);
+            }
+          },
+          {
+            align: 'center',
+            prop: 'code',
+            label: '编码',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            slot: 'name',
+            prop: 'name',
+            label: '名称',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          },
+          {
+            slot: 'level',
+            prop: 'level',
+            label: '等级',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110,
+            formatter: (_row) => {
+              return this.levelOptions.filter(
+                (item) => _row.level == item.value
+              )[0]?.label;
+            }
+          },
+          {
+            slot: 'hourCost',
+            prop: 'hourCost',
+            label: '标准工时费',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          },
+          {
+            slot: 'unit',
+            prop: 'unit',
+            label: '工时费单位',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          }
+        ]
+      };
+    },
+    created() {
+      this.requestDict('工种类型');
+    },
+    methods: {
+      updateVisible(value) {
+        this.visible = value;
+        this.$emit('update:visible', value);
+      },
+
+      async handleMine() {
+        if (this.selection?.length <= 0) {
+          this.$message.warning('请至少选择一条数据!');
+          return;
+        }
+        this.$emit('success', this.selection);
+        this.updateVisible(false);
+      },
+      async datasource({ page, limit, where, order }) {
+        const res = await getProfessionPageList({
+          ...where,
+          ...order,
+          pageNum: page,
+          size: limit
+        });
+        return res;
+      },
+      async open() {
+        this.current = {};
+        this.radio = null;
+        this.visible = true;
+        this.$nextTick(() => {
+          this.$refs.table.reload({
+            pageNum: 1,
+            size: 10,
+            where: {}
+          });
+        });
+      }
+    }
+  };
+</script>

+ 285 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/criticalProcess.vue

@@ -0,0 +1,285 @@
+<template>
+  <ele-modal
+    width="70vw"
+    :visible.sync="visible"
+    v-if="visible"
+    :close-on-click-modal="false"
+    append-to-body
+    custom-class="ele-dialog-form"
+    title="选择工序"
+    :maxable="true"
+  >
+    <el-form label-width="120px">
+      <el-row>
+        <el-col :span="6">
+          <el-form-item label="工序编码" prop="code">
+            <el-input v-model="searchData.code"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="6">
+          <el-form-item label="工序名称" prop="name">
+            <el-input v-model="searchData.name"></el-input>
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="6">
+          <el-form-item label="工作中心" prop="name">
+            <el-select
+              v-model="searchData.workCenterId"
+              placeholder="请选择"
+              filterable
+              clearable
+            >
+              <el-option
+                v-for="item in workCenterList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="6">
+          <div class="ele-form-actions">
+            <el-button type="primary" @click="search">搜索</el-button>
+            <el-button @click="reset">重置</el-button>
+          </div>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <ele-pro-table
+      :columns="columns"
+      :datasource="datasource"
+      ref="table"
+      height="45vh"
+      :initLoad="false"
+      row-key="id"
+      :selection.sync="selection"
+      highlight-current-row
+      :row-click-checked="true"
+      :row-click-checked-intelligent="false"
+      @update:selection="handleSelectionChange"
+    >
+      <template v-slot:type="{ row }">
+        {{ typeLabel(row.type) }}
+      </template>
+    </ele-pro-table>
+
+    <div slot="footer">
+      <el-button type="primary" @click="confirm">确定</el-button>
+      <el-button @click="cancel">返回</el-button>
+    </div>
+  </ele-modal>
+</template>
+
+<script>
+  import producetask from '@/api/‌doorSecurity‌/production';
+  import work from '@/api/‌doorSecurity‌/work';
+  import { userBandingOperation } from '@/api/system/organization';
+  export default {
+    props: {
+      disabledListId: {
+        type: Array,
+        default: () => []
+      }
+    },
+    data() {
+      return {
+        visible: false,
+        selection: [],
+        searchData: {
+          code: '',
+          name: '',
+          workCenterId: '',
+          type: 99
+        },
+        columns: [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center',
+            fixed: 'left',
+            reserveSelection: true
+          },
+          {
+            prop: 'code',
+            label: '工序编码',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          },
+          {
+            prop: 'name',
+            label: '工序名称',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          },
+          {
+            align: 'center',
+            prop: 'controlName',
+            label: '工序控制码',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'workCenterName',
+            label: '所属工作中心',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'type',
+            slot: 'type',
+            label: '工序类型',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          }
+        ],
+        workCenterList: [],
+        typeList: [
+          {
+            value: 99,
+            label: '关键工序'
+          },
+          {
+            value: 1,
+            label: '普通工序'
+          },
+          // {
+          //   value: 2,
+          //   label: '抽样质检'
+          // },
+
+          {
+            value: 3,
+            label: '抽样质检'
+          },
+          {
+            value: 4,
+            label: '包装工序'
+          },
+          {
+            value: 6,
+            label: '质检工序'
+          },
+          // {
+          //   value: 7,
+          //   label: '生产准备'
+          // }
+        ],
+        userIds: [],
+        type: '',
+        allSelection: []
+      };
+    },
+    methods: {
+      open(list, type) {
+        this.visible = true;
+        this.getListWorkCenter();
+        this.$nextTick(() => {
+          this.$refs.table.reload();
+        });
+        this.type = type;
+        if (this.type == 'batch') {
+          this.userIds = list.map((item) => {
+            return item.id;
+          });
+        } else {
+          this.allSelection = list || [];
+          console.log(this.allSelection);
+          this.$nextTick(() => {
+            this.allSelection.forEach((item) => {
+              this.$refs.table.toggleRowSelection(item, true);
+            });
+          });
+        }
+      },
+      /* 表格数据源 */
+      async datasource({ page, limit, where, order }) {
+        const res = await producetask.list({
+          ...where,
+          ...this.searchData,
+          pageNum: page,
+          size: limit
+        });
+        return res;
+      },
+      cancel() {
+        this.searchData = { type: 99 };
+        this.visible = false;
+      },
+
+      handleSelectionChange(data) {
+        this.allSelection = data;
+      },
+
+      confirm() {
+        if (this.allSelection.length == 0) {
+          return this.$message.warning('请选择工序');
+        }
+
+        if (this.type == 'batch') {
+          const taskIds = this.allSelection.map((item) => {
+            return item.id;
+          });
+
+          const loading = this.$loading({
+            lock: true,
+            text: 'Loading',
+            spinner: 'el-icon-loading',
+            background: 'rgba(0, 0, 0, 0.7)'
+          });
+
+          userBandingOperation({
+            userIds: this.userIds,
+            taskIds
+          })
+            .then(() => {
+              loading.close();
+              this.$message({
+                message: '绑定成功',
+                type: 'success'
+              });
+              this.$emit('chooseProcess');
+              this.cancel();
+            })
+            .catch(() => {
+              loading.close();
+            });
+        } else {
+          this.$emit('chooseProcess', this.allSelection);
+          this.cancel();
+        }
+      },
+
+      search() {
+        this.$refs.table.reload();
+      },
+      reset() {
+        this.searchData = {
+          type: 99
+        };
+        this.$refs.table.reload();
+      },
+
+      async getListWorkCenter() {
+        await work.list({ pageNum: 1, size: -1 }).then((res) => {
+          this.workCenterList = res.list;
+        });
+      },
+      typeLabel(type) {
+        return (
+          this.typeList.find((m) => m.value == type) &&
+          this.typeList.find((m) => m.value == type).label
+        );
+      }
+    }
+  };
+</script>

+ 6 - 5
src/views/‌doorSecurity‌/personnelAuthorization/components/door-bind.vue

@@ -70,6 +70,7 @@
                 type="primary"
                 :underline="false"
                 icon="el-icon-edit"
+                v-click-once
                 @click="bindUserDevice(row)"
               >
                 绑定
@@ -128,16 +129,16 @@
         selection: [],
         statusOptions: [
           { 
-            label: '待同步',
+            label: '在线',
             value: 0
 
           },
           {
-            label: '已同步',
+            label: '离线',
             value: 1
           },
           {
-            label: '失败',
+            label: '异常',
             value: 2
           }
         ],
@@ -235,7 +236,7 @@
             showOverflowTooltip: true,
             minWidth: 130,
             formatter: (row) => {
-              return row.status == 1 ? '在线' : '离线';
+              return this.statusOptions.find(item => item.value == row.status)?.label || '';
             }
           },
           {
@@ -294,7 +295,7 @@
             type: 'success'
           });
           row.isBind = true;
-          this.reload();
+          // this.reload();
           this.$emit('success');
         }).catch(err => {
           console.log(err, 'err');

+ 46 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/org-select.vue

@@ -0,0 +1,46 @@
+<!-- 机构选择下拉框 -->
+<template>
+  <ele-tree-select
+    ref="tree"
+    clearable
+    :value="value || ''"
+    :data="data"
+    label-key="name"
+    value-key="id"
+    default-expand-all
+    :placeholder="placeholder"
+    @input="updateValue"
+    :disabled="disabled"
+  />
+</template>
+
+<script>
+export default {
+  props: {
+    // 选中的数据(v-model)
+    value: [Number, String],
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    // 提示信息
+    placeholder: {
+      type: String,
+      default: '请选择机构'
+    },
+    // 机构数据
+    data: Array
+  },
+  methods: {
+    /* 更新选中数据 */
+    updateValue(value) {
+      this.$emit('input', value);
+
+      let nodesInfo = [];
+      nodesInfo = this.$refs['tree'].getHalfCheckedKeys();
+      nodesInfo.push(value);
+      this.$emit('checkedKeys', nodesInfo);
+    }
+  }
+};
+</script>

+ 2227 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/org-user-edit.vue

@@ -0,0 +1,2227 @@
+<!-- 用户编辑弹窗 -->
+<template>
+  <ele-modal
+    width="60%"
+    :visible="visible"
+    :close-on-click-modal="false"
+    custom-class="ele-dialog-form"
+    :title="isUpdate ? '基本信息' : '基本信息'"
+    @update:visible="updateVisible"
+    :maxable="true"
+  >
+    <el-form
+      ref="form"
+      :model="form"
+      class="el-form-box"
+      :rules="rules"
+      label-width="82px"
+      :disabled="disabled"
+    >
+      <el-row :gutter="15">
+        <el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
+          <el-form-item label="姓名:" prop="name">
+            <el-input
+              clearable
+              :maxlength="20"
+              v-model="form.name"
+              placeholder="请输入姓名"
+            />
+          </el-form-item>
+          <el-form-item label="所属工厂:">
+            <el-select
+              style="width: 100%"
+              clearable
+              v-model="form.factoryId"
+              filterable
+              :disabled="!!form.loginName"
+              placeholder="请选择所属工厂"
+            >
+              <el-option
+                v-for="item in factoryList"
+                :label="item.name"
+                :value="item.id"
+                :key="item.id"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="所属机构:" prop="groupId">
+            <org-select
+              :data="institutionList"
+              placeholder="请选择所属机构"
+              v-model="form.groupId"
+              :disabled="!!form.loginName"
+              @checkedKeys="checkedKeys"
+            />
+          </el-form-item>
+
+          <el-form-item label="隶属部门:">
+            <el-cascader
+              class="ele-block"
+              :options="organization"
+              placeholder="请选择隶属部门"
+              :props="defaultProps"
+              ref="deptRef"
+              :show-all-levels="true"
+              @change="handleChange"
+              :disabled="!!form.loginName"
+              v-model="form.deptIds"
+              clearable
+            ></el-cascader>
+          </el-form-item>
+
+          <el-form-item label="性别:" prop="sex">
+            <el-select
+              clearable
+              class="ele-block"
+              v-model="form.sex"
+              placeholder="请选择性别"
+            >
+              <el-option label="男" :value="1" />
+              <el-option label="女" :value="2" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="员工状态:" prop="status">
+            <el-select
+              clearable
+              class="ele-block"
+              v-model="form.status"
+              placeholder="请选择员工状态"
+            >
+              <el-option
+                v-for="item in statusOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="岗位:" prop="postId">
+            <!-- <el-input
+              clearable
+              :maxlength="100"
+              v-model="form.postName"
+              placeholder="请输入岗位"
+            /> -->
+            <DictSelection
+              dictName="岗位"
+              clearable
+              filterable
+              v-model="form.postId"
+              multiple
+            >
+            </DictSelection>
+          </el-form-item>
+          <el-form-item label="身份证号:" prop="idCard">
+            <el-input
+              clearable
+              :maxlength="18"
+              v-model="form.idCard"
+              placeholder="请输入身份证号"
+              @change="idCardChange"
+            />
+          </el-form-item>
+          <!-- <el-form-item label="工种:" prop="workTypeId"> -->
+          <!-- <DictSelection
+              dictName="工种类型"
+              clearable
+              filterable
+              v-model="form.workTypeId"
+            >
+            </DictSelection> -->
+          <!-- <el-select style="width: 100%" clearable v-model="form.workTypeId" filterable placeholder="请选择工种类型">
+              <el-option v-for="item in professionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+            </el-select>
+          </el-form-item> -->
+
+          <el-form-item label="籍贯:" prop="city">
+            <regions-select
+              style="width: 100%"
+              v-model="city"
+              placeholder="请选择省市区"
+            />
+          </el-form-item>
+          <el-form-item label="出生日期:" prop="age">
+            <el-date-picker
+              style="width: 100%"
+              clearable
+              v-model="form.birthday"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="请选择日期"
+            >
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="是否启用">
+            <el-switch
+              v-model="form.isEnabled"
+              :active-text="form.isEnabled == 1 ? '启用' : '停用'"
+              :active-value="1"
+              :inactive-value="0"
+            >
+            </el-switch>
+          </el-form-item>
+          <el-form-item
+            label="审批签名:"
+            prop="signature"
+            :rules="{
+              required: this.isCategory == 1,
+              message: '请上传审批签名',
+              trigger: ['blur', 'change']
+            }"
+          >
+            <WithView
+              :assetName="''"
+              v-model="form.signature"
+              style="max-height: 370px"
+            ></WithView>
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { sm: 12 } : { span: 12 }">
+          <el-form-item label="用户账号:">
+            <el-input
+              :disabled="true"
+              :maxlength="11"
+              v-model="form.loginName"
+            />
+          </el-form-item>
+          <el-form-item label="工号:" prop="jobNumber">
+            <el-input
+              clearable
+              type="text"
+              :maxlength="10"
+              v-model="form.jobNumber"
+              placeholder="请输入工号"
+              onkeyup="value=value.replace(/[^\x00-\xff]/g, '')"
+            />
+          </el-form-item>
+
+          <el-form-item label="手机号:" prop="phone">
+            <el-input
+              clearable
+              :maxlength="11"
+              v-model="form.phone"
+              placeholder="请输入手机号"
+            />
+          </el-form-item>
+          <el-form-item label="邮箱:" prop="email">
+            <el-input
+              clearable
+              :maxlength="100"
+              v-model="form.email"
+              placeholder="请输入邮箱"
+            />
+          </el-form-item>
+          <el-form-item label="年龄:" prop="age">
+            <el-input
+              type="number"
+              clearable
+              :maxlength="100"
+              v-model="form.age"
+              placeholder="请输入年龄"
+              onkeyup="value=value.replace(/[^\d.]/g,'')"
+            />
+          </el-form-item>
+
+          <el-form-item label="入职时间:" prop="joinDate">
+            <el-date-picker
+              style="width: 100%"
+              clearable
+              v-model="form.joinDate"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="请选择日期"
+            >
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="毕业院校:" prop="school">
+            <el-input
+              clearable
+              :maxlength="100"
+              v-model="form.school"
+              placeholder="请输入毕业院校"
+            />
+          </el-form-item>
+          <el-form-item label="微信号:" prop="wxId">
+            <el-input
+              clearable
+              :maxlength="100"
+              v-model="form.wxId"
+              placeholder="请输入微信号"
+            />
+          </el-form-item>
+          <el-form-item label="户籍地址:" prop="censusAddress">
+            <el-input
+              clearable
+              :maxlength="100"
+              v-model="form.censusAddress"
+              placeholder="户籍地址"
+            />
+          </el-form-item>
+
+          <!-- <el-form-item label="关键工序:" prop="censusAddress">
+            <el-input
+              clearable
+              :maxlength="100"
+              v-model="form.censusAddress"
+              placeholder="请选择关键工序"
+              @click.native="chooseOperation"
+              readonly
+            />
+          </el-form-item> -->
+          <el-form-item label="关键工序:" prop="operations">
+            <div class="multi-select-input" @click="chooseOperation">
+              <div class="tag-box">
+                <el-tag
+                  v-for="(item, index) in form.criticalTaskList"
+                  :key="item.taskId"
+                  closable
+                  @close="removeOperation(index)"
+                >
+                  {{ item.taskName }}
+                </el-tag>
+
+                <!-- 占位符 -->
+                <span v-if="!form.criticalTaskList.length" class="placeholder">
+                  请选择关键工序
+                </span>
+              </div>
+            </div>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-tabs v-model="activeName">
+        <el-tab-pane label="证照列表" name="identityPhotos">
+          <ele-pro-table
+            ref="table"
+            :columns="identityPhotosColumns"
+            :datasource="form.identityPhotos"
+            max-height="350px"
+            :toolkit="[]"
+            class="el-form-box"
+            :need-page="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button type="primary" @click="addIdentityPhotos"
+                >添加</el-button
+              >
+            </template>
+            <template v-slot:action="{ row, $index }">
+              <el-link
+                type="danger"
+                :underline="false"
+                icon="el-icon-delete"
+                @click="handleIdentityPhotosDel(row, $index)"
+                >删除
+              </el-link>
+            </template>
+            <template v-slot:categoryLevelId="{ row, $index }"> </template>
+            <template v-slot:type="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'identityPhotos.' + $index + '.type'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <DictSelection
+                  clearable
+                  v-model="row.type"
+                  dictName="证件类型"
+                ></DictSelection>
+              </el-form-item>
+            </template>
+            <template v-slot:code="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'identityPhotos.' + $index + '.code'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-input v-model="row.code" clearable></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:level="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'identityPhotos.' + $index + '.level'"
+              >
+                <el-select
+                  style="width: 100%"
+                  v-model="row.level"
+                  clearable
+                  filterable
+                >
+                  <el-option
+                    :label="item.label"
+                    :value="item.value"
+                    v-for="(item, index) in levelOptions"
+                    :key="index"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </template>
+            <template v-slot:validityStartTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'identityPhotos.' + $index + '.validityStartTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.validityStartTime"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:validityEndTime="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'identityPhotos.' + $index + '.validityEndTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.validityEndTime"
+                  value-format="yyyy-MM-dd"
+                  type="date"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:enactorTime="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'identityPhotos.' + $index + '.enactorTime'"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.enactorTime"
+                  value-format="yyyy-MM-dd"
+                  type="date"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:fileObj="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'identityPhotos.' + $index + '.fileObj'"
+              >
+                <fileUpload
+                  v-model="row.fileObj"
+                  module="main"
+                  :showLib="false"
+                  :limit="5"
+                />
+              </el-form-item>
+            </template>
+            <template v-slot:status="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'identityPhotos.' + $index + '.status'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <DictSelection
+                  clearable
+                  v-model="row.status"
+                  dictName="规则状态"
+                ></DictSelection>
+              </el-form-item>
+            </template>
+            <template v-slot:remark="{ row, $index }">
+              <el-form-item label-width="0px">
+                <el-input v-model="row.remark" type="textarea"></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:isRequired="{ column }">
+              <span class="is-required">{{ column.label }}</span>
+            </template>
+          </ele-pro-table>
+        </el-tab-pane>
+        <el-tab-pane label="技能列表" name="skills">
+          <ele-pro-table
+            ref="table"
+            :columns="skillsColumns"
+            :datasource="form.skills"
+            max-height="350px"
+            :toolkit="[]"
+            class="el-form-box"
+            :need-page="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button type="primary" @click="addSkills">添加</el-button>
+            </template>
+            <template v-slot:action="{ row, $index }">
+              <el-link
+                type="danger"
+                :underline="false"
+                icon="el-icon-delete"
+                @click="handleSkillsDel(row, $index)"
+                >删除
+              </el-link>
+            </template>
+            <template v-slot:categoryLevelId="{ row, $index }"> </template>
+            <template v-slot:name="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'skills.' + $index + '.name'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-input v-model="row.name" clearable></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:level="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'skills.' + $index + '.level'"
+              >
+                <el-select
+                  v-model="row.level"
+                  clearable
+                  filterable
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in []"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </template>
+            <template v-slot:years="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'skills.' + $index + '.years'"
+              >
+                <el-input v-model="row.years" clearable></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:fileAttach="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'skills.' + $index + '.fileAttach'"
+              >
+                <fileUpload
+                  v-model="row.fileAttach"
+                  module="main"
+                  :showLib="false"
+                  :limit="5"
+                />
+              </el-form-item>
+            </template>
+            <template v-slot:remark="{ row, $index }">
+              <el-form-item label-width="0px">
+                <el-input v-model="row.remark" type="textarea"></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:isRequired="{ column }">
+              <span class="is-required">{{ column.label }}</span>
+            </template>
+          </ele-pro-table>
+        </el-tab-pane>
+        <el-tab-pane label="奖惩记录" name="RPRecords">
+          <ele-pro-table
+            ref="table"
+            :columns="RPRecordsColumns"
+            :datasource="form.rewardsPunishments"
+            max-height="350px"
+            :toolkit="[]"
+            class="el-form-box"
+            :need-page="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button type="primary" @click="addRPRecords">添加</el-button>
+            </template>
+            <template v-slot:action="{ row, $index }">
+              <el-link
+                type="danger"
+                :underline="false"
+                icon="el-icon-delete"
+                @click="handleRPRecordsDel(row, $index)"
+                >删除
+              </el-link>
+            </template>
+            <template v-slot:type="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'rewardsPunishments.' + $index + '.type'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-select
+                  v-model="row.type"
+                  clearable
+                  filterable
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in RPRecordsType"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </template>
+            <template v-slot:desce="{ row, $index }">
+              <el-form-item label-width="0px">
+                <el-input
+                  v-model="row.desce"
+                  type="textarea"
+                  clearable
+                ></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:startTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'rewardsPunishments.' + $index + '.startTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.startTime"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:endTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'rewardsPunishments.' + $index + '.endTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.endTime"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:status="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'rewardsPunishments.' + $index + '.status'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-select
+                  v-model="row.status"
+                  clearable
+                  filterable
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in RPRecordsStatus"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </template>
+            <template v-slot:fileAttach="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'rewardsPunishments.' + $index + '.fileAttach'"
+              >
+                <fileUpload
+                  v-model="row.fileAttach"
+                  module="main"
+                  :showLib="false"
+                  :limit="5"
+                />
+              </el-form-item>
+            </template>
+            <template v-slot:remark="{ row, $index }">
+              <el-form-item label-width="0px">
+                <el-input v-model="row.remark" type="textarea"></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:isRequired="{ column }">
+              <span class="is-required">{{ column.label }}</span>
+            </template>
+          </ele-pro-table>
+        </el-tab-pane>
+        <el-tab-pane label="培训记录" name="training">
+          <ele-pro-table
+            ref="table"
+            :columns="trainingColumns"
+            :datasource="form.trainRecords"
+            max-height="350px"
+            :toolkit="[]"
+            class="el-form-box"
+            :need-page="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button type="primary" @click="addTraining">添加</el-button>
+            </template>
+            <template v-slot:action="{ row, $index }">
+              <el-link
+                type="danger"
+                :underline="false"
+                icon="el-icon-delete"
+                @click="handleTrainingDel(row, $index)"
+                >删除
+              </el-link>
+            </template>
+            <template v-slot:categoryLevelId="{ row, $index }"> </template>
+            <template v-slot:title="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'trainRecords.' + $index + '.title'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-input v-model="row.title" clearable></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:desce="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'trainRecords.' + $index + '.desce'"
+              >
+                <el-input
+                  v-model="row.desce"
+                  type="textarea"
+                  clearable
+                ></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:startTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'trainRecords.' + $index + '.startTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.startTime"
+                  type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:endTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'trainRecords.' + $index + '.endTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.endTime"
+                  type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:status="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'trainRecords.' + $index + '.status'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-select
+                  v-model="row.status"
+                  clearable
+                  filterable
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in trainingStatus"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </template>
+            <template v-slot:fileAttach="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'trainRecords.' + $index + '.fileAttach'"
+              >
+                <fileUpload
+                  v-model="row.fileAttach"
+                  module="main"
+                  :showLib="false"
+                  :limit="5"
+                />
+              </el-form-item>
+            </template>
+            <template v-slot:remark="{ row, $index }">
+              <el-form-item label-width="0px">
+                <el-input v-model="row.remark" type="textarea"></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:isRequired="{ column }">
+              <span class="is-required">{{ column.label }}</span>
+            </template>
+          </ele-pro-table>
+        </el-tab-pane>
+        <el-tab-pane label="考勤记录" name="attendance">
+          <ele-pro-table
+            ref="table"
+            :columns="attendanceColumns"
+            :datasource="form.attendanceRecords"
+            max-height="350px"
+            :toolkit="[]"
+            class="el-form-box"
+            :need-page="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button type="primary" @click="addAttendance">添加</el-button>
+            </template>
+            <template v-slot:action="{ row, $index }">
+              <el-link
+                type="danger"
+                :underline="false"
+                icon="el-icon-delete"
+                @click="handleAttendanceDel(row, $index)"
+                >删除
+              </el-link>
+            </template>
+            <template v-slot:type="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'attendanceRecords.' + $index + '.type'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-select
+                  v-model="row.type"
+                  clearable
+                  filterable
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in attendanceType"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </template>
+            <template v-slot:checkTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'attendanceRecords.' + $index + '.checkTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.checkTime"
+                  type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:belateTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'attendanceRecords.' + $index + '.belateTime'"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.belateTime"
+                  type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:leaveEarlyTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'attendanceRecords.' + $index + '.leaveEarlyTime'"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.leaveEarlyTime"
+                  type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+
+            <template v-slot:fileAttach="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'attendanceRecords.' + $index + '.fileAttach'"
+              >
+                <fileUpload
+                  v-model="row.fileAttach"
+                  module="main"
+                  :showLib="false"
+                  :limit="5"
+                />
+              </el-form-item>
+            </template>
+
+            <template v-slot:isRequired="{ column }">
+              <span class="is-required">{{ column.label }}</span>
+            </template>
+          </ele-pro-table>
+        </el-tab-pane>
+        <el-tab-pane label="劳动合同" name="contracts">
+          <ele-pro-table
+            ref="table"
+            :columns="contractsColumns"
+            :datasource="form.contracts"
+            max-height="350px"
+            :toolkit="[]"
+            class="el-form-box"
+            :need-page="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button type="primary" @click="addcontracts">添加</el-button>
+            </template>
+            <template v-slot:action="{ row, $index }">
+              <el-link
+                type="danger"
+                :underline="false"
+                icon="el-icon-delete"
+                @click="handleContractsDel(row, $index)"
+                >删除
+              </el-link>
+            </template>
+            <template v-slot:categoryLevelId="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'contracts.' + $index + '.categoryLevelId'"
+              >
+              </el-form-item>
+            </template>
+            <template v-slot:name="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'contracts.' + $index + '.name'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-input v-model="row.name" clearable></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:signTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'contracts.' + $index + '.signTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.signTime"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:startTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'contracts.' + $index + '.startTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.startTime"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:endTime="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'contracts.' + $index + '.endTime'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-date-picker
+                  style="width: 100%"
+                  v-model="row.endTime"
+                  type="date"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </template>
+            <template v-slot:status="{ row, $index }">
+              <el-form-item
+                label-width="0px"
+                :prop="'contracts.' + $index + '.status'"
+                :rules="{
+                  required: true,
+                  message: '',
+                  trigger: ['blur', 'change']
+                }"
+              >
+                <el-select
+                  v-model="row.status"
+                  clearable
+                  filterable
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in contractsStatus"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </template>
+            <template v-slot:fileAttach="{ row, $index }">
+              <el-form-item
+                label-width="0"
+                :prop="'contracts.' + $index + '.fileAttach'"
+              >
+                <fileUpload
+                  v-model="row.fileAttach"
+                  module="main"
+                  :showLib="false"
+                  :limit="5"
+                />
+              </el-form-item>
+            </template>
+            <template v-slot:remark="{ row, $index }">
+              <el-form-item label-width="0px">
+                <el-input v-model="row.remark" type="textarea"></el-input>
+              </el-form-item>
+            </template>
+            <template v-slot:isRequired="{ column }">
+              <span class="is-required">{{ column.label }}</span>
+            </template>
+          </ele-pro-table>
+        </el-tab-pane>
+        <el-tab-pane label="工种" name="jobManagement">
+          <ele-pro-table
+            ref="table"
+            :columns="jobColumns"
+            :datasource="form.professions"
+            max-height="350px"
+            :toolkit="[]"
+            class="el-form-box"
+            :need-page="false"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:toolbar>
+              <el-button type="primary" @click="$refs.aptitudeDialogRef.open()"
+                >添加</el-button
+              >
+            </template>
+            <template v-slot:action="{ row, $index }">
+              <el-link
+                type="danger"
+                :underline="false"
+                icon="el-icon-delete"
+                @click="deleteJob($index)"
+                >删除
+              </el-link>
+            </template>
+          </ele-pro-table>
+        </el-tab-pane>
+      </el-tabs>
+    </el-form>
+
+    <template v-slot:footer>
+      <el-button @click="updateVisible(false)">取消</el-button>
+      <el-button
+        type="primary"
+        :loading="loading"
+        @click="save"
+        v-if="!disabled"
+      >
+        保存
+      </el-button>
+    </template>
+    <aptitudeDialog
+      ref="aptitudeDialogRef"
+      @success="chooseAptitude"
+      :disabledIds="form.professions?.map((item) => item.id)"
+    ></aptitudeDialog>
+
+    <critical-process
+      ref="criticalProcessRef"
+      @chooseProcess="chooseProcess"
+    ></critical-process>
+  </ele-modal>
+</template>
+
+<script>
+  import { emailReg, phoneReg } from 'ele-admin';
+  import OrgSelect from './org-select.vue';
+  import RoleSelect from './role-select.vue';
+  import RegionsSelect from '@/components/RegionsSelect/index.vue';
+  import { getNotBoundAccount } from '@/api/system/user';
+  import {
+    getUserDetail,
+    saveOrUpdateUser,
+    checkExistence
+  } from '@/api/system/organization';
+  import { getFactoryarea, getProfessionPageList } from '@/api/factoryModel';
+  import WithView from '@/components/upload/WithView.vue';
+  import FileUpload from '@/components/upload/fileUpload.vue';
+  import dictMixins from '@/mixins/dictMixins';
+  import aptitudeDialog from './aptitudeDialog.vue';
+  import criticalProcess from './criticalProcess.vue';
+  import { parameterGetByCode } from '@/api/system/dictionary/index.js';
+
+  // D:\中赢\kd-aiot-frontend\src\views\system\user
+
+  export default {
+    mixins: [dictMixins],
+
+    components: {
+      OrgSelect,
+      RoleSelect,
+      RegionsSelect,
+      WithView,
+      FileUpload,
+      aptitudeDialog,
+      criticalProcess
+    },
+    props: {
+      // 弹窗是否打开
+      visible: Boolean,
+      // 修改回显的数据
+      data: Object,
+      // 全部机构
+      organizationList: Array,
+      //
+      institutionList: Array,
+      // 机构id
+      organizationId: [Number, String]
+    },
+    data() {
+      const defaultForm = {
+        id: null,
+        identityPhotos: [],
+        skills: [],
+        rewardsPunishments: [],
+        trainRecords: [],
+        attendanceRecords: [],
+        contracts: [],
+        deptIds: [],
+        deptName: '',
+        isEnabled: 1,
+        groupId: null,
+        groupName: null,
+        name: '',
+        sex: null,
+        email: '',
+        phone: '',
+        age: '',
+        accountId: '',
+        factoryId: '',
+        idCard: '',
+        workTypeId: '',
+        birthday: '',
+        signature: {},
+        postName: '',
+        professions: [],
+        censusAddress: '',
+        criticalTaskList: []
+      };
+      return {
+        defaultForm,
+        isCategory: '0', //是否启用个人电子签。0 不启用,1启用
+        // 表单数据
+        form: { ...defaultForm },
+        disabled: false,
+        activeName: 'identityPhotos',
+        // 表单验证规则
+        rules: {
+          groupId: [
+            { required: true, message: '请选择所属机构', trigger: 'blur' }
+          ],
+          name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+          sex: [{ required: true, message: '请选择性别', trigger: 'blur' }],
+
+          email: [
+            { pattern: emailReg, message: '邮箱格式不正确', trigger: 'blur' }
+          ],
+          phone: [
+            { required: true, message: '请输入手机号', trigger: 'blur' },
+            { pattern: phoneReg, message: '手机号格式不正确', trigger: 'blur' }
+          ],
+          jobNumber: [
+            {
+              required: true,
+              trigger: 'blur'
+            }
+          ],
+          status: [
+            { required: true, message: '请选择员工状态', trigger: 'blur' }
+          ]
+        },
+        // 提交状态
+        loading: false,
+        // 是否是修改
+        isUpdate: false,
+        city: '',
+        factoryList: [],
+        levelOptions: [
+          {
+            label: '初级',
+            value: '1'
+          },
+          {
+            label: '中级',
+            value: '2'
+          },
+          {
+            label: '高级',
+            value: '3'
+          }
+        ],
+        RPRecordsStatus: [
+          {
+            label: '未生效',
+            value: 0
+          },
+          {
+            label: '审核中',
+            value: 1
+          },
+          {
+            label: '生效中',
+            value: 2
+          },
+          {
+            label: '已过期',
+            value: 3
+          },
+          {
+            label: '无效',
+            value: 4
+          }
+        ],
+        RPRecordsType: [
+          {
+            label: '未分类',
+            value: 0
+          },
+          {
+            label: '奖励',
+            value: 1
+          },
+          {
+            label: '惩罚',
+            value: 2
+          }
+        ],
+        trainingStatus: [
+          {
+            label: '未开始',
+            value: 0
+          },
+          {
+            label: '进行中',
+            value: 1
+          },
+          {
+            label: '已完成',
+            value: 2
+          },
+          {
+            label: '取消',
+            value: 4
+          }
+        ],
+        contractsStatus: [
+          {
+            label: '未生效',
+            value: 0
+          },
+          {
+            label: '审核中',
+            value: 1
+          },
+          {
+            label: '生效中',
+            value: 2
+          },
+          {
+            label: '过期',
+            value: 3
+          },
+          {
+            label: '转续签',
+            value: 4
+          }
+        ],
+        attendanceType: [
+          {
+            label: '未分类',
+            value: 0
+          },
+          {
+            label: '上班打卡',
+            value: 1
+          },
+          {
+            label: '下班打卡',
+            value: 2
+          }
+        ],
+        statusOptions: [
+          { value: 1, label: '全职' },
+          { value: 2, label: '兼职' },
+          { value: 3, label: '实习' },
+          { value: 4, label: '正式' },
+          { value: 5, label: '试用' },
+          { value: 6, label: '离职' }
+        ],
+        accountList: [],
+        levelOptions: [
+          {
+            label: '初级',
+            value: '1'
+          },
+          {
+            label: '中级',
+            value: '2'
+          },
+          {
+            label: '高级',
+            value: '3'
+          }
+        ],
+        deptTree: [],
+        defaultProps: {
+          multiple: true,
+          checkStrictly: true,
+          emitPath: false,
+          children: 'children',
+          value: 'id',
+          label: 'name'
+        },
+
+        professionList: []
+      };
+    },
+    computed: {
+      // 是否开启响应式布局
+      styleResponsive() {
+        return this.$store.state.theme.styleResponsive;
+      },
+      organization() {
+        return this.setList(this.organizationList);
+      },
+      identityPhotosColumns() {
+        return [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '证照类型',
+            prop: 'type',
+            slot: 'type',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '证照编号',
+            prop: 'code',
+            slot: 'code',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '等级',
+            prop: 'level',
+            slot: 'level',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '有效期开始时间',
+            prop: 'validityStartTime',
+            slot: 'validityStartTime',
+            headerSlot: 'isRequired',
+            minWidth: 150,
+            align: 'center'
+          },
+          {
+            label: '有效期结束时间',
+            prop: 'validityEndTime',
+            slot: 'validityEndTime',
+            headerSlot: 'isRequired',
+            minWidth: 150,
+            align: 'center'
+          },
+          {
+            label: '颁布日期',
+            prop: 'enactorTime',
+            slot: 'enactorTime',
+            minWidth: 150,
+            align: 'center'
+          },
+          {
+            label: '证照附件',
+            prop: 'fileObj',
+            slot: 'fileObj',
+            minWidth: 200,
+            align: 'center'
+          },
+          {
+            label: '状态',
+            prop: 'status',
+            slot: 'status',
+            headerSlot: 'isRequired',
+            minWidth: 100,
+            align: 'center'
+          },
+          {
+            label: '备注',
+            prop: 'remark',
+            slot: 'remark',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            action: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center'
+          }
+        ];
+      },
+      skillsColumns() {
+        return [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '分类',
+            prop: 'categoryLevelId',
+            slot: 'categoryLevelId',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '技能名称',
+            prop: 'name',
+            slot: 'name',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '技能等级',
+            prop: 'level',
+            slot: 'level',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '技能经验(年限)',
+            prop: 'years',
+            slot: 'years',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '证照附件',
+            prop: 'fileAttach',
+            slot: 'fileAttach',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '备注',
+            prop: 'remark',
+            slot: 'remark',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            action: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center'
+          }
+        ];
+      },
+      RPRecordsColumns() {
+        return [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '奖惩类型',
+            prop: 'type',
+            slot: 'type',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '奖惩说明',
+            prop: 'desce',
+            slot: 'desce',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '开始时间',
+            prop: 'startTime',
+            slot: 'startTime',
+            headerSlot: 'isRequired',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '结束时间',
+            prop: 'endTime',
+            slot: 'endTime',
+            headerSlot: 'isRequired',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '证照附件',
+            prop: 'fileAttach',
+            slot: 'fileAttach',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '生效状态',
+            prop: 'status',
+            slot: 'status',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '备注',
+            prop: 'remark',
+            slot: 'remark',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            action: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center'
+          }
+        ];
+      },
+      trainingColumns() {
+        return [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '分类',
+            prop: 'categoryLevelId',
+            slot: 'categoryLevelId',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '培训标题',
+            prop: 'title',
+            slot: 'title',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '培训说明',
+            prop: 'desce',
+            slot: 'desce',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '开始时间',
+            prop: 'startTime',
+            slot: 'startTime',
+            headerSlot: 'isRequired',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '结束时间',
+            prop: 'endTime',
+            slot: 'endTime',
+            headerSlot: 'isRequired',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '附件',
+            prop: 'fileAttach',
+            slot: 'fileAttach',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '生效状态',
+            prop: 'status',
+            slot: 'status',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '备注',
+            prop: 'remark',
+            slot: 'remark',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            action: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center'
+          }
+        ];
+      },
+      attendanceColumns() {
+        return [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '考勤类型',
+            prop: 'type',
+            slot: 'type',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '签到时间',
+            prop: 'checkTime',
+            slot: 'checkTime',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          // {
+          //   label: '迟到时间偏差值',
+          //   prop: 'belateTime',
+          //   minWidth: 120,
+          //   align: "center"
+          // },
+          // {
+          //   label: '早退时间偏差值',
+          //   prop: 'leaveEarlyTime',
+          //   minWidth: 130,
+          //   align: "center"
+          // },
+          {
+            label: '附件',
+            prop: 'fileAttach',
+            slot: 'fileAttach',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            action: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center'
+          }
+        ];
+      },
+      contractsColumns() {
+        return [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '分类',
+            prop: 'categoryLevelId',
+            slot: 'categoryLevelId',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '合同名称',
+            prop: 'name',
+            slot: 'name',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '签订时间',
+            prop: 'signTime',
+            slot: 'startTime',
+            headerSlot: 'isRequired',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '开始时间',
+            prop: 'startTime',
+            slot: 'startTime',
+            headerSlot: 'isRequired',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '结束时间',
+            prop: 'endTime',
+            slot: 'endTime',
+            headerSlot: 'isRequired',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '合同附件',
+            prop: 'fileAttach',
+            slot: 'fileAttach',
+            minWidth: 130,
+            align: 'center'
+          },
+          {
+            label: '生效状态',
+            prop: 'status',
+            slot: 'status',
+            headerSlot: 'isRequired',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            label: '备注',
+            prop: 'remark',
+            slot: 'remark',
+            minWidth: 120,
+            align: 'center'
+          },
+          {
+            action: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center'
+          }
+        ];
+      },
+      jobColumns() {
+        return [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            slot: 'type',
+            label: '类型',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110,
+            formatter: (_row) => {
+              return this.getDictValue('工种类型', _row.type);
+            }
+          },
+          {
+            align: 'center',
+            prop: 'code',
+            label: '编码',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            slot: 'name',
+            prop: 'name',
+            label: '名称',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          },
+          {
+            slot: 'level',
+            prop: 'level',
+            label: '等级',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110,
+            formatter: (_row) => {
+              return this.levelOptions.filter(
+                (item) => _row.level == item.value
+              )[0].label;
+            }
+          },
+          {
+            slot: 'hourCost',
+            prop: 'hourCost',
+            label: '标准工时费',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          },
+          {
+            slot: 'unit',
+            prop: 'unit',
+            label: '工时费单位',
+            showOverflowTooltip: true,
+            align: 'center',
+            minWidth: 110
+          },
+
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 260,
+            align: 'center',
+            resizable: false,
+            slot: 'action',
+            showOverflowTooltip: true
+          }
+        ];
+      }
+    },
+    created() {
+      this.getFactoryList();
+      console.log(this.institutionList, '========');
+      this.getProfessionList();
+      parameterGetByCode({
+        code: 'main_is_personal_electronic_signature'
+      }).then((res) => {
+        this.isCategory = res.value;
+      });
+    },
+    methods: {
+      chooseAptitude(data) {
+        console.log(data);
+        this.form.professions.push(...data);
+      },
+      deleteJob(index) {
+        this.form.professions.splice(index, 1);
+      },
+
+      idCardChange() {
+        // 检查身份证号是否为18位
+        if (this.form.idCard.length === 18) {
+          // 提取出生日期部分(YYYYMMDD)并转换为YYYY-MM-DD格式
+          const birthDatePart = this.form.idCard.substr(6, 8); // 获取YYYYMMDD部分
+          const year = birthDatePart.substr(0, 4); // 年份
+          const month = birthDatePart.substr(4, 2); // 月份
+          const day = birthDatePart.substr(6, 2); // 日期
+          this.form.birthday = `${year}-${month}-${day}`; // 格式化日期并存储到data中
+          const birthDate = new Date(year, month - 1, day); // 月份是从0开始的,所以要减1
+          const now = new Date();
+          this.form.age = now.getFullYear() - birthDate.getFullYear();
+          const monthDifference = now.getMonth() - birthDate.getMonth();
+          if (
+            monthDifference < 0 ||
+            (monthDifference === 0 && now.getDate() < birthDate.getDate())
+          ) {
+            this.form.age--;
+          }
+        }
+      },
+      async getProfessionList() {
+        const res = await getProfessionPageList({
+          pageNum: 1,
+          size: 9999
+        });
+
+        this.professionList = res.list || [];
+      },
+      setList(list) {
+        return list.map((val) => {
+          val['disabled'] = val.id == this.form.groupId;
+          if (val.children) {
+            val.children = this.setList(val.children);
+          }
+          return val;
+        });
+      },
+      addIdentityPhotos() {
+        this.form.identityPhotos.push({
+          holder: this.form.name,
+          holderType: '1'
+        });
+      },
+      handleIdentityPhotosDel(row, index) {
+        this.form.identityPhotos.splice(index, 1);
+      },
+      addSkills() {
+        this.form.skills.push({});
+      },
+      handleSkillsDel(row, index) {
+        this.form.skills.splice(index, 1);
+      },
+      addRPRecords() {
+        this.form.rewardsPunishments.push({});
+      },
+      handleRPRecordsDel(row, index) {
+        this.form.rewardsPunishments.splice(index, 1);
+      },
+      addTraining() {
+        this.form.trainRecords.push({});
+      },
+      handleTrainingDel(row, index) {
+        this.form.trainRecords.splice(index, 1);
+      },
+      addAttendance() {
+        this.form.attendanceRecords.push({});
+      },
+      handleAttendanceDel(row, index) {
+        this.form.attendanceRecords.splice(index, 1);
+      },
+      addcontracts() {
+        this.form.contracts.push({});
+      },
+      handleContractsDel(row, index) {
+        this.form.contracts.splice(index, 1);
+      },
+      getAccountList() {
+        getNotBoundAccount().then((res) => {
+          this.accountList = res;
+        });
+      },
+      setDisabled(disabled) {
+        this.disabled = disabled;
+        this.getProfessionList();
+      },
+      async getFactoryList() {
+        const { list } = await getFactoryarea({
+          pageNum: 1,
+          size: 999,
+          type: 1
+        });
+        this.factoryList = list || [];
+      },
+
+      // chooseOperation() {
+      //   this.$refs.criticalProcessRef.open();
+      // },
+
+      chooseProcess(listData) {
+        this.form.criticalTaskList = listData.map((item) => ({
+          taskId: item.id,
+          taskName: item.name
+        }));
+      },
+
+      removeOperation(index) {
+        this.form.criticalTaskList.splice(index, 1);
+      },
+
+      chooseOperation() {
+        const list = this.form.criticalTaskList.map((item) => ({
+          id: item.taskId,
+          taskId: item.taskId,
+          taskName: item.taskName,
+          name: item.taskName
+        }));
+        this.$refs.criticalProcessRef.open(list, 'single');
+      },
+
+      /* 保存编辑 */
+      save() {
+        this.$refs.form.validate((valid, obj) => {
+          if (obj) {
+            let messages = Object.keys(obj).map((key) => obj[key][0]);
+            if (messages.length > 0) {
+              this.$message.warning(messages[0].message);
+            }
+          }
+          if (!valid) {
+            return false;
+          }
+          this.loading = true;
+          this.form.addressId = this.city
+            ? this.city[this.city.length - 1]
+            : '';
+
+          // if (this.deptTree.length > 0) {
+          //   this.deptTree.forEach(i => {
+          //     this.form.deptIds.push(i[i.length - 1])
+          //   })
+          //
+          //   this.form['deptTree'] = JSON.stringify(this.deptTree)
+          // }
+          let formData = JSON.parse(JSON.stringify(this.form));
+          if (formData.postId) {
+            formData.postName = formData.postId
+              .map((item) => this.getDictValue('岗位', item))
+              .toString();
+            formData.postId = formData.postId.toString();
+          }
+          if (formData.professions?.length) {
+            formData.professionId = formData.professions
+              .map((item) => item.id)
+              .toString();
+          }
+          const data = {
+            ...formData
+          };
+          if (!this.isUpdate) {
+            delete data.id;
+          }
+          if (!Array.isArray(data.signature)) {
+            data.signature = [data.signature].filter(
+              (item) => Boolean(item) && Object.keys(item).length !== 0
+            );
+          }
+          saveOrUpdateUser(data)
+            .then((msg) => {
+              this.loading = false;
+              if (this.isUpdate) {
+                this.$message.success('人员信息编辑成功');
+              } else {
+                this.$message.success('人员新增成功');
+              }
+              this.updateVisible(false);
+              this.$emit('done');
+            })
+            .catch((e) => {
+              this.loading = false;
+              // this.$message.error(e.message);
+            });
+        });
+      },
+      /* 更新visible */
+      updateVisible(value) {
+        this.$emit('update:visible', value);
+      },
+      handleChange() {
+        let arr = Array.from(this.$refs.deptRef.getCheckedNodes());
+        this.form.deptName = arr.map((i) => i.label).join('/') || '';
+        this.form.deptIds = this.form.deptIds || [];
+      },
+      checkedKeys(value) {
+        this.getLabelName(this.institutionList, (i) => {
+          if (i.id == this.form.groupId) {
+            return (this.form.groupName = i.name);
+          }
+        });
+        this.form.deptIds = this.form.deptIds.filter(
+          (item) => item != this.form.groupId
+        );
+        console.log(this.form.groupName);
+      },
+      getLabelName(data, callback) {
+        data.some((i) => {
+          callback(i);
+          if (i.children) {
+            this.getLabelName(i.children, callback);
+          }
+        });
+      }
+    },
+    watch: {
+      visible(visible) {
+        if (visible) {
+          this.getAccountList();
+          if (this.data) {
+            getUserDetail(this.data.id).then((res) => {
+              if (res.postId) {
+                res.postId = res.postId.split(',');
+              }
+              this.form = { ...res };
+              if (Array.isArray(this.form.signature)) {
+                this.form.signature = this.form.signature[0];
+              }
+
+              // this.deptTree = []
+              // this.form.deptIds = []
+              // if (this.form.deptTree) {
+              //   this.deptTree = JSON.parse(this.form.deptTree)
+              // }
+              // this.form.workTypeId = this.form.workTypeId + '';
+              // this.form.postName = this.form.postName + '';
+
+              this.city = res.addressId ? res.addressId.toString() : null;
+              this.isUpdate = true;
+            });
+            // this.$util.assignObject(this.form, {
+            //   ...this.data,
+            //   password: ''
+            // });
+            // this.form = {...this.data}
+            // this.form.address = ["130000","130300","130304"]
+            // this.form.address = "130304"
+            // console.log('this.form',this.form)
+          } else {
+            this.city = null;
+            this.form.groupId = this.organizationId;
+            this.isUpdate = false;
+          }
+        } else {
+          this.city = null;
+          this.$refs.form.clearValidate();
+          this.form = { ...this.defaultForm };
+        }
+      }
+    }
+  };
+</script>
+<style scoped lang="scss">
+  ::v-deep .el-tabs__header {
+    margin-bottom: 10px;
+  }
+
+  .multi-select-input {
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    padding: 3px 5px;
+    min-height: 36px;
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+    cursor: pointer;
+  }
+
+  .multi-select-input:hover {
+    border-color: #409eff;
+  }
+
+  .tag-box {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+  }
+
+  .placeholder {
+    color: #c0c4cc;
+    padding-left: 5px;
+  }
+</style>

+ 11 - 9
src/views/‌doorSecurity‌/personnelAuthorization/components/org-user-list.vue

@@ -18,7 +18,7 @@
     >
       <!-- 表头工具栏 -->
       <template v-slot:toolbar>
-        <el-button
+        <!-- <el-button
           size="small"
           type="primary"
           icon="el-icon-plus"
@@ -61,7 +61,7 @@
           plain
           @click="allPushBtn"
           >批量推送</el-button
-        >
+        > -->
       </template>
       <!-- 角色列 -->
       <template v-slot:roles="{ row }">
@@ -92,7 +92,7 @@
       </template> -->
       <!-- 操作列 -->
       <template v-slot:action="{ row }">
-        <el-link
+        <!-- <el-link
           type="primary"
           :underline="false"
           icon="el-icon-edit"
@@ -118,7 +118,7 @@
           @click="addUsers(row)"
         >
           新建账号
-        </el-link>
+        </el-link> -->
         <el-link
           type="primary"
           :underline="false"
@@ -127,7 +127,7 @@
         >
           门禁
         </el-link>
-        <el-popconfirm
+        <!-- <el-popconfirm
           class="ele-action"
           title="确定要删除此用户吗?"
           @confirm="remove(row)"
@@ -138,7 +138,7 @@
               删除
             </el-link>
           </template>
-        </el-popconfirm>
+        </el-popconfirm> -->
       </template>
     </ele-pro-table>
     <!-- 编辑弹窗 -->
@@ -197,13 +197,15 @@
   import dictMixins from '@/mixins/dictMixins';
   import { getFactoryarea } from '@/api/factoryModel';
   import DoorModal from './door-modal.vue';
+  import OrgUserEdit from './org-user-edit.vue';
 
   export default {
     mixins: [tabMixins, dictMixins],
     components: {
       importDialog,
       OrgUserSearch,
-      DoorModal
+      DoorModal,
+      OrgUserEdit
     },
     props: {
       // 机构id
@@ -360,8 +362,8 @@
           {
             columnKey: 'action',
             label: '操作',
-            width: 260,
-            align: 'left',
+            width: 120,
+            align: 'center',
             resizable: false,
             fixed: 'right',
             slot: 'action',

+ 80 - 0
src/views/‌doorSecurity‌/personnelAuthorization/components/role-select.vue

@@ -0,0 +1,80 @@
+<!-- 角色选择下拉框 -->
+<template>
+  <el-select
+    multiple
+    clearable
+    :value="value"
+    class="ele-block"
+    :placeholder="placeholder"
+    @input="updateValue"
+    filterable
+  >
+    <el-option
+      v-for="item in data"
+      :key="item.id"
+      :value="item.id"
+      :label="item.name"
+    />
+  </el-select>
+</template>
+
+<script>
+  import { getlistRole } from '@/api/system/role';
+
+  export default {
+    props: {
+      // 选中的数据(v-modal)
+      value: Array,
+      // 提示信息
+      placeholder: {
+        type: String,
+        default: '请选择角色'
+      }
+    },
+    data() {
+      return {
+        data: []
+      };
+    },
+    created() {
+      /* 获取角色数据 */
+      getlistRole()
+        .then((res) => {
+          this.data = res;
+
+          console.log(this.data, '返回的数据');
+        })
+        .catch((e) => {
+          // this.$message.error(e.message);
+        });
+    },
+    methods: {
+      // updateValue(value) {
+      //   // console.log(value, '值值');
+      //   // const data = this.data.find((item) => value.has(item.id));
+      //   // console.log(data);
+      //   // this.$emit('input', value);
+
+      //   const selectedSet = new Set(value);
+      //   const data = this.data.find((item) => selectedSet.has(item.id));
+      //   console.log(data);
+      //   this.$emit('input', data);
+      // }
+
+      updateValue(value) {
+        // const dataList = [];
+        // console.log(value);
+        // for (let it of value) {
+        //   const data = this.data.find((item) =>
+        //     item.id == it.id ? it.id : it
+        //   );
+        //   if (data) dataList.push(data);
+        // }
+
+        // console.log(dataList);
+
+        this.$emit('input', value);
+      }
+    }
+  };
+</script>

+ 2 - 2
src/views/‌doorSecurity‌/personnelAuthorization/index.vue

@@ -9,7 +9,7 @@
         <div>
           <!-- 操作按钮 -->
           <ele-toolbar class="ele-toolbar-actions">
-            <div style="margin: 5px 0">
+            <!-- <div style="margin: 5px 0">
               <el-button
                 size="small"
                 type="primary"
@@ -42,7 +42,7 @@
               >
                 删除
               </el-button>
-            </div>
+            </div> -->
           </ele-toolbar>
           <div class="ele-border-lighter sys-organization-list">
             <el-tree