完成员工亲属实体关联改造并清理旧数据

This commit is contained in:
wkc
2026-04-24 08:55:05 +08:00
parent b7d020c0b2
commit b7db711906
25 changed files with 1298 additions and 219 deletions

View File

@@ -1,6 +1,6 @@
import request from '@/utils/request'
// 查询员工实体关系列表
// 查询员工亲属实体关系列表
export function listRelation(query) {
return request({
url: '/ccdi/staffEnterpriseRelation/list',
@@ -9,7 +9,16 @@ export function listRelation(query) {
})
}
// 查询员工实体关系详情
// 查询有效员工亲属下拉选项
export function listFamilyOptions(query) {
return request({
url: '/ccdi/staffEnterpriseRelation/familyOptions',
method: 'get',
params: { query }
})
}
// 查询员工亲属实体关系详情
export function getRelation(id) {
return request({
url: '/ccdi/staffEnterpriseRelation/' + id,
@@ -17,7 +26,7 @@ export function getRelation(id) {
})
}
// 新增员工实体关系
// 新增员工亲属实体关系
export function addRelation(data) {
return request({
url: '/ccdi/staffEnterpriseRelation',
@@ -26,7 +35,7 @@ export function addRelation(data) {
})
}
// 修改员工实体关系
// 修改员工亲属实体关系
export function updateRelation(data) {
return request({
url: '/ccdi/staffEnterpriseRelation',
@@ -35,7 +44,7 @@ export function updateRelation(data) {
})
}
// 删除员工实体关系
// 删除员工亲属实体关系
export function delRelation(ids) {
return request({
url: '/ccdi/staffEnterpriseRelation/' + ids,
@@ -51,7 +60,7 @@ export function importTemplate() {
})
}
// 导入员工实体关系
// 导入员工亲属实体关系
export function importData(file) {
const formData = new FormData()
formData.append('file', file)

View File

@@ -1,39 +1,73 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="身份证号" prop="personId">
<el-input
v-model="queryParams.personId"
placeholder="请输入身份证号"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="统一社会信用代码" prop="socialCreditCode">
<el-input
v-model="queryParams.socialCreditCode"
placeholder="请输入统一社会信用代码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="企业名称" prop="enterpriseName">
<el-input
v-model="queryParams.enterpriseName"
placeholder="请输入企业名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 240px">
<el-option label="有效" :value="1" />
<el-option label="无效" :value="0" />
</el-select>
</el-form-item>
<el-form :model="queryParams" ref="queryForm" size="small" v-show="showSearch" label-width="120px" class="query-form">
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="亲属身份证号" prop="personId">
<el-input
v-model="queryParams.personId"
placeholder="请输入亲属身份证号"
clearable
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="亲属姓名" prop="relationName">
<el-input
v-model="queryParams.relationName"
placeholder="请输入亲属姓名"
clearable
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="关联员工" prop="staffPersonName">
<el-input
v-model="queryParams.staffPersonName"
placeholder="请输入关联员工姓名或身份证号"
clearable
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="统一社会信用代码" prop="socialCreditCode">
<el-input
v-model="queryParams.socialCreditCode"
placeholder="请输入统一社会信用代码"
clearable
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="企业名称" prop="enterpriseName">
<el-input
v-model="queryParams.enterpriseName"
placeholder="请输入企业名称"
clearable
style="width: 100%"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 100%">
<el-option label="有效" :value="1" />
<el-option label="无效" :value="0" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row :gutter="10" class="mb8">
@@ -82,8 +116,13 @@
<el-table v-loading="loading" :data="relationList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="身份证号" align="center" prop="personId" width="180" :show-overflow-tooltip="true"/>
<el-table-column label="员工姓名" align="center" prop="personName" width="100" />
<el-table-column label="亲属身份证号" align="center" prop="personId" width="180" :show-overflow-tooltip="true"/>
<el-table-column label="亲属姓名" align="center" prop="relationName" width="120" :show-overflow-tooltip="true" />
<el-table-column label="关联员工" align="center" min-width="220">
<template slot-scope="scope">
<span>{{ formatStaffPerson(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column label="企业名称" align="center" prop="enterpriseName" :show-overflow-tooltip="true"/>
<el-table-column label="关联人在企业的职务" align="center" prop="relationPersonPost" width="150" :show-overflow-tooltip="true"/>
<el-table-column label="状态" align="center" prop="status" width="100">
@@ -141,32 +180,45 @@
<el-form ref="form" :model="form" :rules="rules" label-width="160px">
<el-row :gutter="16">
<el-col :span="24">
<el-form-item label="身份证号" prop="personId">
<el-form-item label="亲属身份证号" prop="personId">
<el-select
v-model="form.personId"
filterable
remote
reserve-keyword
placeholder="请输入身份证号搜索员工"
:remote-method="searchStaff"
:loading="staffLoading"
placeholder="请输入亲属身份证号搜索有效亲属"
:remote-method="searchFamilyOptions"
:loading="familyLoading"
:disabled="!isAdd"
@focus="handleSelectFocus"
@change="handleFamilyChange"
style="width: 100%"
>
<el-option
v-for="item in staffOptions"
:key="item.idCard"
:label="item.idCard + ' - ' + item.name"
:value="item.idCard"
v-for="item in familyOptions"
:key="item.relationCertNo"
:label="formatFamilyOptionLabel(item)"
:value="item.relationCertNo"
>
<span style="float: left">{{ item.idCard }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.name }}</span>
<span style="float: left">{{ item.relationCertNo }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.relationName }} / {{ item.staffPersonName || '-' }}</span>
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="亲属姓名">
<el-input v-model="form.relationName" disabled placeholder="选择亲属后自动带出" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="关联员工">
<el-input :value="formatStaffPerson(form)" disabled placeholder="选择亲属后自动带出" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="统一社会信用代码" prop="socialCreditCode">
@@ -209,11 +261,13 @@
</el-dialog>
<!-- 详情对话框 -->
<el-dialog title="员工实体关详情" :visible.sync="detailOpen" width="900px" append-to-body>
<el-dialog title="员工亲属实体关详情" :visible.sync="detailOpen" width="900px" append-to-body>
<div class="detail-container">
<el-divider content-position="left">基本信息</el-divider>
<el-descriptions :column="2" border>
<el-descriptions-item label="身份证号">{{ relationDetail.personId || '-' }}</el-descriptions-item>
<el-descriptions-item label="亲属身份证号">{{ relationDetail.personId || '-' }}</el-descriptions-item>
<el-descriptions-item label="亲属姓名">{{ relationDetail.relationName || '-' }}</el-descriptions-item>
<el-descriptions-item label="关联员工" :span="2">{{ formatStaffPerson(relationDetail) }}</el-descriptions-item>
<el-descriptions-item label="统一社会信用代码">{{ relationDetail.socialCreditCode || '-' }}</el-descriptions-item>
<el-descriptions-item label="企业名称" :span="2">{{ relationDetail.enterpriseName || '-' }}</el-descriptions-item>
<el-descriptions-item label="关联人在企业的职务">{{ relationDetail.relationPersonPost || '-' }}</el-descriptions-item>
@@ -286,13 +340,13 @@
<import-result-dialog
:visible.sync="importResultVisible"
:content="importResultContent"
title="导入结果"
title="员工亲属实体关联导入结果"
@close="handleImportResultClose"
/>
<!-- 导入失败记录对话框 -->
<el-dialog
title="导入失败记录"
title="员工亲属实体关联导入失败记录"
:visible.sync="failureDialogVisible"
width="1200px"
append-to-body
@@ -306,7 +360,8 @@
/>
<el-table :data="failureList" v-loading="failureLoading">
<el-table-column label="身份证号" prop="personId" align="center" width="180" />
<el-table-column label="亲属身份证号" prop="personId" align="center" width="180" />
<el-table-column label="亲属姓名" prop="relationName" align="center" width="120" :show-overflow-tooltip="true" />
<el-table-column label="企业名称" prop="enterpriseName" align="center" :show-overflow-tooltip="true"/>
<el-table-column label="统一社会信用代码" prop="socialCreditCode" align="center" width="180" :show-overflow-tooltip="true"/>
<el-table-column label="失败原因" prop="errorMessage" align="center" min-width="200" :show-overflow-tooltip="true" />
@@ -335,15 +390,15 @@ import {
getImportFailures,
getImportStatus,
getRelation,
listFamilyOptions,
listRelation,
updateRelation
} from "@/api/ccdiStaffEnterpriseRelation";
import {listBaseStaff} from "@/api/ccdiBaseStaff";
import {getToken} from "@/utils/auth";
import ImportResultDialog from "@/components/ImportResultDialog.vue";
export default {
name: "StaffEnterpriseRelation",
name: "StaffFamilyEnterpriseRelation",
dicts: ['ccdi_relation_status', 'ccdi_data_source'],
components: { ImportResultDialog },
data() {
@@ -360,7 +415,7 @@ export default {
showSearch: true,
// 总条数
total: 0,
// 员工实体关表格数据
// 员工亲属实体关表格数据
relationList: [],
// 弹出层标题
title: "",
@@ -368,7 +423,7 @@ export default {
open: false,
// 是否显示详情弹出层
detailOpen: false,
// 员工实体关详情
// 员工亲属实体关详情
relationDetail: {},
// 是否为新增操作
isAdd: false,
@@ -377,6 +432,8 @@ export default {
pageNum: 1,
pageSize: 10,
personId: null,
relationName: null,
staffPersonName: null,
socialCreditCode: null,
enterpriseName: null,
status: null
@@ -386,8 +443,8 @@ export default {
// 表单校验
rules: {
personId: [
{ required: true, message: "身份证号不能为空", trigger: "blur" },
{ pattern: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/, message: "请输入正确的18位身份证号", trigger: "blur" }
{ required: true, message: "亲属身份证号不能为空", trigger: "blur" },
{ pattern: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/, message: "请输入正确的18位亲属身份证号", trigger: "blur" }
],
socialCreditCode: [
{ required: true, message: "统一社会信用代码不能为空", trigger: "blur" },
@@ -407,9 +464,9 @@ export default {
{ max: 500, message: "补充说明长度不能超过500个字符", trigger: "blur" }
]
},
// 员工选项
staffOptions: [],
staffLoading: false,
// 有效员工亲属选项
familyOptions: [],
familyLoading: false,
// 导入参数
upload: {
// 是否显示弹出层
@@ -467,7 +524,7 @@ export default {
}
},
methods: {
/** 查询员工实体关系列表 */
/** 查询员工亲属实体关系列表 */
getList() {
this.loading = true;
listRelation(this.queryParams).then(response => {
@@ -476,25 +533,57 @@ export default {
this.loading = false;
});
},
/** 搜索员工 */
searchStaff(query) {
this.staffLoading = true;
// 如果输入为空,查询所有员工;否则根据身份证号模糊查询
const params = query !== '' ? { idCard: query, pageNum: 1, pageSize: 10 } : { pageNum: 1, pageSize: 10 };
listBaseStaff(params).then(response => {
this.staffOptions = response.rows;
this.staffLoading = false;
/** 搜索有效员工亲属 */
searchFamilyOptions(query) {
this.familyLoading = true;
listFamilyOptions(query || '').then(response => {
this.familyOptions = response.data || [];
this.familyLoading = false;
}).catch(() => {
this.staffLoading = false;
this.familyLoading = false;
});
},
/** 下拉框获得焦点时加载员工列表 */
/** 下拉框获得焦点时加载有效员工亲属列表 */
handleSelectFocus() {
// 如果选项列表为空,自动加载所有员工
if (!this.staffOptions || this.staffOptions.length === 0) {
this.searchStaff('');
if (!this.familyOptions || this.familyOptions.length === 0) {
this.searchFamilyOptions('');
}
},
/** 选中亲属后带出亲属姓名和关联员工 */
handleFamilyChange(value) {
if (!value) {
this.form.relationName = null;
this.form.staffPersonId = null;
this.form.staffPersonName = null;
return;
}
const selected = this.familyOptions.find(item => item.relationCertNo === value);
if (!selected) {
return;
}
this.form.relationName = selected.relationName;
this.form.staffPersonId = selected.staffPersonId;
this.form.staffPersonName = selected.staffPersonName;
},
formatFamilyOptionLabel(item) {
return `${item.relationCertNo} - ${item.relationName || '-'} / ${item.staffPersonName || '-'}`;
},
formatStaffPerson(row) {
if (!row || (!row.staffPersonName && !row.staffPersonId)) {
return '-';
}
if (row.staffPersonName && row.staffPersonId) {
return `${row.staffPersonName}${row.staffPersonId}`;
}
return row.staffPersonName || row.staffPersonId;
},
buildSubmitPayload() {
const payload = { ...this.form };
delete payload.relationName;
delete payload.staffPersonId;
delete payload.staffPersonName;
return payload;
},
/**
* 恢复导入状态
* 在created()钩子中调用
@@ -537,13 +626,16 @@ export default {
this.form = {
id: null,
personId: null,
relationName: null,
staffPersonId: null,
staffPersonName: null,
relationPersonPost: null,
socialCreditCode: null,
enterpriseName: null,
status: 1, // 数字类型,与后端保持一致
remark: null
};
this.staffOptions = [];
this.familyOptions = [];
this.resetForm("form");
},
/** 搜索按钮操作 */
@@ -566,7 +658,7 @@ export default {
handleAdd() {
this.reset();
this.open = true;
this.title = "添加员工实体关";
this.title = "添加员工亲属实体关";
this.isAdd = true;
},
/** 修改按钮操作 */
@@ -575,12 +667,16 @@ export default {
const id = row.id || this.ids[0];
getRelation(id).then(response => {
this.form = response.data;
// 加载员工信息以支持下拉显示
if (this.form.personId) {
this.searchStaff(this.form.personId);
this.familyOptions = [{
relationCertNo: this.form.personId,
relationName: this.form.relationName,
staffPersonId: this.form.staffPersonId,
staffPersonName: this.form.staffPersonName
}];
}
this.open = true;
this.title = "修改员工实体关";
this.title = "修改员工亲属实体关";
this.isAdd = false;
});
},
@@ -596,14 +692,15 @@ export default {
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
const payload = this.buildSubmitPayload();
if (this.isAdd) {
addRelation(this.form).then(response => {
addRelation(payload).then(() => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
} else {
updateRelation(this.form).then(response => {
updateRelation(payload).then(() => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
@@ -624,12 +721,12 @@ export default {
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "员工实体关数据导入";
this.upload.title = "员工亲属实体关数据导入";
this.upload.open = true;
},
/** 下载模板操作 */
importTemplate() {
this.download('ccdi/staffEnterpriseRelation/importTemplate', {}, `员工实体关导入模板_${new Date().getTime()}.xlsx`);
this.download('ccdi/staffEnterpriseRelation/importTemplate', {}, `员工亲属实体关导入模板_${new Date().getTime()}.xlsx`);
},
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
@@ -673,7 +770,7 @@ export default {
// 显示后台处理提示(不是弹窗,是通知)
this.$notify({
title: '导入任务已提交',
title: '员工亲属实体关联导入任务已提交',
message: '正在后台处理中,处理完成后将通知您',
type: 'info',
duration: 3000
@@ -772,7 +869,7 @@ export default {
// 全部成功
this.$notify({
title: '导入完成',
message: `全部成功!共导入${statusResult.totalCount}条数据`,
message: `员工亲属实体关联全部成功!共导入${statusResult.totalCount}条数据`,
type: 'success',
duration: 5000
});
@@ -782,7 +879,7 @@ export default {
// 部分失败
this.$notify({
title: '导入完成',
message: `成功${statusResult.successCount}条,失败${statusResult.failureCount}`,
message: `员工亲属实体关联成功${statusResult.successCount}条,失败${statusResult.failureCount}`,
type: 'warning',
duration: 5000
});
@@ -819,7 +916,7 @@ export default {
...taskData,
saveTime: Date.now()
};
localStorage.setItem('staff_enterprise_relation_import_last_task', JSON.stringify(data));
localStorage.setItem('staff_family_enterprise_relation_import_last_task', JSON.stringify(data));
} catch (error) {
console.error('保存导入任务状态失败:', error);
}
@@ -830,7 +927,7 @@ export default {
*/
getImportTaskFromStorage() {
try {
const data = localStorage.getItem('staff_enterprise_relation_import_last_task');
const data = localStorage.getItem('staff_family_enterprise_relation_import_last_task');
if (!data) return null;
const task = JSON.parse(data);
@@ -883,7 +980,7 @@ export default {
*/
clearImportTaskFromStorage() {
try {
localStorage.removeItem('staff_enterprise_relation_import_last_task');
localStorage.removeItem('staff_family_enterprise_relation_import_last_task');
} catch (error) {
console.error('清除导入任务状态失败:', error);
}
@@ -893,6 +990,19 @@ export default {
</script>
<style scoped>
.query-form ::v-deep .el-row {
display: flex;
flex-wrap: wrap;
}
.query-form ::v-deep .el-col {
float: none;
}
.query-form ::v-deep .el-form-item {
margin-right: 0;
}
.detail-container {
padding: 0 20px;
}