diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java index c27bf72..b59e153 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java @@ -134,7 +134,7 @@ public class FamilyActivity extends BaseModel implements Serializable, SysHomeCo private Integer familyCountScope; @Column - @Comment("是否禁止同一教职工报名本活动内时间重叠的子活动,含候补报名") + @Comment("是否禁止同一教职工下同一家属报名本活动内时间重叠的子活动,含候补报名") @ColDefine(type = ColType.BOOLEAN) @Default("0") private Boolean timeConflictCheck; diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java index 1dec796..e68f734 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java @@ -1224,14 +1224,38 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl i } /** - * 在同一活动、同一教职工内校验时间重叠,含候补,修改和调班排除当前报名记录。 - * 参数为本次报名、所属课程、活动配置和实际报名用户ID;无返回值,冲突时提示已有课程和时间。 + * 提取一条报名中的全部家属唯一标识,用于判断两次报名是否包含同一个孩子。 + * user 为当前或历史报名,activity.onlyKey 为管理员配置的统一字段编码;返回规范化后的标识集合。 + * 缺少字段或值为空时提示核对数据,不能将无法识别的历史报名当作不同孩子而跳过冲突校验。 + */ + private Set getTimeConflictFamilyIdentities(FamilyUser user, FamilyActivity activity) { + if (StrUtil.isBlank(activity.getOnlyKey())) { + throw new BaseException("活动未配置家属唯一标识,请联系管理员"); + } + if (Lang.isEmpty(user.getMobileColumnsValue())) { + throw new BaseException("报名记录缺少家属信息,请联系管理员核对历史数据"); + } + Set identities = new HashSet<>(); + for (List family : user.getMobileColumnsValue()) { + String identity = normalizeFamilyIdentityValue(getFamilyIdentity(family, activity)); + if (StrUtil.isBlank(identity)) { + throw new BaseException("报名记录缺少家属唯一标识,请联系管理员核对字段编码和历史数据"); + } + identities.add(identity); + } + return identities; + } + + /** + * 在同一活动、同一教职工下仅校验同一家属的时间重叠,含候补,修改和调班排除当前报名记录。 + * 参数为本次报名、所属课程、活动配置和实际报名用户ID;无返回值,同一家属冲突时提示已有课程和时间。 * 使用半开区间:一场结束时刻等于另一场开始时刻允许报名;不同日期自然不会冲突。 */ private void validateTimeConflict(FamilyUser user, FamilyCourse course, FamilyActivity activity, String userId) { if (!Boolean.TRUE.equals(activity.getTimeConflictCheck())) { return; } + Set currentIdentities = getTimeConflictFamilyIdentities(user, activity); List currentTimes = getSignUpCourseTimes(course, user.getActivityCourseId()); Cnd cnd = Cnd.where(FamilyUser::getActivityId, "=", activity.getId()) .and(FamilyUser::getUserId, "=", userId).and(FamilyUser::getState, "in", List.of(1, 2, 3)); @@ -1239,6 +1263,11 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl i cnd.and(FamilyUser::getId, "!=", user.getId()); } for (FamilyUser existing : dao().query(FamilyUser.class, cnd)) { + Set existingIdentities = getTimeConflictFamilyIdentities(existing, activity); + // 两次报名没有相同孩子时允许同时段报名;多人报名只要有一个相同孩子,仍需检查时间。 + if (Collections.disjoint(currentIdentities, existingIdentities)) { + continue; + } FamilyCourse oldCourse = dao().fetch(FamilyCourse.class, existing.getCourseId()); if (oldCourse == null || !Objects.equals(oldCourse.getActivityId(), activity.getId())) { throw new BaseException("已有报名的子活动不存在或已变更,请联系管理员核对"); @@ -1247,7 +1276,7 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl i for (FamilyActivityCourse currentTime : currentTimes) { if (currentTime.getCourseStartTime().before(oldTime.getCourseEndTime()) && oldTime.getCourseStartTime().before(currentTime.getCourseEndTime())) { - throw new BaseException("您已报名【" + oldCourse.getCourseName() + "】(" + throw new BaseException("同一家属已报名【" + oldCourse.getCourseName() + "】(" + DateUtil.format(oldTime.getCourseStartTime(), "yyyy-MM-dd HH:mm") + "至" + DateUtil.format(oldTime.getCourseEndTime(), "yyyy-MM-dd HH:mm") + "),与当前报名时间重叠,不能兼报"); @@ -1480,8 +1509,9 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl i return Map.of(false, activity.getKeyWord() + "人数最多为" + currentType.getFamilyMaxCount()); } - List typeList = dao().query(FamilyType.class, Cnd.NEW()); - Map typeMap = typeList.stream().collect(Collectors.toMap(FamilyType::getId, FamilyType::getTypeName)); + // 冲突提示显示历史报名对应的具体子活动名称,不使用类型名称或本次尝试报名的名称。 + Map courseNameMap = courseList.stream().collect(Collectors.toMap(FamilyCourse::getId, + course -> StrUtil.isBlank(course.getCourseName()) ? "原子活动" : course.getCourseName())); List> currentValue = user.getMobileColumnsValue(); @@ -1527,13 +1557,16 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl i if(Objects.equals(onlyKeyValue, hisKeyValue)) { oneFamilyCount ++; if(Objects.equals(courseMap.get(user.getCourseId()), courseMap.get(hisRecord.getCourseId()))) { - return Map.of(false, onlyKeyValue + "已经报名" + typeMap.get(courseMap.get(user.getCourseId())) + "分场"); + return Map.of(false, onlyKeyValue + "已经报名“" + courseNameMap.getOrDefault(hisRecord.getCourseId(), "原子活动") + + "”,不能重复报名同时间段"); } if(aa.contains(user.getCourseId()) && bb.contains(hisRecord.getCourseId())) { - return Map.of(false, onlyKeyValue + "已经报名" + typeMap.get(courseMap.get(hisRecord.getCourseId())) + "分场,存在冲突"); + return Map.of(false, onlyKeyValue + "已经报名“" + courseNameMap.getOrDefault(hisRecord.getCourseId(), "原子活动") + + "”,与当前子活动存在冲突"); } if(bb.contains(user.getCourseId()) && aa.contains(hisRecord.getCourseId())) { - return Map.of(false, onlyKeyValue + "已经报名" + typeMap.get(courseMap.get(hisRecord.getCourseId())) + "分场,存在冲突"); + return Map.of(false, onlyKeyValue + "已经报名“" + courseNameMap.getOrDefault(hisRecord.getCourseId(), "原子活动") + + "”,与当前子活动存在冲突"); } } } diff --git a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareAddressManageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareAddressManageServiceImpl.java index d64c279..8098010 100644 --- a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareAddressManageServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareAddressManageServiceImpl.java @@ -43,11 +43,12 @@ public class WelfareAddressManageServiceImpl extends BaseServiceImpl list = listMap(sql); - // 工号按字符串导出,保留前导零;收货地址只包含省市区县和详细地址。 + // 工号按字符串导出,保留前导零;收货地址合并所选地址的收货人、电话及省市区县和详细地址。 List entities = new ArrayList<>(); entities.add(new ExcelExportEntity("工号", "loginname", 20)); entities.add(new ExcelExportEntity("姓名", "username", 20)); diff --git a/src/main/resources/views/platform/zhgh/activity/family/manage/basicForm.js b/src/main/resources/views/platform/zhgh/activity/family/manage/basicForm.js index f6d3284..a1a42ed 100644 --- a/src/main/resources/views/platform/zhgh/activity/family/manage/basicForm.js +++ b/src/main/resources/views/platform/zhgh/activity/family/manage/basicForm.js @@ -127,9 +127,9 @@ const basicForm = { + active-text="禁止同一家属时间重叠报名">
- 按子活动实际日期及起止时间判断,含候补报名。上午与同日全天互斥,上午与下午、不同日期可兼报。 + 按同一教职工下同一家属的子活动实际日期及起止时间判断,含候补报名。同一家属上午与同日全天互斥,上午与下午、不同日期可兼报;不同家属可以报名同时段的不同子活动。
diff --git a/src/main/resources/views/platform/zhgh/activity/family/manage/info.js b/src/main/resources/views/platform/zhgh/activity/family/manage/info.js index 6ff6385..eb74c7a 100644 --- a/src/main/resources/views/platform/zhgh/activity/family/manage/info.js +++ b/src/main/resources/views/platform/zhgh/activity/family/manage/info.js @@ -13,7 +13,7 @@ const info = { {{viewData.activitySignUpEndTime}} {{viewData.familyCountScope === 2 ? '按整个活动累计' : '按子活动类型累计'}} {{viewData.familyMaxCount}} - {{viewData.timeConflictCheck === true ? '是(含候补)' : '否'}} + {{viewData.timeConflictCheck === true ? '是(含候补)' : '否'}} {{viewData.onlyKey}}