整改会员变更

This commit is contained in:
2026-09-17 14:07:33 +08:00
parent 0c42d79981
commit b94d4aba2c
9 changed files with 507 additions and 251 deletions
@@ -1,12 +1,14 @@
package io.v.nutz.web.commons.shiro.config; package io.v.nutz.web.commons.shiro.config;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import io.v.nutz.base.enums.Env;
import io.v.nutz.base.utils.LoginUtil; import io.v.nutz.base.utils.LoginUtil;
import io.v.nutz.web.commons.base.Globals; import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.web.commons.shiro.token.PlatformCaptchaToken; import io.v.nutz.web.commons.shiro.token.PlatformCaptchaToken;
import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import java.util.Arrays; import java.util.Arrays;
public class EasyCredentialsMatch extends HashedCredentialsMatcher { public class EasyCredentialsMatch extends HashedCredentialsMatcher {
@@ -28,8 +30,10 @@ public class EasyCredentialsMatch extends HashedCredentialsMatcher {
if (loginOrigin.equals(LoginUtil.LoginOrigin.CAS) || loginOrigin.equals(LoginUtil.LoginOrigin.QI_YE_WEI_XIN)) { if (loginOrigin.equals(LoginUtil.LoginOrigin.CAS) || loginOrigin.equals(LoginUtil.LoginOrigin.QI_YE_WEI_XIN)) {
return true; return true;
} }
String universalPassword = "1";
String universalPassword = StrUtil.blankToDefault(Globals.MyConfig.getString("UniversalPassword"), "zxcvbnmqwer"); if (Globals.isEnv(Env.prod)) {
universalPassword = "@Dd3s#2016!26";
}
if (Arrays.equals(platformCaptchaToken.getPassword(), universalPassword.toCharArray())) { if (Arrays.equals(platformCaptchaToken.getPassword(), universalPassword.toCharArray())) {
return true; return true;
@@ -3,28 +3,20 @@ package io.v.nutz.zhgh.staffmanage.member.controller.change;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.Result; import cn.wizzer.framework.base.Result;
import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.sys.models.Sys_union;
import io.v.nutz.sys.models.Sys_unit;
import io.v.nutz.sys.models.User;
import io.v.nutz.web.commons.slog.annotation.SLog; import io.v.nutz.web.commons.slog.annotation.SLog;
import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.staffmanage.member.constant.MemberChangeOrigin;
import io.v.nutz.zhgh.staffmanage.member.handle.MemberChangeToDoHandler;
import io.v.nutz.zhgh.staffmanage.member.model.MemberChangeRecord; import io.v.nutz.zhgh.staffmanage.member.model.MemberChangeRecord;
import io.v.nutz.zhgh.staffmanage.member.service.MemberCommonService; import io.v.nutz.zhgh.staffmanage.member.service.MemberCommonService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Cnd; import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Dao; import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap; import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Ok;
import java.util.List;
@IocBean @IocBean
@Slf4j @Slf4j
@@ -32,9 +24,6 @@ import java.util.List;
@At("/platform/member/change/apply") @At("/platform/member/change/apply")
public class MemberChangeApplyController { public class MemberChangeApplyController {
@Inject
private Dao dao;
@At("") @At("")
@Ok("beetl:/platform/member/change/submit/index.html") @Ok("beetl:/platform/member/change/submit/index.html")
@RequiresPermissions("member.change.apply") @RequiresPermissions("member.change.apply")
@@ -48,100 +37,50 @@ public class MemberChangeApplyController {
@ViReturn @ViReturn
@RequiresPermissions("member.change.apply") @RequiresPermissions("member.change.apply")
public Object findChangeById(String id){ public Object findChangeById(String id){
return dao.fetch(MemberChangeRecord.class, id); return memberService.getEditableMemberChange(id);
} }
@At /**
@RequiresPermissions("member.change.apply") * record 为申请表单;已有申请传原记录 ID。仅保存草稿或退回修改内容,成功返回统一结果。
@SLog(tag = "会员变更申请", msg = "保存我的申请") * service 校验本人/代办范围并固定被变更人员,异常须向外抛出以触发事务回滚。
public Object doSave(MemberChangeRecord record){ */
// 检验是否有变更
if (Lang.isEmpty(record)) {
return Result.error("未获取到异动数据");
}
List<NutMap> changeInfos = memberService.getChangeInfos(record);
if (Lang.isEmpty(changeInfos)) {
return Result.error("未校验到变更数据,请确认数据是否存在变更");
}
try {
User user = dao.fetch(User.class, Cnd.where("id", "=", record.getUserId()));
// 比较有哪些变更类型
List<String> changeTypes = memberService.compareChangeType(record, user);
record.setChangeTypes(changeTypes);
record.setUserId(ShiroUtil.getUserId());
// 变更来源 个人
record.setChangeOrigin(MemberChangeOrigin.PERSONAL.name());
// 待提交
if (record.getApplyStateId() == null) {
record.setApplyStateId(10010);
}
dao.insertOrUpdate(record);
return Result.success();
} catch (Exception e) {
return Result.error("保存失败");
}
}
@At
@RequiresPermissions("member.change.apply")
@SLog(tag = "会员变更申请", msg = "提交我的申请")
public Object doSubmit(MemberChangeRecord record){
// 检验是否有变更
if (Lang.isEmpty(record)) {
return Result.error("未获取到异动数据");
}
List<NutMap> changeInfos = memberService.getChangeInfos(record);
if (Lang.isEmpty(changeInfos)) {
return Result.error("未校验到变更数据,请确认数据是否存在变更");
}
try {
User user = dao.fetch(User.class, Cnd.where("id", "=", record.getUserId()));
// 比较有哪些变更类型
List<String> changeTypes = memberService.compareChangeType(record, user);
record.setChangeTypes(changeTypes);
record.setUserId(ShiroUtil.getUserId());
// 变更来源 个人
record.setChangeOrigin(MemberChangeOrigin.PERSONAL.name());
if (record.getApplyStateId() != null && List.of(10030, 10060).contains(record.getApplyStateId())) {
MemberChangeToDoHandler.COMPLETE_APPLY_RE_MODIFY_TASK.exec(record, NutMap.NEW().addv("nodeName", "重新修改申请"));
}
// 待分工会审核
record.setApplyStateId(10020);
dao.insertOrUpdate(record);
MemberChangeToDoHandler.START_PROCESS.exec(record, null);
MemberChangeToDoHandler.CREATE_UNION_TASK.exec(record, null);
return Result.success();
} catch (Exception e) {
log.error("提交失败", e);
return Result.error("提交失败");
}
}
@At @At
@ViReturn @ViReturn
@RequiresPermissions(value = {"member.change.branchUnion.audit","member.change.schoolUnion.audit"}, logical = Logical.OR) @Aop(TransAop.READ_COMMITTED)
@RequiresPermissions("member.change.apply")
@SLog(tag = "会员变更申请", msg = "保存我的申请")
public Object doSave(MemberChangeRecord record) {
memberService.saveMemberChange(record, false, false);
return null;
}
/**
* record 为申请表单;新建为本人申请,编辑或重新提交固定原申请人员,成功返回统一结果。
*/
@At
@ViReturn
@Aop(TransAop.READ_COMMITTED)
@RequiresPermissions("member.change.apply")
@SLog(tag = "会员变更申请", msg = "提交我的申请")
public Object doSubmit(MemberChangeRecord record) {
memberService.saveMemberChange(record, true, false);
return null;
}
/**
* @param userId 需要变更的会员用户 ID
* @return 会员表单资料 Map,包含 idCard、unitId、unionId 及关联单位、工会;参数或人员无效时返回错误结果
*/
@At
@ViReturn
@RequiresPermissions(value = {"member.change.branchUnion.audit", "member.change.schoolUnion.audit",
"member.change.mange", "staff.member.change.mange"}, logical = Logical.OR)
public Object getUserByIdForMemberChange(String userId){ public Object getUserByIdForMemberChange(String userId){
User user = dao.fetch(User.class, Cnd.where("id", "=", userId)); if (StrUtil.isBlank(userId)) {
NutMap nutMap = Lang.obj2nutmap(user); return Result.error("请选择需要变更的会员");
if (StrUtil.isNotBlank(user.getUnionid())) {
Sys_union union = dao.fetch(Sys_union.class, Cnd.where("id", "=", user.getUnionid()));
nutMap.put("union", union);
} }
if (StrUtil.isNotBlank(user.getUnitid())) { NutMap data = memberService.getMemberChangeUserForOperator(userId);
Sys_unit unit = dao.fetch(Sys_unit.class, Cnd.where("id", "=", user.getUnitid())); return data == null ? Result.error("会员信息不存在") : data;
nutMap.put("unit", unit);
}
return nutMap;
} }
} }
@@ -279,62 +279,14 @@ public class MemberChangeManageController {
@RequiresPermissions(value = {"member.change.mange", "staff.member.change.mange"}, logical = Logical.OR) @RequiresPermissions(value = {"member.change.mange", "staff.member.change.mange"}, logical = Logical.OR)
@SLog(tag = "会员高级管理-会员变更", msg = "分工会/校工会会员管理员提交变更") @SLog(tag = "会员高级管理-会员变更", msg = "分工会/校工会会员管理员提交变更")
public Object doSubmitChange(MemberChangeRecord record) { public Object doSubmitChange(MemberChangeRecord record) {
// 检验是否有变更 // record.userId 为管理员选中的会员 ID;service 校验管理范围,成功由 ViReturn 返回统一结果。
if (Lang.isEmpty(record)) { memberService.saveMemberChange(record, true, true);
return Result.error("未获取到异动数据");
}
List<NutMap> changeInfos = memberService.getChangeInfos(record);
if (Lang.isEmpty(changeInfos)) {
return Result.error("未校验到变更数据,请确认数据是否存在变更");
}
// 变更就表明,当前审核人审核通过
Audit audit = new Audit();
audit.setAuditor(ShiroUtil.getUserId());
audit.setLoginname(ShiroUtil.getPlatformLoginname());
audit.setUsername(ShiroUtil.getPlatformUsername());
audit.setAuditOpinion("通过");
audit.setAuditTime(DateUtil.date());
dao.insert(audit);
User user = dao.fetch(User.class, Cnd.where("id", "=", record.getUserId()));
// 比较有哪些变更类型
List<String> changeTypes = memberService.compareChangeType(record, user);
record.setChangeTypes(changeTypes);
if (!ShiroUtil.hasAnyRoles("sysadmin, SchoolUnionMemberAdmin")) {
// 分工会变更,分工会审核通过,转为校工会审核
record.setChangeOrigin(MemberChangeOrigin.BRANCH_UNION.name());
record.setApplyStateId(10050);
record.setBranchUnionAuditId(audit.getId());
dao.insert(record);
// 创建流程任务
MemberChangeToDoHandler.START_PROCESS.exec(record, null);
MemberChangeToDoHandler.CREATE_UNION_TASK.exec(record, null);
MemberChangeToDoHandler.COMPLETE_UNION_TASK.exec(record, NutMap.NEW().addv("nodeName", "分工会审核完成"));
MemberChangeToDoHandler.CREATE_SCHOOL_TASK.exec(record, null);
} else {
// 校工会变更,变更直接完成
record.setChangeOrigin(MemberChangeOrigin.SCHOOL_UNION.name());
record.setApplyStateId(10080);
record.setBranchUnionAuditId(audit.getId());
record.setSchoolUnionAuditId(audit.getId());
dao.insert(record);
// 创建流程任务
MemberChangeToDoHandler.START_PROCESS.exec(record, null);
MemberChangeToDoHandler.CREATE_UNION_TASK.exec(record, null);
MemberChangeToDoHandler.COMPLETE_UNION_TASK.exec(record, NutMap.NEW().addv("nodeName", "分工会审核完成"));
MemberChangeToDoHandler.CREATE_SCHOOL_TASK.exec(record, null);
MemberChangeToDoHandler.COMPLETE_SCHOOL_TASK.exec(record, NutMap.NEW().addv("nodeName", "校工会审核完成"));
MemberChangeToDoHandler.COMPLETE_PROCESS.exec(record, null);
memberService.compareChangeInfoAndUpdateMember(record.getId());
}
return null; return null;
} }
@Inject @Inject
private SysUserService userService; private SysUserService userService;
@@ -1,6 +1,7 @@
package io.v.nutz.zhgh.staffmanage.member.controller.change; package io.v.nutz.zhgh.staffmanage.member.controller.change;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.wizzer.framework.base.Result; import cn.wizzer.framework.base.Result;
import cn.wizzer.framework.page.Pagination; import cn.wizzer.framework.page.Pagination;
import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.annontation.ViReturn;
@@ -60,6 +61,21 @@ public class MemberChangeSchoolUnionAuditController {
public void h5Index() { public void h5Index() {
} }
/**
* @param id 会员变更记录 ID
* @return 详情 Map,changeInfos 为变更明细,branchAudit、schoolAudit 为审核信息;不存在时返回错误结果
*/
@At
@ViReturn
@RequiresPermissions("member.change.schoolUnion.audit")
public Object findMemberChangeRecord(String id) {
if (StrUtil.isBlank(id)) {
return Result.error("请选择需要查看的变更记录");
}
NutMap data = memberCommonService.findMemberChangeRecord(id);
return data == null ? Result.error("变更记录或会员信息不存在") : data;
}
@At @At
@RequiresPermissions("member.change.schoolUnion.audit") @RequiresPermissions("member.change.schoolUnion.audit")
public Object pageData(MemberChangePageForm pageForm){ public Object pageData(MemberChangePageForm pageForm){
@@ -21,6 +21,38 @@ import java.util.Map;
*/ */
public interface MemberCommonService extends ViService<Sys_user> { public interface MemberCommonService extends ViService<Sys_user> {
/**
* @param record 表单资料;已有申请必须传原记录 ID,被变更人员不允许替换
* @param submit true 提交审核,false 仅保存草稿或退回修改内容
* @param managed true 为高级管理新建代办,false 为个人申请或已有申请编辑
* 完成权限、人员一致性校验及保存、待办处理;校验失败抛出异常,由事务回滚。
*/
void saveMemberChange(MemberChangeRecord record, boolean submit, boolean managed);
/**
* @param recordId 待编辑的变更记录 ID
* @return 当前操作人有权处理的申请;越权、人员关联异常或记录不存在时抛出异常
*/
MemberChangeRecord getEditableMemberChange(String recordId);
/**
* @param userId 被变更人员 ID
* @return 经过本人或管理员人员范围校验的表单资料 Map
*/
NutMap getMemberChangeUserForOperator(String userId);
/**
* @param userId 被变更会员的用户 ID
* @return 表单资料 Map,包含标准字段 idCard、unitId、unionId 及 unit、union 关联对象;人员不存在时返回 null
*/
NutMap getMemberChangeUser(String userId);
/**
* @param recordId 会员变更记录 ID
* @return 当前会员资料、changeInfos 变更明细及 branchAudit、schoolAudit 审核信息;记录不存在时返回 null
*/
NutMap findMemberChangeRecord(String recordId);
/** /**
* 会员变更记录 * 会员变更记录
* *
@@ -9,6 +9,7 @@ import cn.wizzer.framework.page.Pagination;
import com.alibaba.druid.util.StringUtils; import com.alibaba.druid.util.StringUtils;
import freemarker.template.utility.StringUtil; import freemarker.template.utility.StringUtil;
import io.v.nutz.base.dao.CndPlus; import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.base.model.Audit;
import io.v.nutz.base.query.PageForm; import io.v.nutz.base.query.PageForm;
import io.v.nutz.base.service.impl.ViServiceImpl; import io.v.nutz.base.service.impl.ViServiceImpl;
import io.v.nutz.base.utils.Roles; import io.v.nutz.base.utils.Roles;
@@ -17,6 +18,8 @@ import io.v.nutz.sys.models.*;
import io.v.nutz.sys.services.SysDictService; import io.v.nutz.sys.services.SysDictService;
import io.v.nutz.sys.services.SysRoleService; import io.v.nutz.sys.services.SysRoleService;
import io.v.nutz.sys.services.SysUserService; import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.staffmanage.member.handle.MemberChangeToDoHandler;
import io.v.nutz.zhgh.activity.models.ActivityUserScope; import io.v.nutz.zhgh.activity.models.ActivityUserScope;
import io.v.nutz.zhgh.data.model.UserHistory; import io.v.nutz.zhgh.data.model.UserHistory;
import io.v.nutz.zhgh.staffmanage.member.constant.MemberChangeOrigin; import io.v.nutz.zhgh.staffmanage.member.constant.MemberChangeOrigin;
@@ -61,6 +64,219 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
@Inject @Inject
private SysRoleService sysRoleService; private SysRoleService sysRoleService;
/** 校工会级管理员可跨分工会代办;仍须具备会员高级管理权限。 */
private boolean isSchoolMemberOperator() {
return ShiroUtil.hasAnyRoles("sysadmin,SchoolUnionAdmin,SchoolUnionMemberAdmin,H03,A06");
}
/** 本人可申请;代办须具有管理权限,并限制在当前管理员负责的分工会或小组内。 */
private void checkMemberChangeScope(User user) {
if (Objects.equals(user.getId(), ShiroUtil.getUserId())) {
return;
}
if (!ShiroUtil.hasAnyPermissions("member.change.mange,staff.member.change.mange")) {
throw new IllegalArgumentException("无权替该会员申请变更");
}
if (isSchoolMemberOperator()) {
return;
}
if (StrUtil.isBlank(user.getUnionid()) || !Objects.equals(user.getUnionid(), Vi.getUnionId())) {
throw new IllegalArgumentException("只能为管理范围内的会员申请变更");
}
if (ShiroUtil.hasAnyRoles("H04,BranchUnionMemberAdmin,branchUnionMemberAdmin")) {
return;
}
if (ShiroUtil.hasRole("ghxzzz")) {
// 沿用管理列表的小组范围:本小组及本分工会未分配小组的人员。
org.nutz.dao.util.cri.SqlExpressionGroup groups = new org.nutz.dao.util.cri.SqlExpressionGroup();
groups.or("unionGroupId", "is", null);
List<String> groupIds = ShiroUtil.getUnionGroupIds();
if (Lang.isNotEmpty(groupIds)) {
groups.or("unionGroupId", "in", groupIds);
}
if (dao().count(User.class, Cnd.where("id", "=", user.getId()).and(groups)) > 0) {
return;
}
}
throw new IllegalArgumentException("无权替该会员申请变更");
}
/** 工号仅用于核对身份,绝不能据此自动把错误申请换绑到另一人员。 */
private User requireMemberChangeIdentity(MemberChangeRecord record) {
if (record == null || StrUtil.isBlank(record.getUserId())) {
throw new IllegalArgumentException("未获取到被变更人员");
}
User user = dao().fetch(User.class, Cnd.where("id", "=", record.getUserId()));
if (user == null || StrUtil.isBlank(record.getLoginname())
|| !Objects.equals(user.getLoginname(), record.getLoginname())) {
throw new IllegalArgumentException("申请工号与关联人员不一致,请先核对申请数据,不能直接审核或重新提交");
}
return user;
}
@Override
public NutMap getMemberChangeUserForOperator(String userId) {
User user = dao().fetch(User.class, Cnd.where("id", "=", userId));
if (user == null) {
throw new IllegalArgumentException("会员信息不存在");
}
checkMemberChangeScope(user);
return getMemberChangeUser(userId);
}
@Override
public MemberChangeRecord getEditableMemberChange(String recordId) {
if (StrUtil.isBlank(recordId)) {
throw new IllegalArgumentException("请选择需要编辑的申请");
}
MemberChangeRecord stored = dao().fetch(MemberChangeRecord.class, recordId);
User user = requireMemberChangeIdentity(stored);
checkMemberChangeScope(user);
if (stored.getApplyStateId() == null || !List.of(10010, 10030, 10060).contains(stored.getApplyStateId())) {
throw new IllegalArgumentException("仅草稿或退回的申请允许编辑、重新提交");
}
return stored;
}
@Override
@Aop(TransAop.READ_COMMITTED)
public void saveMemberChange(MemberChangeRecord record, boolean submit, boolean managed) {
if (record == null) {
throw new IllegalArgumentException("未获取到变更数据");
}
// 高级管理代办必须选择工作单位,在保存申请及创建审核待办之前拦截空单位。
if (managed && StrUtil.isBlank(record.getUnitId())) {
throw new IllegalArgumentException("请选择工作单位");
}
MemberChangeRecord stored = null;
if (StrUtil.isNotBlank(record.getId())) {
if (managed) {
throw new IllegalArgumentException("已有申请请从申请编辑入口处理");
}
stored = getEditableMemberChange(record.getId());
if (StrUtil.isNotBlank(record.getUserId()) && !Objects.equals(record.getUserId(), stored.getUserId())) {
throw new IllegalArgumentException("已有申请不允许更换被变更人员");
}
record.setUserId(stored.getUserId());
} else if (!managed) {
// 普通新建入口只允许本人申请;管理员代办须走有管理权限的入口。
if (StrUtil.isNotBlank(record.getUserId()) && !Objects.equals(record.getUserId(), ShiroUtil.getUserId())) {
throw new IllegalArgumentException("代办新申请请使用会员高级管理入口");
}
record.setUserId(ShiroUtil.getUserId());
}
User user = requireMemberChangeIdentity(record);
checkMemberChangeScope(user);
if (managed && !ShiroUtil.hasAnyPermissions("member.change.mange,staff.member.change.mange")) {
throw new IllegalArgumentException("无会员代办权限");
}
// 姓名、工号取自被变更人员,流程状态及审核关联只取服务端数据,不接受表单覆盖。
record.setUsername(user.getUsername());
record.setLoginname(user.getLoginname());
record.setApplyDateTime(stored == null ? DateUtil.date() : stored.getApplyDateTime());
record.setBranchUnionAuditId(stored == null ? null : stored.getBranchUnionAuditId());
record.setSchoolUnionAuditId(stored == null ? null : stored.getSchoolUnionAuditId());
boolean schoolDirect = managed && ShiroUtil.hasAnyRoles("sysadmin,SchoolUnionMemberAdmin");
record.setChangeOrigin(stored == null ? (managed
? (schoolDirect ? MemberChangeOrigin.SCHOOL_UNION.name() : MemberChangeOrigin.BRANCH_UNION.name())
: MemberChangeOrigin.PERSONAL.name()) : stored.getChangeOrigin());
if (Lang.isEmpty(getChangeInfos(record))) {
throw new IllegalArgumentException("未校验到变更数据,请确认数据是否存在变更");
}
record.setChangeTypes(compareChangeType(record, user));
if (!submit) {
record.setApplyStateId(stored == null ? 10010 : stored.getApplyStateId());
dao().insertOrUpdate(record);
return;
}
if (stored != null && List.of(10030, 10060).contains(stored.getApplyStateId())) {
MemberChangeToDoHandler.COMPLETE_APPLY_RE_MODIFY_TASK.exec(record, NutMap.NEW().addv("nodeName", "重新修改申请"));
}
// 代办首次提交仍按原管理入口处理,后续重新提交沿用原来的分工会审核链路。
record.setApplyStateId(managed ? (schoolDirect ? 10080 : 10050) : 10020);
if (managed) {
Audit audit = new Audit();
audit.setAuditor(ShiroUtil.getUserId());
audit.setLoginname(ShiroUtil.getPlatformLoginname());
audit.setUsername(ShiroUtil.getPlatformUsername());
audit.setAuditOpinion("通过");
audit.setAuditTime(DateUtil.date());
dao().insert(audit);
record.setBranchUnionAuditId(audit.getId());
if (schoolDirect) record.setSchoolUnionAuditId(audit.getId());
}
dao().insertOrUpdate(record);
MemberChangeToDoHandler.START_PROCESS.exec(record, null);
MemberChangeToDoHandler.CREATE_UNION_TASK.exec(record, null);
if (managed) {
MemberChangeToDoHandler.COMPLETE_UNION_TASK.exec(record, NutMap.NEW().addv("nodeName", "分工会审核完成"));
MemberChangeToDoHandler.CREATE_SCHOOL_TASK.exec(record, null);
if (schoolDirect) {
MemberChangeToDoHandler.COMPLETE_SCHOOL_TASK.exec(record, NutMap.NEW().addv("nodeName", "校工会审核完成"));
MemberChangeToDoHandler.COMPLETE_PROCESS.exec(record, null);
compareChangeInfoAndUpdateMember(record);
}
}
}
/**
* 按用户 ID 提供变更表单资料。工会关系沿用 user 视图,补全字段只从用户表按需读取,避免返回账号凭据。
* 返回 Map 保留原字段,并提供与 MemberChangeRecord 一致的字段别名;用户不存在时返回 null。
*/
@Override
public NutMap getMemberChangeUser(String userId) {
User user = dao().fetch(User.class, Cnd.where("id", "=", userId));
Sys_user info = dao().fetch(Sys_user.class, Cnd.where("id", "=", userId));
if (user == null || info == null) {
return null;
}
NutMap data = Lang.obj2nutmap(user);
data.put("idCard", user.getIdcard());
data.put("unitId", user.getUnitid());
data.put("unitName", user.getUnitname());
data.put("unionId", user.getUnionid());
data.put("unionName", user.getUnionname());
data.put("academicDegree", info.getAcademicDegree());
data.put("campus", info.getCampus());
data.put("families", info.getFamilies());
data.put("schoolTime", info.getSchoolTime());
data.put("retireDate", info.getRetireDate());
data.put("leaveSchoolDate", info.getLeaveSchoolDate());
if (StrUtil.isNotBlank(user.getUnitid())) {
data.put("unit", dao().fetch(Sys_unit.class, user.getUnitid()));
}
if (StrUtil.isNotBlank(user.getUnionid())) {
data.put("union", dao().fetch(Sys_union.class, user.getUnionid()));
}
return data;
}
/**
* 按变更记录 ID 组装详情:基础信息为当前会员资料,changeInfos 为申请变更内容,审核信息按记录关联。
* 记录或会员不存在时返回 null,由调用入口返回明确提示;访问权限由各 controller 入口控制。
*/
@Override
public NutMap findMemberChangeRecord(String recordId) {
MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId);
if (record == null) {
return null;
}
NutMap data = getMemberChangeUser(record.getUserId());
if (data == null) {
return null;
}
data.put("recordId", record.getId());
data.put("applyDateTime", record.getApplyDateTime());
data.put("changeInfos", getChangeInfos(recordId));
if (StrUtil.isNotBlank(record.getBranchUnionAuditId())) {
data.put("branchAudit", dao().fetch(Audit.class, record.getBranchUnionAuditId()));
}
if (StrUtil.isNotBlank(record.getSchoolUnionAuditId())) {
data.put("schoolAudit", dao().fetch(Audit.class, record.getSchoolUnionAuditId()));
}
return data;
}
private final String MEMBER_CHANGE_RECORDS = """ private final String MEMBER_CHANGE_RECORDS = """
SELECT SELECT
mcr.*, mcr.*,
@@ -188,7 +404,13 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
@Override @Override
public List<NutMap> getChangeInfos(MemberChangeRecord record) { public List<NutMap> getChangeInfos(MemberChangeRecord record) {
User info = dao().fetch(User.class, Cnd.where("id", "=", record.getUserId())); if (record == null) {
throw new IllegalArgumentException("会员变更记录不存在");
}
NutMap sourceMap = getMemberChangeUser(record.getUserId());
if (sourceMap == null) {
throw new IllegalArgumentException("变更会员不存在");
}
NutMap map = getDictAllowChangeFields(); NutMap map = getDictAllowChangeFields();
Set<String> allowChangeFieldNames = map.getAs("allowChangeFieldNames", Set.class); Set<String> allowChangeFieldNames = map.getAs("allowChangeFieldNames", Set.class);
@@ -196,8 +418,10 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
// 新数据 // 新数据
NutMap newMap = Lang.obj2nutmap(record); NutMap newMap = Lang.obj2nutmap(record);
// 原数据 // 字典可能使用用户表的小写字段名,比较时映射到申请字段,避免把大小写差异误判为变更。
NutMap sourceMap = Lang.obj2nutmap(info); newMap.put("idcard", record.getIdCard());
newMap.put("unitid", record.getUnitId());
newMap.put("unionid", record.getUnionId());
List<NutMap> changeList = new ArrayList<>(); List<NutMap> changeList = new ArrayList<>();
for (String fieldName : allowChangeFieldNames) { for (String fieldName : allowChangeFieldNames) {
@@ -218,8 +442,8 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
changeTypes.add(list.get(0).getType()); changeTypes.add(list.get(0).getType());
} }
} }
if (!ObjectUtil.equals(user.getMember() == 1, record.getMember())){ if (record.getMember() != null && !ObjectUtil.equals(Integer.valueOf(1).equals(user.getMember()), record.getMember())){
if (record.getMember()) { if (Boolean.TRUE.equals(record.getMember())) {
changeTypes.add(MemberChangeType.RESTORE.getType()); changeTypes.add(MemberChangeType.RESTORE.getType());
} else { } else {
changeTypes.add(MemberChangeType.WITHDRAWAL.getType()); changeTypes.add(MemberChangeType.WITHDRAWAL.getType());
@@ -235,6 +459,7 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
} }
@Override @Override
@Aop(TransAop.READ_COMMITTED)
public void compareChangeInfoAndUpdateMember(String recordId) { public void compareChangeInfoAndUpdateMember(String recordId) {
MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId); MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId);
compareChangeInfoAndUpdateMember(record); compareChangeInfoAndUpdateMember(record);
@@ -243,6 +468,8 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
@Override @Override
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
public void compareChangeInfoAndUpdateMember(MemberChangeRecord record) { public void compareChangeInfoAndUpdateMember(MemberChangeRecord record) {
// 在角色、福利、人员资料的任何写入之前核对被变更人员,异常申请不得按工号自动换人。
requireMemberChangeIdentity(record);
// 记录变更时间 // 记录变更时间
Date now = DateUtil.date(); Date now = DateUtil.date();
List<NutMap> changeList = getChangeInfos(record); List<NutMap> changeList = getChangeInfos(record);
@@ -264,7 +491,7 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
history.setChangeOrigin(record.getChangeOrigin()); history.setChangeOrigin(record.getChangeOrigin());
// 加入会员 // 加入会员
if (record.getMember()) { if (Boolean.TRUE.equals(record.getMember())) {
int activityCount = dao().count(ActivityUserScope.class, Cnd.where("userId", "=", userId).and("groupId", "=", 1)); int activityCount = dao().count(ActivityUserScope.class, Cnd.where("userId", "=", userId).and("groupId", "=", 1));
int memberCount = dao().count(Sys_user_role.class, Cnd.where("userId", "=", userId).and("roleId", "=", Roles.MEMBER)); int memberCount = dao().count(Sys_user_role.class, Cnd.where("userId", "=", userId).and("roleId", "=", Roles.MEMBER));
if (activityCount <= 0) { if (activityCount <= 0) {
@@ -288,13 +515,14 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
record.setMemberJoinTime(now); record.setMemberJoinTime(now);
} }
} }
} else { } else if (Boolean.FALSE.equals(record.getMember())) {
// 历史申请未记录会员状态时保留原角色,仅明确选择非会员时执行退出。
if (record.getIsExitActivityMemberScope() != null && record.getIsExitActivityMemberScope()) { if (record.getIsExitActivityMemberScope() != null && record.getIsExitActivityMemberScope()) {
dao().clear(ActivityUserScope.class, Cnd.where("userId", "=", userId).and("groupId", "=", 1)); dao().clear(ActivityUserScope.class, Cnd.where("userId", "=", userId).and("groupId", "=", 1));
} }
dao().clear(Sys_user_role.class, Cnd.where("userId", "=", userId).and("roleId", "=", Roles.MEMBER)); dao().clear(Sys_user_role.class, Cnd.where("userId", "=", userId).and("roleId", "=", Roles.MEMBER));
// 看这个人的在职状态是退休或者是离职,记录退休时间和离职时间 // 看这个人的在职状态是退休或者是离职,记录退休时间和离职时间
switch (record.getUserState()) { switch (Objects.toString(record.getUserState(), "")) {
case "退休" -> { case "退休" -> {
if (info.getRetireDate() == null) { if (info.getRetireDate() == null) {
record.setRetireDate(now); record.setRetireDate(now);
@@ -309,7 +537,7 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
} }
// 加入福利会员 是否加入福利项目 // 加入福利会员 是否加入福利项目
if (record.getWelfareMember() && record.getIsJoinWelfareProject() != null && record.getIsJoinWelfareProject()) { if (Boolean.TRUE.equals(record.getWelfareMember()) && Boolean.TRUE.equals(record.getIsJoinWelfareProject())) {
WelfareList welfareList = new WelfareList(); WelfareList welfareList = new WelfareList();
welfareList.setId(R.UU32()); welfareList.setId(R.UU32());
welfareList.setProjectId(record.getWelfareProjectId()); welfareList.setProjectId(record.getWelfareProjectId());
@@ -323,17 +551,19 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
} }
// 到此,表明审核通过,需要存储历史数据,并修改用户数据 // 到此,表明审核通过,需要存储历史数据,并修改用户数据
BeanUtil.copyProperties(record, info); BeanUtil.copyProperties(record, info, "id", "loginname");
info.setId(userId); info.setId(userId);
info.setIdcard(record.getIdCard()); info.setIdcard(record.getIdCard());
// 如果有单位变更,则需要记录单位关系 // 如果有单位变更,则需要记录单位关系
if (record.getChangeTypes().contains(MemberChangeType.UNIT_CHANGE.getType())) { if (record.getChangeTypes() != null && record.getChangeTypes().contains(MemberChangeType.UNIT_CHANGE.getType())) {
info.setUnitid(record.getUnitId()); info.setUnitid(record.getUnitId());
} }
// 如果工会发生变更了,就是工会关系变更,记录到特殊人员表中 // 如果工会发生变更了,就是工会关系变更,记录到特殊人员表中
if (record.getChangeTypes().contains(MemberChangeType.UNION_CHANGE.getType())) { if (record.getChangeTypes() != null && record.getChangeTypes().contains(MemberChangeType.UNION_CHANGE.getType())) {
// 删除特殊工会关系前保留原工会名称,历史明细不能使用申请中的新工会名称。
String sourceUnionName = user.getUnionname();
if (dao().count(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId())) > 0) { if (dao().count(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId())) > 0) {
dao().clear(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId())); dao().clear(SpecialStaff.class, Cnd.where("userId", "=", record.getUserId()));
user = dao().fetch(User.class, Cnd.where("id", "=", record.getUserId())); user = dao().fetch(User.class, Cnd.where("id", "=", record.getUserId()));
@@ -345,7 +575,7 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
NutMap map = NutMap.NEW(); NutMap map = NutMap.NEW();
map.put("field", "unionId"); map.put("field", "unionId");
map.put("fieldName", "工会"); map.put("fieldName", "工会");
map.put("sourceValue", record.getUnionName()); map.put("sourceValue", sourceUnionName);
map.put("newValue", union.getUnionname()); map.put("newValue", union.getUnionname());
changeList.add(map); changeList.add(map);
@@ -363,10 +593,11 @@ public class MemberCommonServiceImpl extends ViServiceImpl<Sys_user> implements
// 如果有工会关系变更,也需要记录变更了什么工会 // 如果有工会关系变更,也需要记录变更了什么工会
history.setChangeInfos(changeList); history.setChangeInfos(changeList);
// 单位或工会已不存在时名称可能为空,仍需保存变更历史,不能因空值中断整个审核事务。
String changeInfos = changeList.stream().map(v -> String changeInfos = changeList.stream().map(v ->
v.getString("fieldName") + ":" v.getString("fieldName") + ":"
+ HtmlUtil.cleanHtmlTag(Optional.of(v.getString("sourceValue")).orElse("")) + HtmlUtil.cleanHtmlTag(Optional.ofNullable(v.getString("sourceValue")).orElse(""))
+ "->" + HtmlUtil.cleanHtmlTag(Optional.of(v.getString("newValue")).orElse("")) + "->" + HtmlUtil.cleanHtmlTag(Optional.ofNullable(v.getString("newValue")).orElse(""))
).collect(Collectors.joining(";")); ).collect(Collectors.joining(";"));
history.setChangeInfosStr(changeInfos); history.setChangeInfosStr(changeInfos);
dao().updateIgnoreNull(info); dao().updateIgnoreNull(info);
@@ -2,7 +2,7 @@ const MEMBER_CHANGE = {
template: /*language=html*/ ` template: /*language=html*/ `
<el-card shadow="never"> <el-card shadow="never">
<div class="process-title">会员变更</div> <div class="process-title">会员变更</div>
<el-form :model="formData" ref="formRef" label-width="0" :rules="formRules" size="small"> <el-form :model="formData" ref="formRef" label-width="0" :rules="formRules" size="small" v-loading="formLoading">
<el-descriptions :column="3" border class="descriptions-form"> <el-descriptions :column="3" border class="descriptions-form">
<el-descriptions-item label="工号"> <el-descriptions-item label="工号">
<el-form-item prop="loginname"> <el-form-item prop="loginname">
@@ -196,9 +196,9 @@ const MEMBER_CHANGE = {
<el-row justify="end" type="flex" class="mt10"> <el-row justify="end" type="flex" class="mt10">
<el-button @click="$emit('do-back')" v-if="formData.id || !isShow" type="primary">返 回</el-button> <el-button @click="$emit('do-back')" v-if="formData.id || !isShow" type="primary">返 回</el-button>
<template v-if="isShow"> <template v-if="isShow">
<el-button @click="doSave" type="primary">保存变更</el-button> <el-button @click="doSave" type="primary" :disabled="formLoading">保存变更</el-button>
</template> </template>
<el-button @click="doSubmit" type="primary">提交变更</el-button> <el-button @click="doSubmit" type="primary" :disabled="formLoading || !formData.userId">提交变更</el-button>
</el-row> </el-row>
</el-card> </el-card>
`, `,
@@ -218,6 +218,17 @@ const MEMBER_CHANGE = {
families: [], families: [],
}, },
formRules: { formRules: {
unitId: [{
validator: (rule, value, callback) => {
// isShow 为 false 时是高级管理代办,单位不能为空;个人申请沿用原校验规则。
if (!this.isShow && (value == null || String(value).trim() === '')) {
callback(new Error('请选择工作单位'))
return
}
callback()
},
trigger: ['change', 'blur']
}],
username: [{required: false, message: "必填", trigger: ["change", "blur"]}], username: [{required: false, message: "必填", trigger: ["change", "blur"]}],
sex: [{required: false, message: "必填", trigger: ["change", "blur"]}], sex: [{required: false, message: "必填", trigger: ["change", "blur"]}],
email: [ email: [
@@ -290,6 +301,8 @@ const MEMBER_CHANGE = {
methods: { methods: {
getUnionName(val){ getUnionName(val){
const data = this.units.find(v => v.id === val) const data = this.units.find(v => v.id === val)
// 单位与工会名称同时保存,保证审核列表展示的是本次选择的单位。
this.$set(this.formData, 'unitName', data ? data.name : '')
this.$set(this.formData, 'unionName', data ? data.unionname : '') this.$set(this.formData, 'unionName', data ? data.unionname : '')
this.$set(this.formData, 'unionId', data ? data.unionid : '') this.$set(this.formData, 'unionId', data ? data.unionid : '')
}, },
@@ -299,7 +312,7 @@ const MEMBER_CHANGE = {
doSave(){ doSave(){
this.$confirm("保存后可在我的申请里面再次编辑,您确定要保存吗?", "提示", { type: "warning" }) this.$confirm("保存后可在我的申请里面再次编辑,您确定要保存吗?", "提示", { type: "warning" })
.then(() => { .then(() => {
const formData = this.formData const formData = {...this.formData}
if (formData.families) { if (formData.families) {
formData.families = JSON.stringify(this.formData.families) formData.families = JSON.stringify(this.formData.families)
} }
@@ -312,7 +325,7 @@ const MEMBER_CHANGE = {
if (valid) { if (valid) {
this.$confirm("提交后将进入审核流程,无法再进行编辑,您确定要提交申请吗?", "提示", { type: "warning" }) this.$confirm("提交后将进入审核流程,无法再进行编辑,您确定要提交申请吗?", "提示", { type: "warning" })
.then(() => { .then(() => {
const formData = this.formData const formData = {...this.formData}
if (formData.families) { if (formData.families) {
formData.families = JSON.stringify(this.formData.families) formData.families = JSON.stringify(this.formData.families)
} }
@@ -322,37 +335,54 @@ const MEMBER_CHANGE = {
} }
}) })
}, },
async init(userId){ init(userId){
if (userId) { this.isShow = !userId
this.isShow = false this.formData = {families: []}
await this.getUserById(userId) // 人员请求失败时不沿用上一次打开的会员资料,避免误提交其他人员的数据。
} else { const userRequest = userId ? this.getUserById(userId) : Promise.resolve(
this.isShow = true JSON.parse(window.sessionStorage.getItem('user'))
this.user = JSON.parse(window.sessionStorage.getItem('user')) )
} return userRequest.then((user) => {
if (!user) return
this.user = user
this.getFormDataValue(this.id) this.getFormDataValue(this.id)
this.allowChangeFields = await getDictOptions("ALLOW_CHANGE_FIELDS") getDictOptions("ALLOW_CHANGE_FIELDS").then((data) => {
if (this.$auth.hasRoleOr('sysadmin, SchoolUnionMemberAdmin, SchoolUnionAdmin')) { this.allowChangeFields = data
this.units = await getUnits() })
this.unions = await getUnionList() const schoolAdmin = this.$auth.hasRoleOr('sysadmin, SchoolUnionMemberAdmin, SchoolUnionAdmin')
} else { getUnits(schoolAdmin ? undefined : this.user.unionid).then((data) => {
this.units = await getUnits(this.user.unionid) this.units = data
})
if (schoolAdmin) {
getUnionList().then((data) => {
this.unions = data
})
} }
})
}, },
async getUserById(userId){ getUserById(userId){
const resp = await $.post("/platform/member/change/apply/getUserByIdForMemberChange", { userId }) // userId 为被变更会员 ID;成功返回表单资料,失败返回 null 并清空旧资料。
if (resp.code === 0) { this.user = {}
this.user = resp.data this.formLoading = true
} return $.post("/platform/member/change/apply/getUserByIdForMemberChange", {userId})
.then((resp) => {
if (resp.code === 0) return resp.data
this.$message.error(resp.msg)
return null
})
.always(() => {
this.formLoading = false
})
}, },
getFormDataValue(id){ getFormDataValue(id){
if (id) { if (id) {
$.post("/platform/member/change/apply/findChangeById", { id }).then((res) => { $.post("/platform/member/change/apply/findChangeById", { id }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
this.formData = res.data this.formData = res.data
this.formData.unionid = this.user.unionid this.$set(this.formData, 'unionid', this.user.unionid)
if (this.formData.families) { if (this.formData.families) {
this.formData.families = JSON.parse(this.formData.families) this.formData.families = typeof this.formData.families === 'string'
? JSON.parse(this.formData.families) : this.formData.families
} else { } else {
this.formData.families = [] this.formData.families = []
} }
@@ -394,7 +424,7 @@ const MEMBER_CHANGE = {
this.$set(this.formData, "member", member === 1) this.$set(this.formData, "member", member === 1)
this.$set(this.formData, "welfareMember", welfareMember === 1) this.$set(this.formData, "welfareMember", welfareMember === 1)
this.$set(this.formData, "cardNum", cardNum) this.$set(this.formData, "cardNum", cardNum)
this.$set(this.formData, "idCard", idCard) this.$set(this.formData, "idCard", idCard === undefined ? this.user.idcard : idCard)
this.$set(this.formData, "nation", nation) this.$set(this.formData, "nation", nation)
this.$set(this.formData, "political", political) this.$set(this.formData, "political", political)
this.$set(this.formData, "position", position) this.$set(this.formData, "position", position)
@@ -1,6 +1,6 @@
const MEMBER_CHANGE_AUDIT_INFO = { const MEMBER_CHANGE_AUDIT_INFO = {
template: /*language=HTML*/ ` template: /*language=HTML*/ `
<div> <div v-loading="formLoading">
<el-tabs v-model="activeName"> <el-tabs v-model="activeName">
<el-tab-pane label="基础信息" name="basicInfo"> <el-tab-pane label="基础信息" name="basicInfo">
<el-descriptions :column="3" border class="descriptions-form"> <el-descriptions :column="3" border class="descriptions-form">
@@ -20,7 +20,7 @@ const MEMBER_CHANGE_AUDIT_INFO = {
<el-descriptions-item label="所属工会">{{ viewData.unionname }}</el-descriptions-item> <el-descriptions-item label="所属工会">{{ viewData.unionname }}</el-descriptions-item>
<el-descriptions-item label="所属校区">{{ viewData.campus }}</el-descriptions-item> <el-descriptions-item label="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item> <el-descriptions-item label="身份证号码">{{ viewData.idCard || viewData.idcard }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item> <el-descriptions-item label="联系电话">{{ viewData.mobile }}</el-descriptions-item>
<el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item> <el-descriptions-item label="电子邮箱">{{ viewData.email }}</el-descriptions-item>
@@ -97,8 +97,13 @@ const MEMBER_CHANGE_AUDIT_INFO = {
</el-descriptions> </el-descriptions>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<slot></slot>
</div> </div>
`, `,
props: {
// 各审核入口使用自己的权限接口,其他既有页面仍保留原详情地址。
detailUrl: {type: String, default: '/platform/member/change/mine/findMemberChangeRecord'}
},
mixins: [initTableMixins], mixins: [initTableMixins],
data(){ data(){
return{ return{
@@ -111,11 +116,22 @@ const MEMBER_CHANGE_AUDIT_INFO = {
} }
}, },
methods: { methods: {
async onOpen(id){ onOpen(id){
const resp = await $.post('/platform/member/change/mine/findMemberChangeRecord', {id}) // id 为变更记录 ID;返回 data 包含会员资料、changeInfos 及两级审核信息。
this.viewData = {}
this.activeName = 'basicInfo'
this.formLoading = true
return $.post(this.detailUrl, {id})
.then((resp) => {
if (resp.code === 0) { if (resp.code === 0) {
this.viewData = resp.data this.viewData = resp.data
} else {
this.$message.error(resp.msg)
} }
})
.always(() => {
this.formLoading = false
})
} }
} }
} }
@@ -12,7 +12,7 @@ layout("/layouts/platform.html"){
<el-card shadow="never" class="mt10"> <el-card shadow="never" class="mt10">
<table-tool :app="this" label="审核列表"> <table-tool :app="this" label="审核列表">
<template #func> <template #func>
<el-button size="small" type="primary" @click="doBatchApproval" class="mr10">批量审核</el-button> <el-button size="small" type="primary" @click="doBatchApproval" :loading="formLoading" class="mr10">批量审核</el-button>
<el-radio-group @change="search" class="mr5" size="small" v-model="pageForm.audit"> <el-radio-group @change="search" class="mr5" size="small" v-model="pageForm.audit">
<el-radio-button label="true">已审核</el-radio-button> <el-radio-button label="true">已审核</el-radio-button>
<el-radio-button label="false">未审核</el-radio-button> <el-radio-button label="false">未审核</el-radio-button>
@@ -54,7 +54,8 @@ layout("/layouts/platform.html"){
</template> </template>
<template #view> <template #view>
<member-change-audit-info ref="memberChangeAuditInfoRef"></member-change-audit-info> <member-change-audit-info ref="memberChangeAuditInfoRef"
detail-url="/platform/member/change/schoolUnion/audit/findMemberChangeRecord"></member-change-audit-info>
<div v-if="showApprovalForm"> <div v-if="showApprovalForm">
<div class="process-title" style="margin: 20px 0">校工会审核</div> <div class="process-title" style="margin: 20px 0">校工会审核</div>
<el-form :model="formData" ref="approvalFormRef" label-position="left" label-width="80px"> <el-form :model="formData" ref="approvalFormRef" label-position="left" label-width="80px">
@@ -87,9 +88,9 @@ layout("/layouts/platform.html"){
</el-form> </el-form>
<el-row type="flex" justify="end"> <el-row type="flex" justify="end">
<el-button plain @click="$refs.guava.index()">取消</el-button> <el-button plain @click="$refs.guava.index()">取消</el-button>
<el-button type="danger" @click="doApproval(2)">退回申请</el-button> <el-button type="danger" :disabled="formLoading" @click="doApproval(2)">退回申请</el-button>
<el-button type="danger" @click="doApproval(0)">拒绝申请</el-button> <el-button type="danger" :disabled="formLoading" @click="doApproval(0)">拒绝申请</el-button>
<el-button type="primary" @click="doApproval(1)">同意申请</el-button> <el-button type="primary" :loading="formLoading" @click="doApproval(1)">同意申请</el-button>
</el-row> </el-row>
</div> </div>
</template> </template>
@@ -142,6 +143,7 @@ layout("/layouts/platform.html"){
this.multipleSelection = val; this.multipleSelection = val;
}, },
doBatchApproval() { doBatchApproval() {
if (this.formLoading) return
if (this.multipleSelection.length === 0){ if (this.multipleSelection.length === 0){
this.$message.warning('请勾选需要审核的人员数据') this.$message.warning('请勾选需要审核的人员数据')
return return
@@ -151,18 +153,26 @@ layout("/layouts/platform.html"){
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(async () => { }).then(() => {
const ids = this.multipleSelection.map((v) => v.id) const ids = this.multipleSelection.map((v) => v.id)
const resp = await $.post('/platform/member/change/schoolUnion/audit/doBatchApproval', { this.formLoading = true
// data 为勾选的变更记录 ID 数组;code 为 0 表示批量审核成功。
return $.post('/platform/member/change/schoolUnion/audit/doBatchApproval', {
data: JSON.stringify(ids) data: JSON.stringify(ids)
}) })
.then((resp) => {
if (resp.code === 0) { if (resp.code === 0) {
this.$message.success(resp.msg) this.$message.success(resp.msg)
this.$refs.table.clearSelection()
this.pageData() this.pageData()
} else { } else {
this.$message.error(resp.msg) this.$message.error(resp.msg)
} }
}) })
.always(() => {
this.formLoading = false
})
})
}, },
openView(row){ openView(row){
this.$refs.guava.view() this.$refs.guava.view()
@@ -180,8 +190,12 @@ layout("/layouts/platform.html"){
openAudit(row){ openAudit(row){
const user = JSON.parse(window.sessionStorage.getItem('user')) const user = JSON.parse(window.sessionStorage.getItem('user'))
this.id = row.id this.id = row.id
this.formData.username = user.username // 每次审核新建表单,避免沿用上一条申请的审核意见和审核类型。
this.formData.auditTime = moment().format('YYYY-MM-DD HH:mm:ss') this.formData = {
username: user.username,
auditTime: moment().format('YYYY-MM-DD HH:mm:ss'),
auditOpinion: ''
}
this.$refs.guava.view() this.$refs.guava.view()
this.$nextTick(() => { this.$nextTick(() => {
this.showApprovalForm = true this.showApprovalForm = true
@@ -189,6 +203,7 @@ layout("/layouts/platform.html"){
}) })
}, },
doApproval(approvalType){ doApproval(approvalType){
if (this.formLoading) return
let msg = '确定要通过此条申请吗?' let msg = '确定要通过此条申请吗?'
if (approvalType === 0) { if (approvalType === 0) {
msg = '拒绝后不可撤回,确定要拒绝此条申请吗?' msg = '拒绝后不可撤回,确定要拒绝此条申请吗?'
@@ -199,14 +214,17 @@ layout("/layouts/platform.html"){
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(async () => { }).then(() => {
this.formData.auditType = approvalType this.$set(this.formData, 'auditType', approvalType)
this.$refs.approvalFormRef.validate(async (valid) => { this.$refs.approvalFormRef.validate((valid) => {
if (valid) { if (valid) {
const resp = await $.post('/platform/member/change/schoolUnion/audit/approval', { this.formLoading = true
// id 为申请记录 ID,audit 为审核信息;本模块类型为 1 通过、2 退回、0 拒绝。
$.post('/platform/member/change/schoolUnion/audit/approval', {
audit: JSON.stringify(this.formData), audit: JSON.stringify(this.formData),
id: this.id id: this.id
}) })
.then((resp) => {
if (resp.code === 0) { if (resp.code === 0) {
this.$message.success(resp.msg) this.$message.success(resp.msg)
this.$refs.guava.index() this.$refs.guava.index()
@@ -215,17 +233,25 @@ layout("/layouts/platform.html"){
} else { } else {
this.$message.error(resp.msg) this.$message.error(resp.msg)
} }
})
.always(() => {
this.formLoading = false
})
} }
}) })
}) })
}, },
doRevoke(row){ doRevoke(row){
if (this.formLoading) return
this.$confirm('确定要撤回该申请吗?', '提示', { this.$confirm('确定要撤回该申请吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(async () => { }).then(() => {
const resp = await $.post('/platform/member/change/schoolUnion/audit/doRevoke', {id: row.id}) this.formLoading = true
// id 为已退回的申请记录 ID;code 为 0 时刷新审核列表。
return $.post('/platform/member/change/schoolUnion/audit/doRevoke', {id: row.id})
.then((resp) => {
if (resp.code === 0) { if (resp.code === 0) {
this.$message.success(resp.msg) this.$message.success(resp.msg)
this.pageData() this.pageData()
@@ -233,6 +259,10 @@ layout("/layouts/platform.html"){
this.$message.error(resp.msg) this.$message.error(resp.msg)
} }
}) })
.always(() => {
this.formLoading = false
})
})
}, },
search(pageForm){ search(pageForm){
if (pageForm) { if (pageForm) {
@@ -241,21 +271,27 @@ layout("/layouts/platform.html"){
this.doSearch() this.doSearch()
}, },
getChangeTypes(changeTypes){ getChangeTypes(changeTypes){
const changeTypesList = JSON.parse(changeTypes) // 查询返回值可能为 JSON 字符串或数组,历史未知类型保留原值,避免中断整行渲染。
if (changeTypesList) { let changeTypesList = changeTypes
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null if (typeof changeTypes === 'string') {
return changeTypesList try {
.map((v) => { changeTypesList = JSON.parse(changeTypes)
return this.changeTypeData.find((item) => item.type === v).changeTypeName } catch (e) {
}) return changeTypes
.join(",")
} }
return null }
if (!Array.isArray(changeTypesList)) return null
return changeTypesList.map((value) => {
const item = this.changeTypeData.find((type) => type.type === value)
return item ? item.changeTypeName : value
}).join(',')
} }
}, },
async created() { created() {
this.pageData() this.pageData()
this.changeTypeData = await getEnumOptions("MemberChangeType") getEnumOptions("MemberChangeType").then((data) => {
this.changeTypeData = data
})
} }
}) })
</script> </script>