<!-- Description: 人员管理页面 Author: 李亚光 Date: 2023-04-23 --> <script lang="ts" setup name="personEdit"> import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' import { ElMessage, ElMessageBox, ElTable } from 'element-plus' import { Plus } from '@element-plus/icons-vue' import photograph from './photograph.vue' import { getDeptTreeList } from '@/api/system/dept' import { toTreeList } from '@/utils/structure' import { getDictByCode } from '@/api/system/dict' import { addPerson, updatePerson, uploadApi } from '@/api/person' const $route = useRoute() const $router = useRouter() const ruleFormRef = ref<FormInstance>() // from组件 const ruleForm: { [key: string]: string | any } = ref({ workerName: '', // 姓名 gender: '', deptId: '', // 所属部门 phoneNumber: '', // 联系方式 workerAvatar: '', // 照片 idCardNumber: '', // 身份证号 workerType: '1', }) // 表单 // 图片地址 const photoUrl = computed(() => { return `${import.meta.env.VITE_APP_API_BASEURL}/static/${ruleForm.value.workerAvatar}` }) const photographRef = ref() // 身份证号码验证规则 const validateIDcard = (rule: any, value: any, callback: any) => { const rr = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[X])$)$/ if (rr.test(value)) { callback() } else { callback(new Error('验证失败')) } } const rules = ref({ workerName: [{ required: true, message: '姓名不能为空', trigger: 'blur' }], gender: [{ required: true, message: '性别不能为空', trigger: 'blur' }], deptId: [{ required: true, message: '所属部门不能为空', trigger: 'blur' }], phoneNumber: [{ required: true, message: '联系方式不能为空', trigger: 'blur' }], idCardNumber: [{ required: true, message: '身份证号码不符合规范', trigger: 'blur', validator: validateIDcard }], }) // 表单验证规则 // 图片上传请求 const uploadQuarterlyEvaluateFile: any = (file: any) => { const fd = new FormData() fd.append('file', file.file) uploadApi(fd).then((res) => { if (res.code === 200) { console.log(res.data, '123') ElMessage.success('上传成功') ruleForm.value.workerAvatar = res.data } }) } // 图片上传之前的验证 const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => { if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png' && rawFile.type !== 'image/jpg') { ElMessage.error('只能上传png/jpeg/jpg格式的图片') return false } else if (rawFile.size / 1024 / 1024 > 2) { ElMessage.error('图片不能大于2MB') return false } return true } // 拍照功能 const tackPhoto = ref(false) const register = () => { photographRef.value.initDialog() tackPhoto.value = true } // 关闭摄像头 const offPthot = (url: string) => { if (url) { ruleForm.value.workerAvatar = url } tackPhoto.value = false } // 提交 const submitForm = async (formEl: FormInstance | undefined) => { if (!formEl) { return } // 当前选中的证书基本信息列表 await formEl.validate((valid, fields) => { if (valid) { ElMessageBox.confirm( '确认提交吗?', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }, ).then(() => { // 更新或者新增 ($route.query.type === 'add' ? addPerson(ruleForm.value) : updatePerson(ruleForm.value)).then((res) => { if (res.code === 200) { ElMessage.success('操作成功') $router.go(-1) } }) }) } }) } // 取消 const resetForm = () => { $router.go(-1) } const deptTreeList = ref([]) // 加载组织机构树形下拉 const fetchDeptTree = () => { getDeptTreeList().then((res) => { if (res.data) { // 将列表转树结构 deptTreeList.value = toTreeList(res.data, '0', true) } }) } fetchDeptTree() const sexList = ref<{ id: string; value: string; name: string }[]>() // 获取性别 const getSexList = () => { getDictByCode('sysSex').then((response) => { sexList.value = response.data }) } getSexList() const title = ref('') onMounted(() => { const type = $route.query.type if (type === 'update') { title.value = '人员编辑' const row = JSON.parse($route.query.row as string) ruleForm.value = row } else { title.value = '人员新增' } }) </script> <template> <app-container> <!-- 拍照组件 --> <photograph ref="photographRef" :tack-photo="tackPhoto" @off="offPthot" /> <detail-page :title="title"> <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-position="right" label-width="110px" border stripe> <el-row :gutter="24"> <el-col :span="6"> <el-form-item> <el-upload class="avatar-uploader" :show-file-list="false" :http-request="uploadQuarterlyEvaluateFile" :before-upload="beforeAvatarUpload" accept="image/png, image/jpeg,image/jpg"> <img v-if="ruleForm.workerAvatar" :src="photoUrl" class="avatar"> <el-icon v-else class="avatar-uploader-icon"> <plus /> </el-icon> </el-upload> <el-button type="primary" style="margin-top: 20px; display: block; width: 190px;" @click="register">人脸注册</el-button> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="姓名" prop="workerName" style="margin-top: 40px;"> <el-input v-model.trim="ruleForm.workerName" placeholder="姓名"> </el-input> </el-form-item> <el-form-item label="所属部门" prop="deptId" class="marg-item" style="margin-top: 40px;"> <dept-select v-model="ruleForm.deptId" :data="deptTreeList" placeholder="所属部门" style="width: 100%;" /> </el-form-item> <el-form-item label="职务" prop="name" style="margin-top: 40px;"> <el-input v-model.trim="ruleForm.name" placeholder="职务" :disabled="title === '详情'"> </el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="性别" prop="gender" class="marg-item" style="margin-top: 40px;"> <el-select v-model="ruleForm.gender" placeholder="请选择性别" :disabled="title === '详情'" style="width: 100%;"> <el-option v-for="item in sexList" :key="item.id" :label="item.name" :value="item.value" /> </el-select> </el-form-item> <el-form-item label="联系方式" prop="phoneNumber" style="margin-top: 40px;"> <el-input v-model.trim="ruleForm.phoneNumber" placeholder="联系方式" :disabled="title === '详情'"> </el-input> </el-form-item> <el-form-item label="证件号码" prop="idCardNumber" style="margin-top: 40px;"> <el-input v-model.trim="ruleForm.idCardNumber" placeholder="证件号码" :disabled="title === '详情'"> </el-input> </el-form-item> </el-col> </el-row> </el-form> <div class="dialog-footer"> <el-button style="margin-left: 30px;" @click="resetForm"> 取消 </el-button> <el-button type="primary" @click="submitForm(ruleFormRef)"> 保存 </el-button> </div> </detail-page> </app-container> </template> <style lang="scss" scoped> .dialog-footer { display: flex; justify-items: end; flex-direction: row-reverse; } :deep(.el-radio__label) { display: none; } :deep(.el-icon.avatar-uploader-icon) { font-size: 28px; color: #8c939d; width: 190px; height: 250px; text-align: center; } :deep(.avatar-uploader .avatar) { width: 190px; height: 250px; display: block; } .isDetail { ::v-deep { .el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label::before, .el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label::before { display: none; } } } </style> <style scoped> .avatar-uploader .avatar { width: 190px; height: 250px; display: block; } </style> <style> .avatar-uploader .el-upload { border: 1px dashed var(--el-border-color); border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; transition: var(--el-transition-duration-fast); } .avatar-uploader .el-upload:hover { border-color: var(--el-color-primary); } .el-icon.avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 190px; height: 250px; text-align: center; } </style>