Files
yunzerwebsiteallinone/backend/src/views/apps/oa/employeefile/components/fileEditDialog.vue
T
2026-08-29 22:06:00 +08:00

319 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>