待确认人员功能整改

This commit is contained in:
2026-09-29 15:35:03 +08:00
parent 5c0f593c08
commit 52bfd3578a
11 changed files with 240 additions and 20 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.budwk</groupId>
<artifactId>zhgh_cug_v4</artifactId>
<artifactId>mini</artifactId>
<version>5.6.0-plus</version>
<build>
<resources>
@@ -237,6 +237,11 @@ public class Sys_user extends BaseModel implements Serializable {
@ColDefine(type = ColType.DATE)
private Date retireDate;
@Column
@Comment("福利享受截止时间")
@ColDefine(type = ColType.DATE)
private Date welfareStopDate;
@Column
@Comment("博士后进站时间")
@ColDefine(type = ColType.DATE)
@@ -18,10 +18,21 @@ public enum MemberChangeType {
//变更类型
NEW("NEW", "新入职"),
BASIC_CHANGE("BASIC_CHANGE", "基本信息异动"),
UNIT_CHANGE("UNIT_CHANGE", "单位异动"),
UNION_CHANGE("UNION_CHANGE", "工会关系异动"),
ONLINE("ONLINE", "在岗"),
OFFLINE("OFFLINE", "不在岗"),
RESTORE("RESTORE", "入会"),
WITHDRAWAL("WITHDRAWAL", "退会"),
ONLINE("ONLINE", "在岗"),
EXTEND("EXTEND", "延聘"),
REHIRE_SCH("REHIRE_SCH", "学校返聘"),
REHIRE_DEPT("REHIRE_DEPT", "部门返聘"),
FLEX("FLEX", "柔性"),
SECONDED("SECONDED", "借调挂职"),
REMOTE_POST("REMOTE_POST", "异地任职"),
@@ -40,18 +51,7 @@ public enum MemberChangeType {
STUDY_DOMESTIC("STUDY_DOMESTIC", "国内进修"),
STUDY_ABROAD("STUDY_ABROAD", "境外留学"),
OFF_JOB_START("OFF_JOB_START", "离岗创业"),
INNER_RETIRE("INNER_RETIRE", "内部退养"),
EXTEND("EXTEND", "延聘"),
REHIRE_SCH("REHIRE_SCH", "学校返聘"),
REHIRE_DEPT("REHIRE_DEPT", "部门返聘"),
OFFLINE("OFFLINE", "不在岗"),
UNIT_CHANGE("UNIT_CHANGE", "单位异动"),
UNION_CHANGE("UNION_CHANGE", "工会关系异动"),
BASIC_CHANGE("BASIC_CHANGE", "基本信息异动");
INNER_RETIRE("INNER_RETIRE", "内部退养");
private final String code;
private final String changeTypeName;
@@ -262,6 +262,15 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
allowChangeFieldNames.add("threeUnitId");
dictMap.put("threeUnitId", "三级单位");
}
// 日期字段由具体变更表单明确传入时才参与比较,避免旧变更记录被误判为清空日期。
if (record.getRetireDate() != null) {
allowChangeFieldNames.add("retireDate");
dictMap.put("retireDate", "退休日期");
}
if (record.getWelfareStopDate() != null) {
allowChangeFieldNames.add("welfareStopDate");
dictMap.put("welfareStopDate", "福利享受截止时间");
}
// 新数据
NutMap newMap = Lang.obj2nutmap(record);
@@ -305,14 +314,18 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
@Override
@Aop(TransAop.READ_COMMITTED)
public void compareChangeInfoAndUpdateMember(String recordId) {
MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId);
compareChangeInfoAndUpdateMember(record);
}
@Override
@Aop(TransAop.READ_COMMITTED)
public void compareChangeInfoAndUpdateMember(MemberChangeRecord record) {
applyRetiredPersonType(record);
normalizeArrivalAtSchoolDate(record);
normalizeWelfareStopDate(record);
List<NutMap> changeList = getChangeInfos(record);
// 如果有工会关系人员,这个user用来存储数据
@@ -382,6 +395,10 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
// 到此,表明审核通过,需要存储历史数据,并修改用户数据
BeanUtil.copyProperties(record, info);
// 变更记录使用字符串接收页面日期,人员表使用 Date,保存前显式转换避免类型转换差异。
if (StrUtil.isNotBlank(record.getWelfareStopDate())) {
info.setWelfareStopDate(DateUtil.parseDate(record.getWelfareStopDate()));
}
info.setId(userId);
// 如果有单位变更,则需要记录单位关系
@@ -518,7 +535,9 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
@Override
public void validateChangeAndSetBasicData(MemberChangeRecord record, MemberChangeOrigin origin) {
applyRetiredPersonType(record);
normalizeArrivalAtSchoolDate(record);
normalizeWelfareStopDate(record);
// 校验有没有发生变更
List<NutMap> changeInfos = getChangeInfos(record);
if (Lang.isEmpty(changeInfos)) {
@@ -536,6 +555,43 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
record.setApplyDateTime(DateUtil.date());
}
/**
* 在职状态调整为退休时,按人员类型字典名称自动设置“离退休人员”编码。
* 字典中不存在该名称时保留原人员类型,不阻断其他变更。
*
* @param record 人员变更内容,userState 为“退休”时才执行自动设置
*/
private void applyRetiredPersonType(MemberChangeRecord record) {
if (record == null || !StrUtil.equals("退休", record.getUserState())) {
return;
}
List<Sys_dict> personTypeOptions = sysDictService.getSubListByCode("USER_PERSON_TYPE");
if (Lang.isEmpty(personTypeOptions)) {
return;
}
personTypeOptions.stream()
.filter(option -> StrUtil.equals("离退休人员", option.getName()))
.findFirst()
.ifPresent(option -> record.setPersonType(option.getCode()));
}
/**
* 校验并规范福利享受截止时间,统一使用 yyyy-MM-dd 参与比较及保存。
*
* @param record 人员变更内容,空日期保持为空
*/
private void normalizeWelfareStopDate(MemberChangeRecord record) {
if (record == null || StrUtil.isBlank(record.getWelfareStopDate())) {
return;
}
try {
Date parsedDate = parseArrivalAtSchoolDate(StrUtil.trim(record.getWelfareStopDate()));
record.setWelfareStopDate(DateUtil.format(parsedDate, "yyyy-MM-dd"));
} catch (Exception e) {
throw new BaseException("福利享受截止时间格式不正确,请使用yyyy-MM-dd格式");
}
}
/**
* 统一规范变更记录中的到校日期,避免 Date 对象复制后以英文字符串形式参与比较或直接落库。
@@ -2,6 +2,8 @@ package com.budwk.app.zhgh.staffmanage.sourcechange.param;
import lombok.Data;
import java.util.Date;
/**
* 待确认人员批量变更参数。
*/
@@ -23,6 +25,16 @@ public class PendingConfirmUserBatchChangeParam {
*/
private String userState;
/**
* 批量设置的退休时间,仅在目标在职状态为退休且传入日期时参与变更。
*/
private Date retireDate;
/**
* 批量设置的福利享受截止时间,仅在目标在职状态为退休且传入日期时参与变更。
*/
private Date welfareStopDate;
/**
* 批量设置的人员属性,空值不参与批量变更。
*/
@@ -120,6 +120,7 @@ public class PendingConfirmUserServiceImpl extends BaseServiceImpl<Sys_user> imp
if (record == null || StrUtil.isBlank(record.getUserId())) {
throw new BaseException("未获取到待确认人员数据");
}
applyRetiredPersonType(record);
if (StrUtil.isBlank(record.getPersonType())) {
throw new BaseException("请选择人员类型");
}
@@ -143,6 +144,7 @@ public class PendingConfirmUserServiceImpl extends BaseServiceImpl<Sys_user> imp
if (!hasBatchChangeField(changeParam)) {
throw new BaseException("请选择需要变更的内容");
}
applyRetiredPersonType(changeParam);
if (StrUtil.isNotBlank(changeParam.getPersonType())) {
validatePersonType(changeParam.getPersonType());
}
@@ -173,6 +175,13 @@ public class PendingConfirmUserServiceImpl extends BaseServiceImpl<Sys_user> imp
if (StrUtil.isNotBlank(changeParam.getUserState())) {
record.setUserState(changeParam.getUserState());
}
// 退休时间只随“退休”状态批量写入,其他状态忽略该参数,避免请求篡改隐藏字段。
if (StrUtil.equals("退休", changeParam.getUserState()) && changeParam.getRetireDate() != null) {
record.setRetireDate(changeParam.getRetireDate());
}
if (StrUtil.equals("退休", changeParam.getUserState()) && changeParam.getWelfareStopDate() != null) {
record.setWelfareStopDate(DateUtil.formatDate(changeParam.getWelfareStopDate()));
}
if (StrUtil.isNotBlank(changeParam.getUserAttribute())) {
record.setUserAttribute(changeParam.getUserAttribute());
}
@@ -239,13 +248,15 @@ public class PendingConfirmUserServiceImpl extends BaseServiceImpl<Sys_user> imp
safeRecord.setUserId(userId);
safeRecord.setPersonType(record.getPersonType() == null ? userView.getPersonType() : StrUtil.trim(record.getPersonType()));
safeRecord.setUserState(record.getUserState() == null ? userView.getUserState() : record.getUserState());
safeRecord.setRetireDate(record.getRetireDate() == null ? userView.getRetireDate() : record.getRetireDate());
safeRecord.setUserAttribute(record.getUserAttribute() == null ? userView.getUserAttribute() : record.getUserAttribute());
safeRecord.setMember(record.getMember() == null ? Integer.valueOf(1).equals(userView.getMember()) : record.getMember());
safeRecord.setWelfareMember(record.getWelfareMember() == null ? Integer.valueOf(1).equals(userView.getWelfareMember()) : record.getWelfareMember());
safeRecord.setArrivalAtSchoolDate(userView.getArrivalAtSchoolDate() == null
? null : DateUtil.formatDate(userView.getArrivalAtSchoolDate()));
safeRecord.setWelfareStopDate(userView.getWelfareStopDate() == null
? null : DateUtil.formatDate(userView.getWelfareStopDate()));
safeRecord.setWelfareStopDate(record.getWelfareStopDate() == null
? (userView.getWelfareStopDate() == null ? null : DateUtil.formatDate(userView.getWelfareStopDate()))
: record.getWelfareStopDate());
try {
// 复用公共校验和历史记录生成口径,确保单人、批量变更结果保持一致。
@@ -312,6 +323,53 @@ public class PendingConfirmUserServiceImpl extends BaseServiceImpl<Sys_user> imp
}
}
/**
* 单人待确认变更选择退休时,存在“离退休人员”字典项才自动设置人员类型编码。
*
* @param record 单人待确认变更内容
*/
private void applyRetiredPersonType(MemberChangeRecord record) {
if (record == null || !StrUtil.equals("退休", record.getUserState())) {
return;
}
String retiredPersonTypeCode = resolveRetiredPersonTypeCode();
if (StrUtil.isNotBlank(retiredPersonTypeCode)) {
record.setPersonType(retiredPersonTypeCode);
}
}
/**
* 批量待确认变更选择退休时,存在“离退休人员”字典项才自动设置人员类型编码。
*
* @param changeParam 批量待确认变更参数
*/
private void applyRetiredPersonType(PendingConfirmUserBatchChangeParam changeParam) {
if (changeParam == null || !StrUtil.equals("退休", changeParam.getUserState())) {
return;
}
String retiredPersonTypeCode = resolveRetiredPersonTypeCode();
if (StrUtil.isNotBlank(retiredPersonTypeCode)) {
changeParam.setPersonType(retiredPersonTypeCode);
}
}
/**
* 根据人员类型字典名称获取“离退休人员”编码,未配置时返回空字符串。
*
* @return 离退休人员字典编码,未配置时为空字符串
*/
private String resolveRetiredPersonTypeCode() {
List<Sys_dict> personTypeDicts = sysDictService.getSubListByCode("USER_PERSON_TYPE");
if (personTypeDicts == null) {
return "";
}
return personTypeDicts.stream()
.filter(dict -> StrUtil.equals("离退休人员", dict.getName()))
.map(Sys_dict::getCode)
.findFirst()
.orElse("");
}
/**
* 变更提交成功后仅把待确认人员更新为已确认,重复调用不会改变其他状态。
*
@@ -0,0 +1,19 @@
-- 系统用户增加福利享受截止时间,字段保持可空以兼容历史人员数据。
-- 脚本支持重复执行,字段已存在时不再修改表结构。
SET @welfare_stop_date_column_count = (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'sys_user'
AND COLUMN_NAME = 'welfareStopDate'
);
SET @welfare_stop_date_ddl = IF(
@welfare_stop_date_column_count = 0,
'ALTER TABLE sys_user ADD COLUMN welfareStopDate DATE NULL COMMENT ''福利享受截止时间'' AFTER retireDate',
'SELECT 1'
);
PREPARE welfare_stop_date_stmt FROM @welfare_stop_date_ddl;
EXECUTE welfare_stop_date_stmt;
DEALLOCATE PREPARE welfare_stop_date_stmt;
@@ -140,6 +140,7 @@ const MEMBER_CHANGE = {
<el-descriptions-item label="在职状态">
<el-form-item prop="userState">
<dict-select v-model="formData.userState" code="USER_STATE"
@change="handleRetiredStateChange"
:disabled="allowFields('userState')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
@@ -177,7 +178,6 @@ const MEMBER_CHANGE = {
<el-form-item prop="welfareStopDate">
<el-date-picker v-model="formData.welfareStopDate"
type="date"
:disabled="isView"
placeholder="请选择福利享受截止日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
@@ -392,6 +392,18 @@ const MEMBER_CHANGE = {
allowFields(prop) {
return !this.allowChangeFields.map(v => v.code).includes(prop)
},
/** 在职状态选择退休时,存在“离退休人员”字典项才自动设置对应人员类型编码。 */
handleRetiredStateChange(userState) {
if (userState !== "退休") {
return
}
this.$businessTool.getDictOptions("USER_PERSON_TYPE").then((options) => {
const retiredOption = (options || []).find((item) => item.name === "离退休人员")
if (retiredOption) {
this.$set(this.formData, "personType", retiredOption.code)
}
})
},
// 管理页仅查询当前被编辑人员所属二级单位的直属三级单位,避免越级选择其他单位数据。
initThreeUnits() {
this.threeUnits = []
@@ -500,6 +512,8 @@ const MEMBER_CHANGE = {
campus,
threeUnitId,
userState,
retireDate,
welfareStopDate,
personType,
preparedBy,
userAttribute,
@@ -528,6 +542,11 @@ const MEMBER_CHANGE = {
this.$set(this.formData, "campus", campus)
this.$set(this.formData, "threeUnitId", threeUnitId)
this.$set(this.formData, "userState", userState)
// 日期选择器使用 yyyy-MM-dd 字符串,避免接口日期值无法在组件中正确回显。
this.$set(this.formData, "retireDate", retireDate
? this.$moment(retireDate).format("YYYY-MM-DD") : "")
this.$set(this.formData, "welfareStopDate", welfareStopDate
? this.$moment(welfareStopDate).format("YYYY-MM-DD") : "")
this.$set(this.formData, "personType", personType)
this.$set(this.formData, "preparedBy", preparedBy)
this.$set(this.formData, "userAttribute", userAttribute)
@@ -200,8 +200,23 @@ layout("/layouts/platform.html"){
</el-form-item>
<el-form-item label="在职状态">
<dict-select v-model="batchChangeForm.userState" clearable code="USER_STATE"
@change="handleBatchUserStateChange"
placeholder="请选择在职状态" style="width: 100%"></dict-select>
</el-form-item>
<el-form-item label="退休时间" prop="retireDate"
v-if="batchChangeForm.userState === '退休'">
<el-date-picker v-model="batchChangeForm.retireDate" type="date"
placeholder="请选择退休时间"
format="yyyy-MM-dd" value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
<el-form-item label="福利享受截止时间" prop="welfareStopDate"
v-if="batchChangeForm.userState === '退休'">
<el-date-picker v-model="batchChangeForm.welfareStopDate" type="date"
placeholder="请选择福利享受截止时间"
format="yyyy-MM-dd" value-format="yyyy-MM-dd"
style="width: 100%"></el-date-picker>
</el-form-item>
<el-form-item label="人员属性">
<dict-select v-model="batchChangeForm.userAttribute" clearable code="USER_ATTRIBUTE"
placeholder="请选择人员属性" style="width: 100%"></dict-select>
@@ -254,6 +269,8 @@ layout("/layouts/platform.html"){
batchChangeForm: {
personType: "",
userState: "",
retireDate: "",
welfareStopDate: "",
userAttribute: "",
member: null,
welfareMember: null
@@ -343,6 +360,18 @@ layout("/layouts/platform.html"){
|| this.batchChangeForm.member !== null && this.batchChangeForm.member !== undefined && this.batchChangeForm.member !== ""
|| this.batchChangeForm.welfareMember !== null && this.batchChangeForm.welfareMember !== undefined && this.batchChangeForm.welfareMember !== ""
},
/** 退休状态自动匹配人员类型;非退休状态清理隐藏日期,避免沿用上次结果。 */
handleBatchUserStateChange(userState) {
if (userState === "退休") {
const retiredOption = this.pendingPersonTypeOptions.find((item) => item.name === "离退休人员")
if (retiredOption) {
this.$set(this.batchChangeForm, "personType", retiredOption.code)
}
return
}
this.$set(this.batchChangeForm, "retireDate", "")
this.$set(this.batchChangeForm, "welfareStopDate", "")
},
/** 二次确认批量操作,防止误改多名人员。 */
confirmBatchChange() {
if (!this.hasBatchChangeField()) {
@@ -373,6 +402,12 @@ layout("/layouts/platform.html"){
if (this.batchChangeForm.userState) {
params.userState = this.batchChangeForm.userState
}
if (this.batchChangeForm.userState === "退休" && this.batchChangeForm.retireDate) {
params.retireDate = this.batchChangeForm.retireDate
}
if (this.batchChangeForm.userState === "退休" && this.batchChangeForm.welfareStopDate) {
params.welfareStopDate = this.batchChangeForm.welfareStopDate
}
if (this.batchChangeForm.userAttribute) {
params.userAttribute = this.batchChangeForm.userAttribute
}
@@ -401,6 +436,8 @@ layout("/layouts/platform.html"){
resetBatchChangeForm() {
this.batchChangeForm.personType = ""
this.batchChangeForm.userState = ""
this.$set(this.batchChangeForm, "retireDate", "")
this.$set(this.batchChangeForm, "welfareStopDate", "")
this.batchChangeForm.userAttribute = ""
this.batchChangeForm.member = null
this.batchChangeForm.welfareMember = null
@@ -103,6 +103,7 @@
<el-descriptions-item label="在职状态">
<el-form-item prop="userState">
<dict-select v-model="pendingChangeForm.userState" code="USER_STATE"
@change="handlePendingRetiredStateChange"
:disabled="pendingAllowFields('userState')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
@@ -23,10 +23,22 @@ const PENDING_MEMBER_CHANGE = {
methods: {
/** 编辑模式仅允许修改待确认业务确认所需字段;查看模式下所有字段均为只读。 */
pendingAllowFields(prop) {
const editableFields = ["personType", "userState", "userAttribute", "member", "welfareMember"]
const editableFields = ["personType", "userState", "userAttribute", "member", "welfareMember",
"retireDate", "welfareStopDate"]
return this.pendingChangeReadonly || !editableFields.includes(prop)
},
/** 在职状态选择退休时,存在“离退休人员”字典项才自动设置对应人员类型编码。 */
handlePendingRetiredStateChange(userState) {
if (userState !== "退休") {
return
}
const retiredOption = this.pendingPersonTypeOptions.find((item) => item.name === "离退休人员")
if (retiredOption) {
this.$set(this.pendingChangeForm, "personType", retiredOption.code)
}
},
/** 从人员类型字典中仅保留待确认业务允许变更的两种类型。 */
loadPendingPersonTypeOptions() {
return this.$businessTool.getDictOptions("USER_PERSON_TYPE").then((options) => {
@@ -92,8 +104,9 @@ const PENDING_MEMBER_CHANGE = {
preparedBy: user.preparedBy,
userAttribute: user.userAttribute,
aidFundMemberUserType: user.aidFundMemberUserType,
retireDate: user.retireDate,
welfareStopDate: user.welfareStopDate,
retireDate: user.retireDate ? this.$moment(user.retireDate).format("YYYY-MM-DD") : "",
welfareStopDate: user.welfareStopDate
? this.$moment(user.welfareStopDate).format("YYYY-MM-DD") : "",
arrivalAtSchoolDate: user.arrivalAtSchoolDate,
families: user.families || [],
personalData: user.personalData