| | |
| | | <template> |
| | | <div> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? '新增入职' : '编辑人员'" |
| | | width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | <FormDialog |
| | | v-model="dialogFormVisible" |
| | | :operation-type="operationType" |
| | | :title="dialogTitle" |
| | | width="90%" |
| | | @close="closeDia" |
| | | @confirm="submitForm" |
| | | @cancel="closeDia" |
| | | > |
| | | <div class="form-dia-body"> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="员工编号:" |
| | | prop="staffNo"> |
| | | <el-input v-model="form.staffNo" |
| | | placeholder="请输入" |
| | | clearable |
| | | :disabled="operationType !== 'add'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="姓名:" |
| | | prop="staffName"> |
| | | <el-input v-model="form.staffName" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="性别:" |
| | | prop="sex"> |
| | | <el-select v-model="form.sex"> |
| | | <el-option label="男" |
| | | value="男" /> |
| | | <el-option label="女" |
| | | value="女" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="户籍住址:" |
| | | prop="nativePlace"> |
| | | <el-input v-model="form.nativePlace" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="岗位:" |
| | | prop="sysPostId"> |
| | | <el-select v-model="form.sysPostId" |
| | | placeholder="请选择岗位" |
| | | clearable> |
| | | <el-option v-for="item in postOptions" |
| | | :key="item.postId" |
| | | :label="item.postName" |
| | | :value="item.postId" |
| | | :disabled="item.status === '1'" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="现住址:" |
| | | prop="adress"> |
| | | <el-input v-model="form.adress" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="部门:" |
| | | prop="sysDeptId"> |
| | | <el-tree-select v-model="form.sysDeptId" |
| | | :data="deptOptions" |
| | | :props="{ value: 'id', label: 'label', children: 'children' }" |
| | | value-key="id" |
| | | placeholder="请选择部门" |
| | | check-strictly /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="年龄:" |
| | | prop="age"> |
| | | <el-input-number v-model="form.age" |
| | | :precision="0" |
| | | :step="1" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="第一学历:" |
| | | prop="firstStudy"> |
| | | <el-input v-model="form.firstStudy" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="专业:" |
| | | prop="profession"> |
| | | <el-input v-model="form.profession" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系电话:" |
| | | prop="phone"> |
| | | <el-input v-model="form.phone" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="紧急联系人:" |
| | | prop="emergencyContact"> |
| | | <el-input v-model="form.emergencyContact" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="紧急联系人联系电话:" |
| | | prop="emergencyContactPhone"> |
| | | <el-input v-model="form.emergencyContactPhone" |
| | | placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="合同年限:" |
| | | prop="contractTerm"> |
| | | <el-input-number v-model="form.contractTerm" |
| | | :precision="0" |
| | | :step="1" |
| | | style="width: 100%" |
| | | :disabled="true" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="合同开始日期:" |
| | | prop="contractStartTime"> |
| | | <el-date-picker v-model="form.contractStartTime" |
| | | type="date" |
| | | placeholder="请选择日期" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="合同结束日期:" |
| | | prop="contractEndTime"> |
| | | <el-date-picker v-model="form.contractEndTime" |
| | | type="date" |
| | | placeholder="请选择日期" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | label-position="top" |
| | | > |
| | | <BasicInfoSection :form="form" :operation-type="operationType" /> |
| | | <JobInfoSection |
| | | :form="form" |
| | | :post-options="postOptions" |
| | | :dept-options="deptOptions" |
| | | /> |
| | | <EducationWorkSection :form="form" /> |
| | | <EmergencyAndAttachmentSection :form="form" /> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">取消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from "vue"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { findPostOptions } from "@/api/system/post.js"; |
| | | import { listDept } from "@/api/system/dept.js"; |
| | | import { deptTreeSelect } from "@/api/system/user.js"; |
| | | import { |
| | | staffOnJobInfo, |
| | | createStaffOnJob, |
| | | updateStaffOnJob, |
| | | } from "@/api/personnelManagement/staffOnJob.js"; |
| | | import { deptTreeSelect } from "@/api/system/user.js"; |
| | | |
| | | import BasicInfoSection from "./BasicInfoSection.vue"; |
| | | import JobInfoSection from "./JobInfoSection.vue"; |
| | | import EducationWorkSection from "./EducationWorkSection.vue"; |
| | | import EmergencyAndAttachmentSection from "./EmergencyAndAttachmentSection.vue"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(["close"]); |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref(""); |
| | | const operationType = ref("add"); |
| | | const id = ref(0); |
| | | const data = reactive({ |
| | | form: { |
| | | const formRef = ref(null); |
| | | |
| | | const dialogTitle = () => |
| | | operationType.value === "add" ? "新增入职" : "编辑人员"; |
| | | |
| | | const createEmptyEducation = () => ({ |
| | | degree: "", |
| | | school: "", |
| | | admissionDate: "", |
| | | graduationDate: "", |
| | | major: "", |
| | | academicDegree: "", |
| | | }); |
| | | |
| | | const createEmptyWork = () => ({ |
| | | company: "", |
| | | department: "", |
| | | position: "", |
| | | startDate: "", |
| | | endDate: "", |
| | | description: "", |
| | | }); |
| | | |
| | | const createEmptyEmergency = () => ({ |
| | | name: "", |
| | | relation: "", |
| | | phone: "", |
| | | address: "", |
| | | }); |
| | | |
| | | const createDefaultForm = () => ({ |
| | | id: undefined, |
| | | // 基本信息 |
| | | staffNo: "", |
| | | staffName: "", |
| | | sex: "", |
| | | nativePlace: "", |
| | | postJob: "", |
| | | adress: "", |
| | | firstStudy: "", |
| | | profession: "", |
| | | age: 0, |
| | | aliasName: "", |
| | | phone: "", |
| | | sex: "", |
| | | birthDate: "", |
| | | age: undefined, |
| | | nativePlace: "", |
| | | nation: "", |
| | | maritalStatus: "", |
| | | politicalStatus: "", |
| | | firstWorkDate: "", |
| | | workingYears: undefined, |
| | | idCardNo: "", |
| | | hukouType: "", |
| | | email: "", |
| | | currentAddress: "", |
| | | // 在职信息 |
| | | jobNo: "", |
| | | staffType: "", |
| | | entryDate: "", |
| | | probationPeriod: undefined, |
| | | regularDate: "", |
| | | sysDeptId: undefined, |
| | | directLeader: "", |
| | | sysPostId: undefined, |
| | | jobLevel: "", |
| | | basicSalary: undefined, |
| | | // 银行卡信息 |
| | | bankName: "", |
| | | bankCardNo: "", |
| | | // 教育经历 |
| | | educationList: [createEmptyEducation()], |
| | | // 工作经历 |
| | | workExperienceList: [createEmptyWork()], |
| | | // 紧急联系人 |
| | | emergencyContacts: [createEmptyEmergency()], |
| | | emergencyContact: "", |
| | | emergencyContactPhone: "", |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | sysPostId: undefined, |
| | | sysDeptId: undefined, |
| | | }, |
| | | rules: { |
| | | staffNo: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | staffName: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | sex: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | nativePlace: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | postJob: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | adress: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | firstStudy: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | profession: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | age: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | phone: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | emergencyContact: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | emergencyContactPhone: [ |
| | | { required: true, message: "请输入", trigger: "blur" }, |
| | | ], |
| | | contractTerm: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | contractStartTime: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | contractEndTime: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | sysDeptId: [{ required: true, message: "请选择", trigger: "change" }], |
| | | }, |
| | | postOptions: [], // 岗位选项 |
| | | deptOptions: [], // 部门选项 |
| | | // 材料附件(仅前端展示) |
| | | attachments: [], |
| | | }); |
| | | const { form, rules, postOptions, deptOptions } = toRefs(data); |
| | | |
| | | // 打开弹框 |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === "edit") { |
| | | id.value = row.id; |
| | | staffOnJobInfo(id.value, {}).then(res => { |
| | | form.value = { ...res.data }; |
| | | if (form.value.sysPostId === 0) { |
| | | form.value.sysPostId = undefined; |
| | | } |
| | | if (form.value.sysDeptId === 0) { |
| | | form.value.sysDeptId = undefined; |
| | | } |
| | | // 编辑时也计算一次合同年限 |
| | | calculateContractTerm(); |
| | | const state = reactive({ |
| | | form: createDefaultForm(), |
| | | rules: { |
| | | staffNo: [{ required: true, message: "请输入员工编号", trigger: "blur" }], |
| | | staffName: [{ required: true, message: "请输入姓名", trigger: "blur" }], |
| | | phone: [{ required: true, message: "请输入手机", trigger: "blur" }], |
| | | sex: [{ required: true, message: "请选择性别", trigger: "change" }], |
| | | birthDate: [ |
| | | { required: true, message: "请选择出生日期", trigger: "change" }, |
| | | ], |
| | | jobNo: [{ required: true, message: "请输入工号", trigger: "blur" }], |
| | | staffType: [ |
| | | { required: true, message: "请选择员工类型", trigger: "change" }, |
| | | ], |
| | | entryDate: [ |
| | | { required: true, message: "请选择入职日期", trigger: "change" }, |
| | | ], |
| | | sysDeptId: [ |
| | | { required: true, message: "请选择部门", trigger: "change" }, |
| | | ], |
| | | }, |
| | | postOptions: [], |
| | | deptOptions: [], |
| | | }); |
| | | } else { |
| | | form.value.id = ""; |
| | | } |
| | | |
| | | const { form, rules, postOptions, deptOptions } = toRefs(state); |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form.value, createDefaultForm()); |
| | | nextTick(() => { |
| | | formRef.value?.clearValidate(); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | fetchPostOptions(); |
| | | fetchDeptOptions(); |
| | | }); |
| | | |
| | | const fetchPostOptions = () => { |
| | | findPostOptions().then(res => { |
| | | postOptions.value = res.data; |
| | | findPostOptions().then((res) => { |
| | | postOptions.value = res.data || []; |
| | | }); |
| | | }; |
| | | |
| | | // 查询部门列表 |
| | | const fetchDeptOptions = () => { |
| | | deptTreeSelect().then(response => { |
| | | deptTreeSelect().then((response) => { |
| | | deptOptions.value = filterDisabledDept( |
| | | JSON.parse(JSON.stringify(response.data)) |
| | | JSON.parse(JSON.stringify(response.data || [])) |
| | | ); |
| | | }); |
| | | }; |
| | | |
| | | /** 过滤禁用的部门 */ |
| | | function filterDisabledDept(deptList) { |
| | | return deptList.filter(dept => { |
| | | return deptList.filter((dept) => { |
| | | if (dept.disabled) { |
| | | return false; |
| | | } |
| | |
| | | }); |
| | | } |
| | | |
| | | // 提交产品表单 |
| | | const syncEmergencyToLegacyField = () => { |
| | | const first = form.value.emergencyContacts?.[0]; |
| | | form.value.emergencyContact = first?.name || ""; |
| | | form.value.emergencyContactPhone = first?.phone || ""; |
| | | }; |
| | | |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | fetchPostOptions(); |
| | | fetchDeptOptions(); |
| | | resetForm(); |
| | | if (type === "edit" && row?.id) { |
| | | id.value = row.id; |
| | | staffOnJobInfo(id.value, {}).then((res) => { |
| | | const d = res.data || {}; |
| | | Object.assign(form.value, { |
| | | ...form.value, |
| | | ...d, |
| | | }); |
| | | if (!Array.isArray(form.value.educationList) || !form.value.educationList.length) { |
| | | form.value.educationList = [createEmptyEducation()]; |
| | | } |
| | | if ( |
| | | !Array.isArray(form.value.workExperienceList) || |
| | | !form.value.workExperienceList.length |
| | | ) { |
| | | form.value.workExperienceList = [createEmptyWork()]; |
| | | } |
| | | if ( |
| | | !Array.isArray(form.value.emergencyContacts) || |
| | | !form.value.emergencyContacts.length |
| | | ) { |
| | | form.value.emergencyContacts = [createEmptyEmergency()]; |
| | | } |
| | | if (form.value.sysPostId === 0) { |
| | | form.value.sysPostId = undefined; |
| | | } |
| | | if (form.value.sysDeptId === 0) { |
| | | form.value.sysDeptId = undefined; |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | fetchPostOptions(); |
| | | fetchDeptOptions(); |
| | | }); |
| | | |
| | | const submitForm = () => { |
| | | if (!form.value.sysPostId) { |
| | | form.value.sysPostId = undefined; |
| | |
| | | if (!form.value.sysDeptId) { |
| | | form.value.sysDeptId = undefined; |
| | | } |
| | | proxy.$refs.formRef.validate(valid => { |
| | | syncEmergencyToLegacyField(); |
| | | formRef.value?.validate((valid) => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | createStaffOnJob(form.value).then(res => { |
| | | createStaffOnJob(form.value).then(() => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | }); |
| | | } else { |
| | | updateStaffOnJob(id.value, form.value).then(res => { |
| | | updateStaffOnJob(id.value, form.value).then(() => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | | }); |
| | |
| | | } |
| | | }); |
| | | }; |
| | | // 计算合同年限 |
| | | const calculateContractTerm = () => { |
| | | if (form.value.contractStartTime && form.value.contractEndTime) { |
| | | const startDate = new Date(form.value.contractStartTime); |
| | | const endDate = new Date(form.value.contractEndTime); |
| | | |
| | | if (endDate > startDate) { |
| | | // 计算年份差 |
| | | const yearDiff = endDate.getFullYear() - startDate.getFullYear(); |
| | | const monthDiff = endDate.getMonth() - startDate.getMonth(); |
| | | const dayDiff = endDate.getDate() - startDate.getDate(); |
| | | |
| | | let years = yearDiff; |
| | | |
| | | // 如果结束日期的月日小于开始日期的月日,则减去1年 |
| | | if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { |
| | | years = yearDiff - 1; |
| | | } |
| | | |
| | | form.value.contractTerm = Math.max(0, years); |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | }; |
| | | |
| | | // 关闭弹框 |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | formRef.value?.resetFields(); |
| | | dialogFormVisible.value = false; |
| | | emit("close"); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .form-dia-body { |
| | | padding: 0; |
| | | } |
| | | |
| | | .card-title-line { |
| | | color: #f56c6c; |
| | | margin-right: 4px; |
| | | } |
| | | |
| | | .form-card { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | </style> |