diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java index acccf91e..21fc4690 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpManageController.java @@ -10,6 +10,7 @@ import com.budwk.app.flow.entity.ProcessInstance; import com.budwk.app.flow.enums.ProcessInstanceStateEnum; import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.models.Sys_unit; import com.budwk.app.zhgh.activity.trainSignUp.models.*; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; import com.budwk.app.zhgh.club.model.SysClub; @@ -206,14 +207,14 @@ public class TrainSignUpManageController { @Ok("json:full") @ApiOperation("查询分工会和协会") @SaCheckPermission("trainSignUp.manage") - public Result selectUnionAndClub() { + public Result selectUnitAndClub() { List result = new ArrayList<>(); - List unionList = dao.query(Sys_union.class, Cnd.NEW().asc(Sys_union::getUnionCode)); - for (Sys_union union : unionList) { + List unitList = dao.query(Sys_unit.class, Cnd.NEW().asc(Sys_unit::getUnitcode)); + for (Sys_unit unit : unitList) { NutMap map = new NutMap(); - map.put("id", union.getId()); - map.put("name", union.getName()); - map.put("type", "union"); + map.put("id", unit.getId()); + map.put("name", unit.getName()); + map.put("type", "unit"); result.add(map); } List clubList = dao.query(SysClub.class, Cnd.NEW().asc(SysClub::getClubCode)); diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainsignUpMineController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainsignUpMineController.java index 817fe419..fdf4d90b 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainsignUpMineController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainsignUpMineController.java @@ -65,12 +65,18 @@ public class TrainsignUpMineController { public void h5Index() { } + @At("/scan") + @SaCheckPermission("h5.trainSignUp.mine") + @Ok("beetl:/platform/zhghh5/activity/trainSignUp/scan/index.html") + public void scan() { + } + @At @ApiOperation("主动扫码签到") @Aop(TransAop.READ_COMMITTED) @SaCheckPermission(value = {"trainSignUp.mine", "h5.trainSignUp.mine"}, mode = SaMode.OR) @SLog(tag = "品牌活动-活动签到", msg = "主动扫码签到") - public Result drivingScan(String courseId) { + public Result drivingScan(String courseId, Double lat, Double lng) { // 主动扫码签到是用户自己打开扫一扫,扫二维码签到 int count = dao.count(TrainSignUpUserCourse.class, Cnd.where("courseId", "=", courseId).and("userId", "=", SecurityUtil.getUserId())); @@ -79,7 +85,9 @@ public class TrainsignUpMineController { } TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId); + List coordinates = course.getCourseLocationCoordinates(); int minute = course.getSignUnit() != null ? course.getSignUnit() : 0; + int radius = course.getRadius() != null ? course.getRadius() : 100; boolean flag = true; // 获取现在的日期,并根据设置的数据 @@ -96,9 +104,16 @@ public class TrainsignUpMineController { if(flag) { return Result.error(99, "未到签到时间"); } + + double distance = DistanceUtils.getDistance(coordinates.get(0), coordinates.get(1), lat, lng); + if(distance > radius) { + int result = BigDecimal.valueOf(distance).setScale(0, RoundingMode.HALF_UP).intValue(); + return Result.error(99, "签到失败,您距离签到点还有%s米".formatted(result)); + } + dao.update(timeList); - return Result.success(); + return Result.success("签到成功"); } @At @@ -138,15 +153,23 @@ public class TrainsignUpMineController { public Result positionSign(String courseId, String timeId, Double lat, Double lng) { TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId); List coordinates = course.getCourseLocationCoordinates(); - double distance = DistanceUtils.getDistance(coordinates.get(0), coordinates.get(1), lat, lng); - + int minute = course.getSignUnit() != null ? course.getSignUnit() : 0; int radius = course.getRadius() != null ? course.getRadius() : 100; + + TrainSignUpUserCourse userCourse = dao.fetch(TrainSignUpUserCourse.class, timeId); + + DateTime startTime = DateUtil.offsetMinute(userCourse.getCourseStartTime(), -minute); + DateTime endTime = DateUtil.offsetMinute(userCourse.getCourseEndTime(), minute); + if(!DateUtil.isIn(DateUtil.date(), startTime, endTime)) { + return Result.error(99, "未到签到时间"); + } + + double distance = DistanceUtils.getDistance(coordinates.get(0), coordinates.get(1), lat, lng); if(distance > radius) { int result = BigDecimal.valueOf(distance).setScale(0, RoundingMode.HALF_UP).intValue(); return Result.error(99, "签到失败,您距离签到点还有%s米".formatted(result)); } - TrainSignUpUserCourse userCourse = dao.fetch(TrainSignUpUserCourse.class, timeId); userCourse.setAttend(true); userCourse.setAttendTime(DateUtil.date()); dao.update(userCourse); @@ -193,4 +216,11 @@ public class TrainsignUpMineController { List listMap = activityService.listMap(sql); return Result.success(listMap); } + + @At + @SaCheckPermission(value = {"trainSignUp.mine", "h5.trainSignUp.mine"}, mode = SaMode.OR) + public Result fetchCourse(String courseId) { + TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId); + return Result.success(course); + } } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java index d2e72ef6..008447b4 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java @@ -14,6 +14,7 @@ import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsServic import com.budwk.app.zhgh.activity.trainSignUp.models.*; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityStatisticsService; +import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.nutz.aop.interceptor.async.Async; import org.nutz.aop.interceptor.ioc.TransAop; @@ -29,10 +30,7 @@ import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -80,72 +78,28 @@ public class TrainSignUpActivityServiceImpl extends BaseServiceImpl typeLimits = activity.getTypeLimits(); - typeLimits.forEach(v -> v.setActivityId(activity.getId())); - if(Lang.isNotEmpty(typeLimits)) { + if (Lang.isNotEmpty(typeLimits)) { + typeLimits.forEach(limit -> limit.setActivityId(activity.getId())); insertOrUpdate(typeLimits); } - + // 3. 处理课程列表 List courseList = activity.getCourseList(); - courseList.forEach(v -> { - v.setActivityId(activity.getId()); - dao().insertOrUpdate(v); - if (Lang.isNotEmpty(v.getCourseTimeList())) { - this.setCourseTimeAndInsert(v); + if (Lang.isEmpty(courseList)) { + return; + } + for (TrainSignUpCourse course : courseList) { + course.setActivityId(activity.getId()); + dao().insertOrUpdate(course); + + if (Lang.isNotEmpty(course.getCourseTimeList())) { + handleCourseTimes(activity, course); } - }); - - //查询原来的活动 - List oldCourseList = dao().query(TrainSignUpCourse.class, Cnd.where("activityId", "=", activity.getId())); - //原来的培训班id - List oldCourseIdList = oldCourseList.stream().map(TrainSignUpCourse::getId).toList(); - - //原来的上课时间 - List oldActCourseTimeList = dao().query(TrainSignUpActivityCourse.class, Cnd.where("activityId", "=", activity.getId())); - - //现在的上课时间 - List nowCourseTimeListId = new ArrayList<>(); - activity.getCourseList().forEach(v -> { - if (v.getCourseTimeList() != null) { - nowCourseTimeListId.addAll(v.getCourseTimeList().stream().map(TrainSignUpActivityCourse::getId).toList()); - } - }); - - List deleteCourseTimeListId = oldActCourseTimeList.stream().map(TrainSignUpActivityCourse::getId).filter(id -> !nowCourseTimeListId.contains(id)).collect(Collectors.toList()); - List courseIdList = courseList.stream().map(TrainSignUpCourse::getId).collect(Collectors.toList()); - - //删除关联的培训班 - List deleteIdList = oldCourseIdList.stream().filter(v -> !courseIdList.contains(v)).collect(Collectors.toList()); - dao().clear(TrainSignUpCourse.class, Cnd.where("id", "in", deleteIdList)); - - dao().clear(TrainSignUpActivityCourse.class, Cnd.where("id", "in", deleteCourseTimeListId)); - dao().clear(TrainSignUpUser.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); - dao().clear(TrainSignUpUserCourse.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); - - //查询修改过培训时间的记录 - Sql tsuucSql = Sqls.create(""" - SELECT - tsuuc.id, - tsuac.courseStartTime, - tsuac.courseEndTime - FROM - `train_sign_up_user_course` tsuuc - LEFT JOIN train_sign_up_activity_course tsuac ON tsuac.id = tsuuc.activityCourseId - where tsuuc.courseStartTime != tsuac.courseStartTime or tsuuc.courseEndTime != tsuac.courseEndTime - """); - List tsuucList = listMap(tsuucSql); - tsuucList.forEach(v -> { - Chain chain = Chain.make("courseStartTime", v.getTime("courseStartTime")); - chain.add("courseEndTime", v.getTime("courseEndTime")); - Cnd cnd = Cnd.where("id", "=", v.getString("id")); - dao().update("train_sign_up_user_course", chain, cnd); - }); - + } + // 4. 同步首页活动 if (!activity.isDisabled()) { Sys_home_activity sysHomeActivity = activity.covertToSysHomeActivity(); dao().insertOrUpdate(sysHomeActivity); @@ -154,6 +108,101 @@ public class TrainSignUpActivityServiceImpl extends BaseServiceImpl newTimeIds = course.getCourseTimeList().stream() + .map(TrainSignUpActivityCourse::getId) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + + List oldAcList = dao().query(TrainSignUpActivityCourse.class, + Cnd.where("courseId", "=", courseId)); + Set oldTimeIds = oldAcList.stream() + .map(TrainSignUpActivityCourse::getId) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + + // 2. 删除已移除的时间段及其关联用户课程 + Set deletedTimeIds = Sets.difference(oldTimeIds, newTimeIds).immutableCopy(); + if (!deletedTimeIds.isEmpty()) { + dao().clear(TrainSignUpActivityCourse.class, Cnd.where("id", "in", deletedTimeIds)); + dao().clear(TrainSignUpUserCourse.class, Cnd.where("activityCourseId", "in", deletedTimeIds)); + } + + // 3. 插入/更新课程时间段(假设 setCourseTimeAndInsert 是插入新时间段) + setCourseTimeAndInsert(course); + + // 4. 批量处理用户课程关联 + // 查询当前课程下的所有用户 + List users = dao().query(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId)); + if (users.isEmpty()) { + return; + } + + // 查询已存在的用户课程记录(按 activityCourseId 分组) + List existingUserCourses = dao().query(TrainSignUpUserCourse.class, + Cnd.where("courseId", "=", courseId)); + Set existingActivityCourseIds = existingUserCourses.stream() + .map(TrainSignUpUserCourse::getActivityCourseId) + .collect(Collectors.toSet()); + + List toUpdate = new ArrayList<>(); + List toInsert = new ArrayList<>(); + + for (TrainSignUpActivityCourse timeSlot : course.getCourseTimeList()) { + String timeId = timeSlot.getId(); + if (StrUtil.isBlank(timeId)) continue; + + if (existingActivityCourseIds.contains(timeId)) { + // 更新时间 + toUpdate.add(buildUserCourseForUpdate(timeId, timeSlot.getCourseStartTime(), timeSlot.getCourseEndTime())); + } else { + // 为每个用户新增记录 + for (TrainSignUpUser user : users) { + toInsert.add(buildNewUserCourse(activityId, courseId, user.getUserId(), timeId, timeSlot)); + } + } + } + + // 批量更新(可根据 DAO 能力合并为 batchUpdate) + for (TrainSignUpUserCourse item : toUpdate) { + dao().update(TrainSignUpUserCourse.class, + Chain.make("courseStartTime", item.getCourseStartTime()) + .add("courseEndTime", item.getCourseEndTime()), + Cnd.where("activityCourseId", "=", item.getActivityCourseId())); + } + + // 批量插入 + if (!toInsert.isEmpty()) { + dao().insert(toInsert); + } + } + + private TrainSignUpUserCourse buildUserCourseForUpdate(String activityCourseId, Date startTime, Date endTime) { + TrainSignUpUserCourse u = new TrainSignUpUserCourse(); + u.setActivityCourseId(activityCourseId); + u.setCourseStartTime(startTime); + u.setCourseEndTime(endTime); + return u; + } + + private TrainSignUpUserCourse buildNewUserCourse(String activityId, String courseId, String userId, + String activityCourseId, TrainSignUpActivityCourse timeSlot) { + TrainSignUpUserCourse u = new TrainSignUpUserCourse(); + u.setActivityId(activityId); + u.setCourseId(courseId); + u.setUserId(userId); + u.setActivityCourseId(activityCourseId); + u.setCourseStartTime(timeSlot.getCourseStartTime()); + u.setCourseEndTime(timeSlot.getCourseEndTime()); + u.setAttend(false); + u.setAttendTime(null); + return u; + } + private void setCourseTimeAndInsert(TrainSignUpCourse course) { course.getCourseTimeList().forEach(courseTime -> { Calendar calendar = Calendar.getInstance(); diff --git a/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/basicForm.js b/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/basicForm.js index 8c74f8cd..26f49ca6 100644 --- a/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/basicForm.js +++ b/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/basicForm.js @@ -591,11 +591,11 @@ const basicForm = { this.activityGroupList = await this.getActivityGroup() this.historicalActList = await this.getHistoricalActList() this.courseTypeList = await this.getAllType() - await this.selectUnionAndClub() + await this.selectUnitAndClub() await this.init(row) }, - async selectUnionAndClub() { - const resp = await this.$axios.post("/platform/trainSignUp/manage/selectUnionAndClub") + async selectUnitAndClub() { + const resp = await this.$axios.post("/platform/trainSignUp/manage/selectUnitAndClub") this.undertakeOptions = resp.data }, }, diff --git a/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/makeQrcode.js b/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/makeQrcode.js index 7617e44a..3416cfa7 100644 --- a/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/makeQrcode.js +++ b/src/main/resources/views/platform/zhgh/activity/trainSignUp/manage/makeQrcode.js @@ -66,7 +66,8 @@ const makeQrcode = { this.courseDialog = true }, makeCourseCode(row) { - const url = '${AppDomain!}/platform/trainSignUp/mine/drivingScan' + //const url = '${AppDomain!}/platform/trainSignUp/mine/drivingScan' + const url = '${AppDomain!}/platform/trainSignUp/mine/scan' const data = url + '?courseId=' + row.id console.log(data) const content = jrQrcode.getQrBase64(data) diff --git a/src/main/resources/views/platform/zhghh5/activity/trainSignUp/common/times.js b/src/main/resources/views/platform/zhghh5/activity/trainSignUp/common/times.js index 6a93c898..60d1dd7e 100644 --- a/src/main/resources/views/platform/zhghh5/activity/trainSignUp/common/times.js +++ b/src/main/resources/views/platform/zhghh5/activity/trainSignUp/common/times.js @@ -122,12 +122,19 @@ const times = { callback(null); return; } + const loading = vant.Toast.loading({ + message: "获取定位中...", + forbidClick: false, + loadingType: "spinner", + duration: 0, + }) navigator.geolocation.getCurrentPosition( (position) => { callback({ lat: position.coords.latitude, lng: position.coords.longitude }); + loading.close() }, (error) => { let msg = '定位失败,请稍后重试'; @@ -144,6 +151,7 @@ const times = { } this.$toast(msg); callback(null); + loading.close() }, { enableHighAccuracy: true, diff --git a/src/main/resources/views/platform/zhghh5/activity/trainSignUp/scan/index.html b/src/main/resources/views/platform/zhghh5/activity/trainSignUp/scan/index.html new file mode 100644 index 00000000..99d79211 --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/activity/trainSignUp/scan/index.html @@ -0,0 +1,170 @@ + + + + +
+ + +
+
+
+ + +
+
+
温馨提醒
+
+
+ +
+
+ + + +