319 lines
10 KiB
Vue
319 lines
10 KiB
Vue
<template>
|
||
<el-dialog
|
||
v-model="visible"
|
||
:title="isEdit ? '编辑档案' : '新建档案'"
|
||
width="680px"
|
||
:close-on-click-modal="false"
|
||
@closed="resetForm"
|
||
>
|
||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||
<el-form-item label="关联员工" prop="employee_id">
|
||
<!-- 编辑时员工归属不可变更,只读展示 -->
|
||
<el-input v-if="isEdit" :value="editEmployeeLabel" disabled />
|
||
<el-select
|
||
v-else
|
||
v-model="form.employee_id"
|
||
filterable
|
||
placeholder="选择未建档的员工"
|
||
:loading="employeesLoading"
|
||
style="width: 100%"
|
||
>
|
||
<el-option
|
||
v-for="emp in candidateEmployees"
|
||
:key="emp.id"
|
||
:label="`${emp.name}(${emp.account})`"
|
||
:value="Number(emp.id)"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="档案编号" prop="file_no">
|
||
<el-input v-model="form.file_no" placeholder="留空自动生成" disabled maxlength="50" />
|
||
</el-form-item>
|
||
|
||
<el-divider content-position="left">个人信息</el-divider>
|
||
<el-row :gutter="12">
|
||
<el-col :span="12">
|
||
<el-form-item label="身份证号" prop="id_card">
|
||
<el-input v-model="form.id_card" maxlength="30" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="政治面貌" prop="political_status">
|
||
<el-select
|
||
v-model="form.political_status"
|
||
filterable
|
||
allow-create
|
||
default-first-option
|
||
clearable
|
||
placeholder="选择或输入"
|
||
style="width: 100%"
|
||
>
|
||
<el-option v-for="opt in politicalOptions" :key="opt" :label="opt" :value="opt" />
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="12">
|
||
<el-col :span="12">
|
||
<el-form-item label="婚姻状况" prop="marital_status">
|
||
<el-select v-model="form.marital_status" style="width: 100%">
|
||
<el-option label="未知" :value="0" />
|
||
<el-option label="未婚" :value="1" />
|
||
<el-option label="已婚" :value="2" />
|
||
<el-option label="离异" :value="3" />
|
||
<el-option label="丧偶" :value="4" />
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="籍贯" prop="native_place">
|
||
<el-input v-model="form.native_place" maxlength="100" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-form-item label="户籍地址" prop="household_address">
|
||
<el-input v-model="form.household_address" maxlength="255" />
|
||
</el-form-item>
|
||
<el-form-item label="现居住址" prop="current_address">
|
||
<el-input v-model="form.current_address" maxlength="255" />
|
||
</el-form-item>
|
||
<el-form-item label="工作邮箱" prop="work_email">
|
||
<el-input v-model="form.work_email" maxlength="100" />
|
||
</el-form-item>
|
||
|
||
<el-divider content-position="left">任职信息</el-divider>
|
||
<el-form-item label="在职状态" prop="employment_status">
|
||
<el-radio-group v-model="form.employment_status">
|
||
<el-radio-button :value="1">试用</el-radio-button>
|
||
<el-radio-button :value="2">正式</el-radio-button>
|
||
<el-radio-button :value="3">离职</el-radio-button>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item label="入职日期" prop="hire_date">
|
||
<el-date-picker
|
||
v-model="form.hire_date"
|
||
type="date"
|
||
value-format="YYYY-MM-DD"
|
||
placeholder="选择日期"
|
||
style="width: 100%"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="转正日期" prop="regular_date">
|
||
<el-date-picker
|
||
v-model="form.regular_date"
|
||
type="date"
|
||
value-format="YYYY-MM-DD"
|
||
placeholder="选择日期"
|
||
style="width: 100%"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="离职日期" prop="leave_date">
|
||
<el-date-picker
|
||
v-model="form.leave_date"
|
||
type="date"
|
||
value-format="YYYY-MM-DD"
|
||
placeholder="选择日期"
|
||
style="width: 100%"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-divider content-position="left">紧急联系人</el-divider>
|
||
<el-row :gutter="12">
|
||
<el-col :span="8">
|
||
<el-form-item label="联系人" prop="emergency_contact">
|
||
<el-input v-model="form.emergency_contact" maxlength="50" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="联系电话" prop="emergency_phone">
|
||
<el-input v-model="form.emergency_phone" maxlength="20" />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="与本人关系" prop="emergency_relation">
|
||
<el-input v-model="form.emergency_relation" maxlength="30" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input v-model="form.remark" type="textarea" :rows="2" maxlength="500" show-word-limit />
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<template #footer>
|
||
<el-button @click="visible = false">取消</el-button>
|
||
<el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, reactive, ref } from 'vue';
|
||
import { ElMessage } from 'element-plus';
|
||
import { createEmployeeFile, getFiledEmployeeIds, updateEmployeeFile } from '@/api/employeeFile';
|
||
import { oaOrganizationApi } from '@/api/organization';
|
||
|
||
/**
|
||
* 建档 / 编辑档案弹窗。
|
||
* 新建时员工下拉只展示未建档员工(全部员工 - 已建档ID),
|
||
* 选项先于表单回填加载完成,避免下拉异步回显问题。
|
||
*/
|
||
|
||
const emit = defineEmits(['success']);
|
||
|
||
const visible = ref(false);
|
||
const saving = ref(false);
|
||
const employeesLoading = ref(false);
|
||
const formRef = ref();
|
||
|
||
const isEdit = ref(false);
|
||
const editId = ref(0);
|
||
const editEmployeeLabel = ref('');
|
||
|
||
const allEmployees = ref([]);
|
||
const filedIds = ref([]);
|
||
|
||
const politicalOptions = ['群众', '中共党员', '中共预备党员', '共青团员', '民主党派', '无党派人士'];
|
||
|
||
const form = reactive({
|
||
employee_id: null,
|
||
file_no: '',
|
||
id_card: '',
|
||
political_status: '',
|
||
marital_status: 0,
|
||
native_place: '',
|
||
household_address: '',
|
||
current_address: '',
|
||
work_email: '',
|
||
hire_date: '',
|
||
regular_date: '',
|
||
leave_date: '',
|
||
employment_status: 2,
|
||
emergency_contact: '',
|
||
emergency_phone: '',
|
||
emergency_relation: '',
|
||
remark: '',
|
||
});
|
||
|
||
const rules = {
|
||
employee_id: [{ required: true, message: '请选择员工', trigger: 'change' }],
|
||
work_email: [
|
||
{
|
||
type: 'email',
|
||
message: '邮箱格式不正确',
|
||
trigger: ['blur', 'change'],
|
||
},
|
||
],
|
||
};
|
||
|
||
/** 未建档员工 = 全部员工 - 已建档员工 */
|
||
const candidateEmployees = computed(() => {
|
||
const filed = new Set(filedIds.value.map(Number));
|
||
return allEmployees.value.filter((emp) => !filed.has(Number(emp.id)));
|
||
});
|
||
|
||
const resetForm = () => {
|
||
form.employee_id = null;
|
||
form.file_no = '';
|
||
form.id_card = '';
|
||
form.political_status = '';
|
||
form.marital_status = 0;
|
||
form.native_place = '';
|
||
form.household_address = '';
|
||
form.current_address = '';
|
||
form.work_email = '';
|
||
form.hire_date = '';
|
||
form.regular_date = '';
|
||
form.leave_date = '';
|
||
form.employment_status = 2;
|
||
form.emergency_contact = '';
|
||
form.emergency_phone = '';
|
||
form.emergency_relation = '';
|
||
form.remark = '';
|
||
formRef.value?.clearValidate();
|
||
};
|
||
|
||
/** 加载员工下拉选项:全部员工 + 已建档ID并行请求 */
|
||
const loadEmployeeOptions = async () => {
|
||
employeesLoading.value = true;
|
||
try {
|
||
const [empRes, filedRes] = await Promise.all([
|
||
oaOrganizationApi.getEmployeeList(),
|
||
getFiledEmployeeIds(),
|
||
]);
|
||
allEmployees.value = empRes?.data || empRes || [];
|
||
filedIds.value = filedRes?.data || filedRes || [];
|
||
} catch (error) {
|
||
allEmployees.value = [];
|
||
filedIds.value = [];
|
||
ElMessage.error(error?.message || '加载员工选项失败');
|
||
} finally {
|
||
employeesLoading.value = false;
|
||
}
|
||
};
|
||
|
||
/** 打开弹窗;file 为空表示新建,否则回填编辑 */
|
||
const open = async (file = null) => {
|
||
resetForm();
|
||
isEdit.value = !!file?.id;
|
||
editId.value = file?.id || 0;
|
||
|
||
if (isEdit.value) {
|
||
// 编辑前先并行刷新选项数据,再回填表单
|
||
await loadEmployeeOptions();
|
||
editEmployeeLabel.value = file.employee_name
|
||
? `${file.employee_name}(${file.employee_account || '-'})`
|
||
: `员工 #${file.employee_id}`;
|
||
// 编辑时员工归属不可修改,但必须回填校验字段,避免保存时触发“请选择员工”。
|
||
form.employee_id = file.employee_id ? Number(file.employee_id) : null;
|
||
form.file_no = file.file_no || '';
|
||
form.id_card = file.id_card || '';
|
||
form.political_status = file.political_status || '';
|
||
form.marital_status = Number(file.marital_status ?? 0);
|
||
form.native_place = file.native_place || '';
|
||
form.household_address = file.household_address || '';
|
||
form.current_address = file.current_address || '';
|
||
form.work_email = file.work_email || '';
|
||
form.hire_date = file.hire_date || '';
|
||
form.regular_date = file.regular_date || '';
|
||
form.leave_date = file.leave_date || '';
|
||
form.employment_status = Number(file.employment_status ?? 2);
|
||
form.emergency_contact = file.emergency_contact || '';
|
||
form.emergency_phone = file.emergency_phone || '';
|
||
form.emergency_relation = file.emergency_relation || '';
|
||
form.remark = file.remark || '';
|
||
} else {
|
||
await loadEmployeeOptions();
|
||
}
|
||
|
||
visible.value = true;
|
||
};
|
||
|
||
const handleSave = async () => {
|
||
const valid = await formRef.value?.validate().then(() => true).catch(() => false);
|
||
if (!valid) return;
|
||
|
||
const payload = { ...form };
|
||
delete payload.employee_id;
|
||
|
||
saving.value = true;
|
||
try {
|
||
if (isEdit.value) {
|
||
await updateEmployeeFile(editId.value, payload);
|
||
} else {
|
||
await createEmployeeFile({ ...payload, employee_id: form.employee_id });
|
||
}
|
||
ElMessage.success(isEdit.value ? '保存成功' : '建档成功');
|
||
visible.value = false;
|
||
emit('success');
|
||
} catch (error) {
|
||
ElMessage.error(error?.message || '保存失败');
|
||
} finally {
|
||
saving.value = false;
|
||
}
|
||
};
|
||
|
||
defineExpose({ open });
|
||
</script>
|