From a0c5cb6ec8f45cd5caa0f0bf77f68e1267e3dd9e Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 6 Jun 2026 17:28:14 +0800 Subject: [PATCH] commit --- .../com/budwk/app/sys/models/Sys_user.java | 2 +- .../impl/SysDataUserAllUpdateServiceImpl.java | 62 +++++++++++++++++-- .../impl/SysDataUserPullServiceImpl.java | 3 +- .../info/MemberInfoBoardController.java | 8 ++- .../info/MemberInfoGroupController.java | 5 ++ .../member/service/MemberInfoService.java | 2 +- .../service/impl/MemberInfoServiceImpl.java | 3 + .../staffmanage/member/info/board/index.html | 41 +++++++----- .../staffmanage/member/info/group/index.html | 17 ++++- .../zhgh/welfare/projectMange/filterUser.js | 26 ++++---- 10 files changed, 128 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/budwk/app/sys/models/Sys_user.java b/src/main/java/com/budwk/app/sys/models/Sys_user.java index 7c362f33..26334f25 100644 --- a/src/main/java/com/budwk/app/sys/models/Sys_user.java +++ b/src/main/java/com/budwk/app/sys/models/Sys_user.java @@ -22,7 +22,7 @@ import java.util.List; @Data @EqualsAndHashCode(callSuper = true) @Accessors(chain = true) -@Table("sys_user") +@Table("") @TableMeta("{'mysql-charset':'utf8mb4'}") @TableIndexes({@Index(name = "INDEX_SYS_USER_LOGINNAMAE", fields = {"loginname"})}) public class Sys_user extends BaseModel implements Serializable { diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java index 4d74a992..65640829 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java @@ -67,10 +67,15 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService private static Map unitIdNameMap; /** - * 更新人员数据时仅按在职状态增加会员,不因状态不匹配取消已有会员。 + * 全量更新时,以下在职状态会自动设置为会员。 */ private static final Set MEMBER_USER_STATES = Set.of("在岗", "切线", "免职", "驻村", "援疆(藏)"); + /** + * 全量更新时,以下在职状态会自动取消会员身份和会员角色。 + */ + private static final Set REMOVE_MEMBER_USER_STATES = Set.of("离退休", "离世", "离校"); + /** * 字段映射类,用于缓存反射结果 */ @@ -152,6 +157,24 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService return StrUtil.isNotBlank(userState) && MEMBER_USER_STATES.contains(userState); } + /** + * 判断本次人员状态是否需要取消会员身份。 + */ + private boolean shouldRemoveMember(String userState) { + return StrUtil.isNotBlank(userState) && REMOVE_MEMBER_USER_STATES.contains(userState); + } + + /** + * 人员源数据只负责基础人员信息,会员缴费及会费类字段由会员业务维护。 + * 更新已有人员时置空这些字段,配合 updateIgnoreNull 避免把已维护的数据覆盖为空或默认值。 + */ + private void ignoreMemberBusinessFields(Sys_user user) { + user.setMemberFeePaid(null); + user.setMemberTime(null); + user.setPreparationMemberFee(null); + user.setContractMemberFee(null); + } + /** * 批量补充指定角色,已存在该角色的用户不重复插入。 */ @@ -190,6 +213,26 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService return insertCount; } + /** + * 批量取消会员身份并删除会员角色,仅用于全量更新中明确需要退会的人员状态。 + */ + private int removeMemberAndRole(List userIds, Sys_role memberRole) { + if (Lang.isEmpty(userIds) || memberRole == null) { + return 0; + } + List distinctUserIds = userIds.stream().filter(Objects::nonNull).distinct().toList(); + if (distinctUserIds.isEmpty()) { + return 0; + } + int removeRoleCount = 0; + for (List userIdBatch : ListUtil.split(distinctUserIds, 500)) { + dao.update(Sys_user.class, Chain.make("member", false), Cnd.where("id", "in", userIdBatch)); + removeRoleCount += dao.clear(Sys_user_role.class, + Cnd.where("roleId", "=", memberRole.getId()).and("userId", "in", userIdBatch)); + } + return removeRoleCount; + } + /** * 全量更新用户数据 * @@ -241,6 +284,7 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService Sys_user u = new Sys_user(); BeanUtils.copyProperties(source, u); boolean addMember = shouldAddMember(source.getUserState()); + boolean removeMember = shouldRemoveMember(source.getUserState()); if (user == null) { // 新增用户,初始化数据 @@ -250,20 +294,23 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService String salt = R.UU32(); u.setSalt(salt); u.setPassword(PwdUtil.getPassword(PwdUtil.generate(12), salt)); - // 更新人员数据只增加会员,不因状态不匹配取消已有会员。 if (addMember) { u.setMember(true); addMemberUserIds.add(u.getId()); + } else if (removeMember) { + u.setMember(false); } needInitUserList.add(u); } else { // 修改现有用户 - 根据工号判断是原有的人 u.setId(user.getId()); - // 保持原有会员身份不变 - // 更新人员数据只增加会员,不因状态不匹配取消已有会员。 + ignoreMemberBusinessFields(u); if (addMember) { u.setMember(true); addMemberUserIds.add(user.getId()); + } else if (removeMember) { + u.setMember(false); + removeMemberUserIds.add(user.getId()); } needDoUpdateList.add(u); @@ -362,7 +409,10 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService return "更新失败: " + e.getMessage(); } - // 全量更新后统一补齐角色:所有人补公共角色,所有会员补会员角色;仅新增缺失角色,不删除、不重复插入。 + int memberRoleRemoveCount = removeMemberAndRole(removeMemberUserIds, memberRole); + log.info("全量更新取消会员完成,取消会员{}个,删除会员角色{}个", removeMemberUserIds.stream().filter(Objects::nonNull).distinct().count(), memberRoleRemoveCount); + + // 全量更新后统一补齐角色:所有人补公共角色,所有会员补会员角色;仅新增缺失角色,不重复插入。 List latestUsers = dao.query(Sys_user.class, Cnd.NEW()); List allUserIds = latestUsers.stream().map(Sys_user::getId).filter(Objects::nonNull).toList(); List memberUserIds = latestUsers.stream() @@ -435,6 +485,8 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService log.info("全量更新用户数据完成,耗时: {} 毫秒", (endTime - startTime)); return "更新完成: 新增用户 " + needInitUserList.size() + " 个, 更新用户 " + needDoUpdateList.size() + + " 个, 取消会员 " + removeMemberUserIds.stream().filter(Objects::nonNull).distinct().count() + + " 个, 删除会员角色 " + memberRoleRemoveCount + " 个, 新增公共角色 " + publicRoleAddCount + " 个, 新增会员角色 " + memberRoleAddCount + " 个"; } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java index 21ecc100..7d5df596 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java @@ -196,7 +196,8 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl // 特殊处理 根据身份证号获取性别和出生年月 switch (mapping.field.getName()) { case "idCard" -> { - // 设置出生年月 + // 保存证件号码,并尝试根据身份证号解析出生年月;解析失败只影响生日字段。 + mapping.field.set(sysUser, value); if (StrUtil.isNotBlank(value)) { try { sysUser.setBirthday(IdcardUtil.getBirthDate(value)); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoBoardController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoBoardController.java index 1f8061b5..49e8956c 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoBoardController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoBoardController.java @@ -53,7 +53,7 @@ public class MemberInfoBoardController { } /** - * @return 今年会员数、未缴费会员数和去年的会员数 + * @return 今年职工数、缴费会员数、未缴费会员数和去年的会员数 */ @At @SaCheckPermission(value = {"member.info.board", "h5.member.info.board"}, mode = SaMode.OR) @@ -111,7 +111,7 @@ public class MemberInfoBoardController { /** - * 各工会会员数 + * 各工会职工数及缴费会员数 * * @return */ @@ -123,7 +123,9 @@ public class MemberInfoBoardController { un.name as unionname, un.unionCode, ( SELECT count( 1 ) FROM vw_user WHERE member = 1 and unionId = un.id ) `value`, - ( SELECT count( 1 ) FROM vw_user u LEFT JOIN sys_user su ON su.id = u.id WHERE u.member = 1 and u.unionId = un.id and (su.memberFeePaid = 0 or su.memberFeePaid is null) ) unpaidValue + ( SELECT count( 1 ) FROM vw_user u LEFT JOIN sys_user su ON su.id = u.id WHERE u.member = 1 and u.unionId = un.id and (su.memberFeePaid = 0 or su.memberFeePaid is null) ) unpaidValue, + ( SELECT count( 1 ) FROM vw_user WHERE member = 1 and unionId = un.id ) + - ( SELECT count( 1 ) FROM vw_user u LEFT JOIN sys_user su ON su.id = u.id WHERE u.member = 1 and u.unionId = un.id and (su.memberFeePaid = 0 or su.memberFeePaid is null) ) paidValue FROM sys_union un ORDER BY diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoGroupController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoGroupController.java index f8a197ee..93f9b038 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoGroupController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoGroupController.java @@ -1,6 +1,7 @@ package com.budwk.app.zhgh.staffmanage.member.controller.info; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaCheckRole; import cn.dev33.satoken.annotation.SaMode; import cn.hutool.core.util.DesensitizedUtil; import com.alibaba.excel.EasyExcel; @@ -104,6 +105,7 @@ public class MemberInfoGroupController { @At @SaCheckPermission("member.info.group") + @SaCheckRole(value = {"SYSADMIN", "SCHOOL_UNION_ADMIN", "SCHOOL_UNION_CHAIRMAN"}, mode = SaMode.OR) public Result toggleMemberFeePaid(String userId) { try { return Result.success(memberInfoService.toggleMemberFeePaid(userId)); @@ -115,6 +117,7 @@ public class MemberInfoGroupController { @At @SaCheckPermission("member.info.group") + @SaCheckRole(value = {"SYSADMIN", "SCHOOL_UNION_ADMIN", "SCHOOL_UNION_CHAIRMAN"}, mode = SaMode.OR) public Result batchSetMemberFeePaid(MemberInfoPageForm pageForm) { try { return Result.success(memberInfoService.batchSetMemberFeePaid(pageForm)); @@ -128,6 +131,7 @@ public class MemberInfoGroupController { @At @Ok("void") @SaCheckPermission("member.info.group") + @SaCheckRole(value = {"SYSADMIN", "SCHOOL_UNION_ADMIN", "SCHOOL_UNION_CHAIRMAN"}, mode = SaMode.OR) public void downloadMemberTemplate(HttpServletResponse response) { try { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); @@ -147,6 +151,7 @@ public class MemberInfoGroupController { @At @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("member.info.group") + @SaCheckRole(value = {"SYSADMIN", "SCHOOL_UNION_ADMIN", "SCHOOL_UNION_CHAIRMAN"}, mode = SaMode.OR) @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) public Result importMember(TempFile file, Boolean isFlag) { try { diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java index e9c1c959..2fa3bebc 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/MemberInfoService.java @@ -64,7 +64,7 @@ public interface MemberInfoService extends BaseService { /** * 获取会员看板会员数统计数据 * - * @return memberNum 会员总数、unpaidMemberNum 未缴费会员数、lastYearMemberNum 去年会员数 + * @return memberNum 会员总数、paidMemberNum 缴费会员数、unpaidMemberNum 未缴费会员数、lastYearMemberNum 去年会员数 */ NutMap getBoardMemberNumber(); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java index c5cf4eba..320fbf8b 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberInfoServiceImpl.java @@ -275,9 +275,12 @@ public class MemberInfoServiceImpl extends BaseServiceImpl implements int memberNum = count(Sqls.create("select count(1) from sys_user where member = 1")); // 空值按未缴费处理,保持会员列表中“是否缴费”的展示口径一致。 int unpaidMemberNum = count(Sqls.create("select count(1) from sys_user where member = 1 and (memberFeePaid = 0 or memberFeePaid is null)")); + // 缴费会员数用于会员看板展示,口径为当前会员总数减去未缴费会员数。 + int paidMemberNum = memberNum - unpaidMemberNum; int lastYearMemberNum = count(Sqls.create("select count(1) from member_history where year = year(now()) -1 ")); return NutMap.NEW() .addv("memberNum", memberNum) + .addv("paidMemberNum", paidMemberNum) .addv("unpaidMemberNum", unpaidMemberNum) .addv("lastYearMemberNum", lastYearMemberNum); } diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/info/board/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/info/board/index.html index e765ab62..8bef5e56 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/info/board/index.html +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/info/board/index.html @@ -292,9 +292,9 @@ layout("/layouts/platform.html"){
-
会员数/未缴费人数
+
职工数/会员数
- {{memberNumberData.memberNum}} / {{memberNumberData.unpaidMemberNum}} + {{memberNumberData.memberNum}} / {{memberNumberData.paidMemberNum}}  人
@@ -322,7 +322,7 @@ layout("/layouts/platform.html"){
-
工会会员数/未缴费数
+
工会职工数/会员数
@@ -356,7 +356,7 @@ layout("/layouts/platform.html"){ align="center" header-align="center" label="会员人数" - prop="value" + prop="paidValue" show-overflow-tooltip sortable width="120px" @@ -392,6 +392,7 @@ layout("/layouts/platform.html"){ }, memberNumberData: { memberNum: "--", + paidMemberNum: "--", unpaidMemberNum: "--", lastYearMemberNum: "--", ratio: "0.0%", @@ -412,11 +413,13 @@ layout("/layouts/platform.html"){ this.$axios.post("/platform/member/info/board/memberNumber").then((resp) => { if (resp.code === 0) { const { - data: { memberNum, unpaidMemberNum, lastYearMemberNum } + data: { memberNum, paidMemberNum, unpaidMemberNum, lastYearMemberNum } } = resp const diff = memberNum - lastYearMemberNum const ratio = (lastYearMemberNum ? (Math.abs(diff) / lastYearMemberNum) * 100 : (diff / 1) * 10).toFixed(2) + " %" - this.$set(this, "memberNumberData", { memberNum, unpaidMemberNum, lastYearMemberNum, diff, ratio }) + // 兼容旧接口未返回 paidMemberNum 的情况,会员数按总会员数减未缴费人数计算。 + const paidMemberCount = paidMemberNum !== undefined ? paidMemberNum : memberNum - unpaidMemberNum + this.$set(this, "memberNumberData", { memberNum, paidMemberNum: paidMemberCount, unpaidMemberNum, lastYearMemberNum, diff, ratio }) this.loading.memberNumber = false } else { this.$message.warning(resp.msg) @@ -577,23 +580,26 @@ layout("/layouts/platform.html"){ const unpaidValue = item.unpaidValue || item.unpaidvalue || 0 return Number(unpaidValue) || 0 }, - formatUnionMemberValue(item) { - const unpaidValue = this.getUnionUnpaidValue(item) - if (unpaidValue > 0) { - return item.value + "/" + unpaidValue + getUnionPaidValue(item) { + // 缴费会员数优先使用后端返回字段,旧数据则按职工数减未缴费数兜底。 + const paidValue = item.paidValue !== undefined && item.paidValue !== null ? item.paidValue : item.paidvalue + if (paidValue !== undefined && paidValue !== null) { + return Number(paidValue) || 0 } - return item.value + return (Number(item.value) || 0) - this.getUnionUnpaidValue(item) + }, + formatUnionMemberValue(item) { + return item.value + "/" + this.getUnionPaidValue(item) }, buildUnionMemberTooltip(title, items) { if (!items || !items.length) { return "" } const data = items[0].data || {} - const unpaidValue = this.getUnionUnpaidValue(data) return '
' + '
' + title + '
' + - '
会员数:' + data.value + '
' + - '
未缴费数:' + unpaidValue + '
' + + '
职工数:' + data.value + '
' + + '
会员数:' + this.getUnionPaidValue(data) + '
' + '
' }, async getUnionMember() { @@ -602,8 +608,11 @@ layout("/layouts/platform.html"){ this.loading.unionMember = false if (resp.code === 0) { const { chartData, tableData } = resp.data + // 标准化缴费会员数字段,避免后端 Record 字段大小写影响表格绑定和排序。 + chartData.forEach((item) => this.$set(item, "paidValue", this.getUnionPaidValue(item))) + tableData.forEach((item) => this.$set(item, "paidValue", this.getUnionPaidValue(item))) - this.unionMember = tableData + this.$set(this, "unionMember", tableData) if (chart.unionMemberChart) { chart.unionMemberChart.changeData(chartData) @@ -685,7 +694,7 @@ layout("/layouts/platform.html"){ alias: "类型" }, value: { - alias: "会员数" + alias: "职工数" } } }) diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/info/group/index.html b/src/main/resources/views/platform/zhgh/staffmanage/member/info/group/index.html index bd0b8c71..6bdb369d 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/info/group/index.html +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/info/group/index.html @@ -10,8 +10,20 @@ layout("/layouts/platform.html"){ - 一键设置已缴费 - 导入会员 + 一键设置已缴费 + 导入会员 查看 - - - - - - - + + @@ -107,6 +101,13 @@ const filterUser = { + + + + + + @@ -159,7 +160,8 @@ const filterUser = { userStates: [], personTypes: [], preparedBys: [], - unitIds: [] + unitIds: [], + memberFeePaid: null }, sexOptions: ["男", "女"], unionOptions: [], @@ -188,8 +190,7 @@ const filterUser = { }, resetPageForm() { - this.$set(this.pageForm, "userName", null) - this.$set(this.pageForm, "loginName", null) + this.$set(this.pageForm, "searchKeyword", null) this.$set(this.pageForm, "sex", null) this.$set(this.pageForm, "birthday", null) this.$set(this.pageForm, "birthMonths", []) @@ -199,6 +200,7 @@ const filterUser = { this.$set(this.pageForm, "preparedBys", []) this.$set(this.pageForm, "userStates", []) this.$set(this.pageForm, "isMember", null) + this.$set(this.pageForm, "memberFeePaid", null) }, pageData() {