diff --git a/src/main/java/io/v/nutz/member/controller/change/MemberChangeManageController.java b/src/main/java/io/v/nutz/member/controller/change/MemberChangeManageController.java index 40c1746..e83907e 100644 --- a/src/main/java/io/v/nutz/member/controller/change/MemberChangeManageController.java +++ b/src/main/java/io/v/nutz/member/controller/change/MemberChangeManageController.java @@ -4,6 +4,8 @@ import cn.hutool.core.util.StrUtil; import cn.wizzer.framework.base.Result; import com.google.common.base.Joiner; import io.v.nutz.annontation.ViReturn; +import io.v.nutz.base.event.user.UserChangeMsg; +import io.v.nutz.base.event.user.UserChangePublisher; import io.v.nutz.base.utils.RCSCloudAPI; import io.v.nutz.base.utils.Vi; import io.v.nutz.dao.CndPlus; @@ -27,6 +29,7 @@ import io.v.nutz.sys.models.Sys_unit; import io.v.nutz.sys.models.Sys_user; import io.v.nutz.sys.models.User; import io.v.nutz.sys.services.SysDictService; +import io.v.nutz.sys.services.SysRoleService; import io.v.nutz.sys.services.SysUnitService; import io.v.nutz.sys.services.SysUserService; import io.v.nutz.util.ShiroUtil; @@ -43,6 +46,7 @@ import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.Strings; +import org.nutz.lang.random.R; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; @@ -84,6 +88,9 @@ public class MemberChangeManageController { @Inject private SysUnitService sysUnitService; + @Inject + private SysRoleService sysRoleService; + @At @ViReturn @RequiresPermissions("member.change.mange") @@ -126,6 +133,48 @@ public class MemberChangeManageController { .setParam("success", MemberChangeApplyState.SUCCESS) .setVar("failStates", Joiner.on(",").join(List.of(MemberChangeApplyState.UNION_FAIL, MemberChangeApplyState.SCHOOL_UNION_FAIL))); + sql.setCondition(memberSelectionCondition(unionId, unitId, threeUnitId, unionGroupId, + changeDateBefore, changeDateEnd, pageForm, campus, sex, personType, userState, + changeType, changed, isMember)); + return memberService.list(pageForm, sql); + } + + @At + @ViReturn + @RequiresPermissions("member.change.mange") + public Object selectAllUsers(@Param(value = "unionId", required = false) String unionId, + @Param(value = "unitId", required = false) String unitId, + @Param(value = "threeUnitId", required = false) String threeUnitId, + @Param(value = "unionGroupId", required = false) String unionGroupId, + @Param(value = "changeDateBefore", required = false) String changeDateBefore, + @Param(value = "changeDateEnd", required = false) String changeDateEnd, + PageForm pageForm, + @Param(value = "campus", required = false) String campus, + @Param(value = "sex", required = false) String sex, + @Param(value = "personType", required = false) String personType, + @Param(value = "userState", required = false) String userState, + @Param(value = "changeType", required = false) String changeType, + @Param(value = "changed", required = false) Integer changed, + @Param(value = "isMember", required = false) Integer isMember) { + Sql sql = Sqls.create(""" + SELECT u.id, u.loginname, u.username, u.unitname, u.unionname, + u.threeUnitName, u.campusId + FROM `user` u + LEFT JOIN user_history_latest his ON his.loginname = u.loginname + LEFT JOIN member_change_record_latest mcr ON mcr.userId = u.id + LEFT JOIN audit_state state ON mcr.stateId = state.stateId + $condition + """); + sql.setCondition(memberSelectionCondition(unionId, unitId, threeUnitId, unionGroupId, + changeDateBefore, changeDateEnd, pageForm, campus, sex, personType, userState, + changeType, changed, isMember)); + return memberService.listMap(sql); + } + + private CndPlus memberSelectionCondition(String unionId, String unitId, String threeUnitId, + String unionGroupId, String changeDateBefore, String changeDateEnd, + PageForm pageForm, String campus, String sex, String personType, + String userState, String changeType, Integer changed, Integer isMember) { CndPlus cnd = CndPlus.create(); SqlExpressionGroup group = new SqlExpressionGroup(); @@ -181,8 +230,7 @@ public class MemberChangeManageController { } } cnd.desc("his.changeTime"); - sql.setCondition(cnd); - return memberService.list(pageForm, sql); + return cnd; } @At @@ -424,35 +472,75 @@ public class MemberChangeManageController { @RequiresPermissions("member.change.mange") public Object userUnitMove(String threeUnitId, String unitId, @Param("userId[]") String[] userId) { + if (userId == null || userId.length == 0) { + return Result.error("请选择需要调整的用户"); + } Sys_unit unit = memberService.dao().fetch(Sys_unit.class, unitId); + if (unit == null) { + return Result.error("所选单位不存在"); + } Trans.exec(() -> { - Chain updateUnitChain = Chain.make("unitid", unit.getId()) - .add("unionid", unit.getUnionid()) - .add("threeUnitId", threeUnitId); - memberService.update("sys_user", updateUnitChain, Cnd.where("id", "in", userId)); + List users = dao.query(Sys_user.class, Cnd.where("id", "in", userId)); + if (users.size() != new HashSet<>(Arrays.asList(userId)).size()) { + throw new IllegalArgumentException("部分用户不存在,请重新选择"); + } + List audits = new ArrayList<>(); + List records = new ArrayList<>(); + List histories = new ArrayList<>(); + Map> usersByOriginUnit = new LinkedHashMap<>(); + Date applyTime = new Date(); + + for (Sys_user user : users) { + UserHistory history = new UserHistory(); + BeanUtils.copyProperties(user, history); + history.setId(R.UU32()); + history.setChangeTime(applyTime); + history.setChangeType(UserChangeType.UNIT_CHANGE.getCode()); + histories.add(history); - for (String uid : userId) { MemberChangeRecord record = new MemberChangeRecord(); record.setRecordMode(MemberChangeRecordMode.MEMBER.getCode()); record.setType(UserChangeType.UNIT_CHANGE.getCode()); - record.setUserId(uid); - record.setApplyTime(new Date()); + record.setUserId(user.getId()); + record.setOriginUnitId(user.getUnitid()); + record.setOriginUnionId(user.getUnionid()); + record.setOriginThreeUnitId(user.getThreeUnitId()); + record.setCurrentUnitId(unit.getId()); + record.setCurrentUnionId(unit.getUnionid()); + record.setCurrentThreeUnitId(threeUnitId); + record.setApplyTime(applyTime); record.setApplyOrigin(MemberChangeOrigin.SCHOOL.getCode()); - record.setRecordMode(MemberChangeRecordMode.MEMBER.getCode()); record.setStateId(MemberChangeApplyState.SUCCESS); Audit audit = new Audit(); audit.setAuditPass(true); audit.setAuditOpinion(MemberOrigin.BATCH.getDescription()); - String id = auditService.insert(audit).getId(); - - record.setSchoolAuditId(id); - memberService.insert(record); + audits.add(audit); + records.add(record); + usersByOriginUnit.computeIfAbsent(user.getUnitid(), key -> new ArrayList<>()).add(user.getId()); } + + dao.insert(audits); + for (int i = 0; i < records.size(); i++) { + records.get(i).setSchoolAuditId(audits.get(i).getId()); + } + dao.insert(records); + dao.fastInsert(histories); + + usersByOriginUnit.forEach((originUnitId, ids) -> + UserChangePublisher.broadcast(new UserChangeMsg(ids, + UserChangeMsg.UNIT_CHANGE_OPERATION, originUnitId, unit.getId()))); + + Chain updateUnitChain = Chain.make("unitid", unit.getId()) + .add("unionid", unit.getUnionid()) + .add("threeUnitId", threeUnitId); + memberService.update("sys_user", updateUnitChain, Cnd.where("id", "in", userId)); }); + userService.clearCache(); + sysRoleService.clearCache(); return null; } diff --git a/src/main/java/io/v/nutz/member/controller/info/MemberGroupInfoController.java b/src/main/java/io/v/nutz/member/controller/info/MemberGroupInfoController.java index 5eff655..30d4cd2 100644 --- a/src/main/java/io/v/nutz/member/controller/info/MemberGroupInfoController.java +++ b/src/main/java/io/v/nutz/member/controller/info/MemberGroupInfoController.java @@ -48,6 +48,9 @@ import org.springframework.util.CollectionUtils; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -310,13 +313,51 @@ public class MemberGroupInfoController { List userList = new ArrayList<>(); - List errorInfos = new ArrayList<>(); + List errorInfos = new ArrayList<>(); memberImportList.forEach(v -> { Sys_user user = sysUserService.fetch(Cnd.where("loginname", "=", v.getLoginName())); user = user == null ? new Sys_user() : user; Sys_unit unit = unitMap.get(v.getUnitName()); + List errors = new ArrayList<>(); + if (!isfg && user.getId() != null) { + errors.add("一卡通号已存在,仅追加模式不能重复导入"); + } if (unit == null) { - errorInfos.add(v); + errors.add("请核对该人员的单位信息"); + } + String schoolTime = StrUtil.trim(v.getSchoolTime()); + LocalDate schoolDate = null; + if (StrUtil.isNotBlank(schoolTime)) { + if (!schoolTime.matches("[0-9]{8}|[0-9]{4}-[0-9]{2}-[0-9]{2}")) { + errors.add("入校时间【" + schoolTime + "】格式错误,请填写yyyy-MM-dd或yyyyMMdd"); + } else { + try { + schoolDate = LocalDate.parse(schoolTime, schoolTime.length() == 8 + ? DateTimeFormatter.BASIC_ISO_DATE : DateTimeFormatter.ISO_LOCAL_DATE); + } catch (DateTimeParseException e) { + errors.add("入校时间【" + schoolTime + "】不是有效日期,请核对年月日"); + } + } + } + String memberJoinTime = StrUtil.trim(v.getMemberJoinTime()); + LocalDate memberJoinDate = null; + if (StrUtil.isNotBlank(memberJoinTime)) { + if (!memberJoinTime.matches("[0-9]{8}|[0-9]{4}-[0-9]{2}-[0-9]{2}")) { + errors.add("入会时间【" + memberJoinTime + "】格式错误,请填写yyyy-MM-dd或yyyyMMdd"); + } else { + try { + memberJoinDate = LocalDate.parse(memberJoinTime, memberJoinTime.length() == 8 + ? DateTimeFormatter.BASIC_ISO_DATE : DateTimeFormatter.ISO_LOCAL_DATE); + } catch (DateTimeParseException e) { + errors.add("入会时间【" + memberJoinTime + "】不是有效日期,请核对年月日"); + } + } + } + if (!errors.isEmpty()) { + errorInfos.add(NutMap.NEW().addv("工号", v.getLoginName()).addv("姓名", v.getUserName()) + .addv("性别", v.getSex()).addv("所属工会", v.getUnionName()).addv("所属单位", v.getUnitName()) + .addv("入校时间", v.getSchoolTime()).addv("入会时间", v.getMemberJoinTime()) + .addv("错误原因", String.join(";", errors))); } else { user.setId(user.getId() == null ? R.UU32() : user.getId()); user.setLoginname(v.getLoginName()); @@ -330,8 +371,8 @@ public class MemberGroupInfoController { user.setPolitical(v.getPolitical()); user.setEducation(v.getEducation()); user.setJobTitle(v.getJobTitle()); - user.setSchoolTime(v.getSchoolTime()); - user.setMemberJoinTime(v.getMemberJoinTime() != null ? DateUtil.parseDate(v.getMemberJoinTime()) : null); + user.setSchoolTime(schoolDate == null ? null : schoolDate.toString()); + user.setMemberJoinTime(memberJoinDate == null ? null : DateUtil.parseDate(memberJoinDate.toString())); user.setPersonType(v.getPersonType()); user.setPreparedBy(v.getPreparedBy()); user.setRemarks(v.getRemarks()); @@ -350,16 +391,12 @@ public class MemberGroupInfoController { } } - String errMsg = "请核对该人员的单位信息"; - if (!CollectionUtils.isEmpty(errorInfos)) { NutMap nutMap = NutMap.NEW(); nutMap.setv("totalCount", memberImportList.size()); nutMap.setv("successCount", successUserList.size()); nutMap.setv("errorCount", errorInfos.size()); - nutMap.setv("errorList", errorInfos.stream().map(v -> { - return NutMap.NEW().addv("工号", v.getLoginName()).addv("姓名", v.getUserName()).addv("性别", v.getSex()).addv("所属工会", v.getUnionName()).addv("所属单位", v.getUnitName()).addv("错误原因", errMsg); - }).collect(Collectors.toList())); + nutMap.setv("errorList", errorInfos); return Result.success(nutMap); } return Result.success(); diff --git a/src/main/resources/views/platform/member/change/Manage.html b/src/main/resources/views/platform/member/change/Manage.html index d1b7152..b5b0c21 100644 --- a/src/main/resources/views/platform/member/change/Manage.html +++ b/src/main/resources/views/platform/member/change/Manage.html @@ -2,10 +2,42 @@ layout("/layouts/platform.html"){ #--> -
+
+
+ + + 全选({{allUsersSelected ? '全部选中' : (someUsersSelected ? '部分选中' : '未选择')}}) + + 已选中 {{checkUsers.length}} 人 +
+ + :before-close="handleClose" size="70%" custom-class="unit-move-drawer"> 选择新单位 - + - - + + height="100%"> - + @@ -612,11 +656,13 @@ layout("/layouts/platform.html"){ }] }, checkUsers: [], + selectAllLoading: false, batchEditVisible: false, batchEditLoading: false, batchFormData: {}, unitMoveVisibile: false, + unitMoveLoading: false, unitMoveUnions: [], unitMoveUnits: [], unitMoveFormData: { @@ -670,6 +716,25 @@ layout("/layouts/platform.html"){ selectUserLoading: false, } }, + computed: { + allUsersSelected() { + return this.pageForm.totalCount > 0 && this.checkUsers.length === this.pageForm.totalCount + }, + someUsersSelected() { + return this.checkUsers.length > 0 && !this.allUsersSelected + }, + selectionFilters() { + const {pageNumber, pageSize, totalCount, pageOrderName, pageOrderBy, ...filters} = this.pageForm + return JSON.stringify(filters) + } + }, + watch: { + selectionFilters() { + if (this.$refs.table) { + this.$refs.table.clearSelection() + } + } + }, components: { 'guava': httpVueLoader('/components/plugins/Guava.vue'), 'member': httpVueLoader('/components/member/MemberInfo.vue?v=1.0.3'), @@ -772,6 +837,9 @@ layout("/layouts/platform.html"){ } }, async doUnitMove() { + if (this.unitMoveLoading) { + return + } if (this.unitMoveFormData.unitId === '') { this.notifyWarning('请选择新单位!') return @@ -787,14 +855,22 @@ layout("/layouts/platform.html"){ userId: this.checkUsers.map(v => v.id) } - const resp = await $.post(loc() + '/userUnitMove', params) - if (resp.code === 0) { - this.pageData() - this.getNumData() - this.$refs.table.clearSelection(); - this.unitMoveVisibile = false - } else { - this.notifyWarning(resp.msg) + this.unitMoveLoading = true + try { + const resp = await $.post(loc() + '/userUnitMove', params) + if (resp.code === 0) { + this.pageData() + this.getNumData() + this.$refs.table.clearSelection(); + this.unitMoveVisibile = false + this.notifySuccess('迁移完成') + } else { + this.notifyWarning(resp.msg) + } + } catch (e) { + this.notifyWarning('请求异常,无法确认迁移结果') + } finally { + this.unitMoveLoading = false } }, changeDateRangeChange(val) { @@ -834,6 +910,41 @@ layout("/layouts/platform.html"){ this.batchFormData = {} this.batchEditVisible = true }, + changeAllUsersSelection(checked) { + if (checked) { + this.selectAllUsers() + } else { + this.$refs.table.clearSelection() + } + }, + async selectAllUsers() { + if (this.selectAllLoading) { + return + } + this.selectAllLoading = true + const snapshot = this.selectionFilters + try { + const resp = await $.post(loc() + '/selectAllUsers', JSON.parse(snapshot)) + if (resp.code !== 0) { + this.notifyWarning(resp.msg || '全部勾选失败') + return + } + if (snapshot !== this.selectionFilters) { + this.notifyWarning('查询条件已变化,请重新全选') + return + } + const currentRows = new Map(this.tableData.map(v => [v.id, v])) + const selectedUsers = new Map(resp.data.map(v => [v.id, currentRows.get(v.id) || v])) + this.pageForm.totalCount = selectedUsers.size + this.$refs.table.clearSelection() + selectedUsers.forEach(v => this.$refs.table.toggleRowSelection(v, true)) + this.notifySuccess('已勾选 ' + selectedUsers.size + ' 人') + } catch (e) { + this.notifyWarning('全部勾选失败,请稍后重试') + } finally { + this.selectAllLoading = false + } + }, tableHandleSelectionChange(val) { this.checkUsers = val; },