From 8bd5c01c262fc02e3544efab95591bcce8237ed7 Mon Sep 17 00:00:00 2001 From: zhangrui Date: Thu, 23 Apr 2026 17:38:05 +0800 Subject: [PATCH] =?UTF-8?q?bug=E6=95=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/controller/EduCoursesController.java | 7 +- .../edu/h5controller/H5EduController.java | 25 +---- .../edu/service/EduStudyRecordsService.java | 15 +++ .../impl/EduStudyRecordsServiceImpl.java | 65 +++++++++++++ .../qsv/h5controller/H5QsvQuizController.java | 35 ++++--- .../info/MemberInfoInputController.java | 57 ++++++------ .../member/models/MemberChangeRecord.java | 5 + .../member/service/MemberInfoService.java | 17 ++++ .../service/impl/MemberInfoServiceImpl.java | 92 +++++++++++++++++++ .../service/impl/MemberManageServiceImpl.java | 4 +- .../dayofficework/qsv/activity/basicForm.js | 4 +- .../dayofficework/qsv/activity/subjectForm.js | 74 ++++++++++++++- .../zhgh/dayofficework/qsv/survey/answer.js | 2 +- .../member/change/common/memberChange.js | 20 +++- .../member/change/manage/index.html | 1 - .../member/info/common/memberAddForm.js | 66 ++++++++----- .../staffmanage/member/info/input/index.html | 15 ++- .../zhghh5/dayofficework/qsv/quiz/index.html | 8 ++ 18 files changed, 412 insertions(+), 100 deletions(-) diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java index 83b05cbd..232d826d 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java @@ -12,6 +12,7 @@ import com.budwk.app.zhgh.dayofficework.edu.models.EduCourses; import com.budwk.app.zhgh.dayofficework.edu.models.EduStudyRecords; import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos; import com.budwk.app.zhgh.dayofficework.edu.service.EduCoursesService; +import com.budwk.app.zhgh.dayofficework.edu.service.EduStudyRecordsService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.nutz.dao.Cnd; @@ -35,6 +36,8 @@ public class EduCoursesController { private Dao dao; @Inject private EduCoursesService eduCoursesService; + @Inject + private EduStudyRecordsService eduStudyRecordsService; @At("/courses") @Ok("beetl:/platform/zhgh/dayofficework/edu/courses/index.html") @@ -81,7 +84,7 @@ public class EduCoursesController { dao.execute(Sqls.create("delete from edu_study_records where courseId=\'" + id + "\'")); //理论学习视频表 dao.execute(Sqls.create("delete from edu_videos " + - "where courseId in (select id from from edu_chapters where courseId=\'" + id + "\')")); + "where chapterId in (select id from edu_chapters where courseId=\'" + id + "\')")); //理论学习视频章节表 dao.execute(Sqls.create("delete from edu_chapters where courseId=\'" + id + "\'")); //理论学习课程表 @@ -171,6 +174,8 @@ public class EduCoursesController { @ApiOperation("删除") @SLog(tag = "理论学习课程", msg = "删除课程视频,id:${args[0]}") public Result deleteVideo(@Param("id") String id) { + // 删除视频时同步清理学习记录,避免已删除视频继续影响学习进度。 + eduStudyRecordsService.deleteStudyRecordsByVideoId(id); dao.delete(EduVideos.class, id); return Result.success(); } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java index 7087e89b..81ec6c97 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java @@ -114,29 +114,8 @@ public class H5EduController { return Result.error("用户未登录"); } - // 获取课程总视频数 - List chapters = dao.query(EduChapters.class, Cnd.where(EduChapters::getCourseId, "=", courseId)); - List chapterIds = chapters.stream().map(EduChapters::getId).toList(); - int totalVideos = dao.count(EduVideos.class, Cnd.where(EduVideos::getChapterId, "in", chapterIds)); - - // 获取已完成的视频ID列表 - List completedRecords = dao.query(EduStudyRecords.class, - Cnd.where(EduStudyRecords::getUserId, "=", userId) - .and(EduStudyRecords::getCourseId, "=", courseId) - .and(EduStudyRecords::getIsCompleted, "=", 1)); - - List completedVideoIds = completedRecords.stream() - .map(EduStudyRecords::getVideoId) - .collect(java.util.stream.Collectors.toList()); - - int completedVideos = completedVideoIds.size(); - - java.util.Map progressData = new java.util.HashMap<>(); - progressData.put("totalVideos", totalVideos); - progressData.put("completedVideos", completedVideos); - progressData.put("completedVideoIds", completedVideoIds); - - return Result.success(progressData); + // 进度只按课程当前仍存在的视频统计,删除旧视频后要立即反映到进度条上。 + return Result.success(eduStudyRecordsService.getCurrentCourseProgress(userId, courseId)); } catch (Exception e) { log.error("获取课程进度失败", e); return Result.error("获取课程进度失败"); diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java index f3ff042a..07c45bd0 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java @@ -4,6 +4,7 @@ import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.dayofficework.edu.models.EduStudyRecords; import java.util.List; +import java.util.Map; /** * @ClassName EduStudyRecordsService @@ -54,6 +55,20 @@ public interface EduStudyRecordsService extends BaseService { */ StudyProgressStats getCourseProgressStats(String userId, String courseId); + /** + * 按课程当前仍存在的视频重新计算学习进度,避免已删除视频的历史记录继续参与统计。 + * @param userId 用户ID + * @param courseId 课程ID + * @return 当前课程学习进度数据 + */ + Map getCurrentCourseProgress(String userId, String courseId); + + /** + * 删除视频时同步清理该视频的学习记录,避免历史脏数据影响后续进度统计。 + * @param videoId 视频ID + */ + void deleteStudyRecordsByVideoId(String videoId); + /** * 学习进度统计信息 */ diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java index 1c86c7a7..6cf9e585 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java @@ -2,6 +2,7 @@ package com.budwk.app.zhgh.dayofficework.edu.service.impl; import com.budwk.app.base.exception.BaseException; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters; import com.budwk.app.zhgh.dayofficework.edu.models.EduStudyRecords; import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos; import com.budwk.app.zhgh.dayofficework.edu.service.EduStudyRecordsService; @@ -12,8 +13,12 @@ import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.IocBean; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @ClassName EduStudyRecordsServiceImpl @@ -195,4 +200,64 @@ public class EduStudyRecordsServiceImpl extends BaseServiceImpl return new StudyProgressStats(0, 0, 0, 0); } } + + @Override + public Map getCurrentCourseProgress(String userId, String courseId) { + try { + List chapters = dao().query(EduChapters.class, + Cnd.where(EduChapters::getCourseId, "=", courseId)); + List chapterIds = chapters.stream().map(EduChapters::getId).collect(Collectors.toList()); + Map progressData = new HashMap<>(); + + if (chapterIds.isEmpty()) { + progressData.put("totalVideos", 0); + progressData.put("completedVideos", 0); + progressData.put("completedVideoIds", Collections.emptyList()); + return progressData; + } + + List currentVideos = dao().query(EduVideos.class, + Cnd.where(EduVideos::getChapterId, "in", chapterIds)); + List currentVideoIds = currentVideos.stream().map(EduVideos::getId).collect(Collectors.toList()); + if (currentVideoIds.isEmpty()) { + progressData.put("totalVideos", 0); + progressData.put("completedVideos", 0); + progressData.put("completedVideoIds", Collections.emptyList()); + return progressData; + } + + // 只统计当前课程仍存在的视频,避免已删除视频的学习记录继续影响进度条。 + List completedRecords = dao().query(EduStudyRecords.class, + Cnd.where(EduStudyRecords::getUserId, "=", userId) + .and(EduStudyRecords::getCourseId, "=", courseId) + .and(EduStudyRecords::getIsCompleted, "=", 1) + .and(EduStudyRecords::getVideoId, "in", currentVideoIds)); + List completedVideoIds = completedRecords.stream() + .map(EduStudyRecords::getVideoId) + .distinct() + .collect(Collectors.toList()); + + progressData.put("totalVideos", currentVideoIds.size()); + progressData.put("completedVideos", completedVideoIds.size()); + progressData.put("completedVideoIds", completedVideoIds); + return progressData; + } catch (Exception e) { + log.error("按当前课程视频计算学习进度失败", e); + Map progressData = new HashMap<>(); + progressData.put("totalVideos", 0); + progressData.put("completedVideos", 0); + progressData.put("completedVideoIds", Collections.emptyList()); + return progressData; + } + } + + @Override + public void deleteStudyRecordsByVideoId(String videoId) { + try { + dao().clear(EduStudyRecords.class, Cnd.where(EduStudyRecords::getVideoId, "=", videoId)); + } catch (Exception e) { + log.error("删除视频学习记录失败, videoId={}", videoId, e); + throw new BaseException("删除视频学习记录失败", e); + } + } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvQuizController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvQuizController.java index ebe56109..b2e1635d 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvQuizController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvQuizController.java @@ -1,6 +1,7 @@ package com.budwk.app.zhgh.dayofficework.qsv.h5controller; import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -102,7 +103,7 @@ public class H5QsvQuizController { List subjectIds = lastRecordOptional.get().getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = lastRecordOptional.get().getId(); } else { @@ -114,7 +115,7 @@ public class H5QsvQuizController { List subjectIds = answerRecord.getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); } } else { @@ -143,7 +144,7 @@ public class H5QsvQuizController { List subjectIds = answerRecord.getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); } } else { @@ -169,7 +170,7 @@ public class H5QsvQuizController { } Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); repeatTips = true; } else { @@ -179,7 +180,7 @@ public class H5QsvQuizController { List subjectIds = maxAnswerRecordOptional.get().getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = maxAnswerRecordOptional.get().getId(); } else { @@ -192,7 +193,7 @@ public class H5QsvQuizController { List subjectIds = maxAnswerRecordOptional.get().getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = maxAnswerRecordOptional.get().getId(); } else { @@ -206,7 +207,7 @@ public class H5QsvQuizController { List subjectIds = notFinishRecordOptional.get().getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = notFinishRecordOptional.get().getId(); } else { @@ -244,7 +245,7 @@ public class H5QsvQuizController { List subjectIds = maxAnswerRecordOptional.get().getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); answerRecordId = maxAnswerRecordOptional.get().getId(); } else { @@ -280,7 +281,7 @@ public class H5QsvQuizController { List subjectIds = answerRecord.getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); } else { //今天最大那次的记录 @@ -291,7 +292,7 @@ public class H5QsvQuizController { List subjectIds = maxTodayRecord.get().getSubjectIds(); Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); } else { throw new RuntimeException("业务异常"); @@ -305,9 +306,12 @@ public class H5QsvQuizController { answerRecordId = answerRecord.getId(); List subjectIds = answerRecord.getSubjectIds(); + if(CollectionUtil.isEmpty(subjectIds)){ + throw new RuntimeException("题目列表为空!请检查答题显示日期"); + } Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); resultSubjects = dao.query(QsvSubject.class, cnd); } } @@ -340,6 +344,13 @@ public class H5QsvQuizController { float totalScore = 0; for (QsvAnswerParam.Subject subject : qsvAnswerParam.getSubjects()) { + QsvSubject dbSubject = dao.fetch(QsvSubject.class, subject.getId()); + if (ObjectUtil.isNotEmpty(dbSubject) && "checkbox".equals(dbSubject.getType()) + && ObjectUtil.isNotEmpty(dbSubject.getMaxMulti()) && dbSubject.getMaxMulti() > 0 + && CollectionUtil.size(subject.getUserSelectOptionIds()) > dbSubject.getMaxMulti()) { + // 后端兜底校验最大可选数,避免绕过前端直接提交超限答案。 + return Result.error("题目【" + dbSubject.getTitle() + "】最多只能选择" + dbSubject.getMaxMulti() + "项"); + } JSONObject entries = extJson.get(subject.getId(), JSONObject.class); if (ObjectUtil.isNotEmpty(entries)) { entries.set("optionIds", subject.getUserSelectOptionIds()); @@ -384,7 +395,7 @@ public class H5QsvQuizController { Cnd cnd = Cnd.where("id", "in", subjectIds); String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(",")); - cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")")); + cnd.orderBy("sortNum","asc"); List subjects = dao.query(QsvSubject.class, cnd); dao.fetchLinks(subjects, "options", Cnd.NEW().asc("sortNum")); diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoInputController.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoInputController.java index c8fad38e..d856e161 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoInputController.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/controller/info/MemberInfoInputController.java @@ -1,20 +1,15 @@ package com.budwk.app.zhgh.staffmanage.member.controller.info; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.util.ObjectUtil; import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.constant.RoleConstant; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.result.Result; -import com.budwk.app.base.utils.CommonDownloadUtil; import com.budwk.app.sys.models.Sys_role; -import com.budwk.app.sys.models.Sys_union; import com.budwk.app.sys.models.Sys_user; -import com.budwk.app.sys.models.Sys_user_role; import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord; import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberInfoPageForm; import com.budwk.app.zhgh.staffmanage.member.service.MemberInfoService; -import org.apache.poi.ss.usermodel.Workbook; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Cnd; import org.nutz.dao.Sqls; @@ -22,27 +17,13 @@ import org.nutz.dao.sql.Sql; 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.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; import org.nutz.mvc.annotation.POST; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.BufferedOutputStream; -import java.net.URLEncoder; -import java.util.List; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - /** - * @version 1.0 - * @Author hqw - * @name:MemberInfoInputController - * @Date 2026/4/8 19:31 - * @注释 人员补录 + * 人员补录 */ @At("/platform/member/info/input") @Ok("json:full") @@ -58,7 +39,6 @@ public class MemberInfoInputController { public void index() { } - @At @SaCheckPermission("member.info.input") public Result pageData(MemberInfoPageForm pageForm) { @@ -74,30 +54,53 @@ public class MemberInfoInputController { @SLog(tag = "会员信息录入", type = "add", msg = "新增会员") public Result add(Sys_user user, String unionId, String unitId) { try { - memberInfoService.addMember(user,unionId,unitId); + memberInfoService.addMember(user, unionId, unitId); return Result.success("新增成功"); } catch (Exception e) { return Result.error(e.getMessage()); } } + @At + @SaCheckPermission("member.info.input") + public Result findOne(@Param("recordId") String recordId, @Param("userId") String userId) { + try { + return Result.success(memberInfoService.getMemberInputDetail(recordId, userId)); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + @At @POST @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("member.info.input") - @SLog(tag = "人员补录", msg = "删除会员") + @SLog(tag = "人员补录", type = "update", msg = "编辑补录人员") + public Result update(Sys_user user, String unionId, String unitId, String recordId) { + try { + memberInfoService.updateMemberInput(user, unionId, unitId, recordId); + return Result.success("编辑成功"); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @At + @POST + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("member.info.input") + @SLog(tag = "人员补录", msg = "删除会员") public Result doDelete(String id, String userId) { try { memberInfoService.dao().delete(MemberChangeRecord.class, id); Sys_role memberRole = memberInfoService.dao().fetch(Sys_role.class, Cnd.where("code", "=", RoleConstant.MEMBER.name())); Sys_role publicRole = memberInfoService.dao().fetch(Sys_role.class, Cnd.where("code", "=", RoleConstant.PUBLIC.name())); - memberInfoService.dao().execute(Sqls.create("delete from sys_user_role where userId = \'"+userId+"\' and roleId = \'"+publicRole.getId()+"\'")); - memberInfoService.dao().execute(Sqls.create("delete from sys_user_role where userId = \'"+userId+"\' and roleId = \'"+memberRole.getId()+"\'")); + memberInfoService.dao().execute(Sqls.create("delete from sys_user_role where userId = '" + userId + "' and roleId = '" + publicRole.getId() + "'")); + memberInfoService.dao().execute(Sqls.create("delete from sys_user_role where userId = '" + userId + "' and roleId = '" + memberRole.getId() + "'")); memberInfoService.dao().delete(Sys_user.class, userId); return Result.success("删除成功"); } catch (Exception e) { return Result.error(e.getMessage()); } } - } diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java index e04a749f..61a1d8bb 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/models/MemberChangeRecord.java @@ -237,5 +237,10 @@ public class MemberChangeRecord extends BaseModel { @ColDefine(type = ColType.VARCHAR,width = 10) private String aidFundMemberUserType; + @Column + @Comment("入校时间") + @ColDefine(type = ColType.DATE) + private String arrivalAtSchoolDate; + private Boolean edit; } 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 dfe8da2f..ca5de4b7 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 @@ -40,6 +40,23 @@ public interface MemberInfoService extends BaseService { */ void addMember(Sys_user user, String unionId, String unitId); + /** + * 获取人员补录编辑详情 + * @param recordId 补录记录ID + * @param userId 用户ID + * @return 编辑详情 + */ + NutMap getMemberInputDetail(String recordId, String userId); + + /** + * 更新人员补录信息 + * @param user 用户信息 + * @param unionId 工会ID + * @param unitId 单位ID + * @param recordId 补录记录ID + */ + void updateMemberInput(Sys_user user, String unionId, String unitId, String recordId); + /** * 获取会员历史 * @param pageForm 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 3db77b6f..6dd49fdb 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 @@ -268,6 +268,98 @@ public class MemberInfoServiceImpl extends BaseServiceImpl implements } + @Override + public NutMap getMemberInputDetail(String recordId, String userId) { + MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId); + if (ObjectUtil.isEmpty(record)) { + throw new BaseException("补录记录不存在"); + } + Sys_user user = dao().fetch(Sys_user.class, userId); + if (ObjectUtil.isEmpty(user)) { + throw new BaseException("人员信息不存在"); + } + NutMap detail = NutMap.NEW(); + detail.putAll(BeanUtil.beanToMap(user)); + // 编辑页复用新增表单,需要把补录记录中的单位/工会及记录ID一起回填。 + detail.put("recordId", record.getId()); + detail.put("unitId", record.getUnitId()); + detail.put("unitName", record.getUnitName()); + detail.put("unionId", record.getUnionId()); + detail.put("unionName", record.getUnionName()); + return detail; + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void updateMemberInput(Sys_user user, String unionId, String unitId, String recordId) { + if (StrUtil.isBlank(user.getId())) { + throw new BaseException("用户ID不能为空"); + } + if (StrUtil.isBlank(recordId)) { + throw new BaseException("补录记录ID不能为空"); + } + if (StrUtil.isBlank(user.getLoginname())) { + throw new BaseException("工号不能为空"); + } + if (StrUtil.isBlank(user.getUsername())) { + throw new BaseException("姓名不能为空"); + } + Sys_user existUser = dao().fetch(Sys_user.class, Cnd.where("loginname", "=", user.getLoginname()).and("id", "!=", user.getId())); + if (ObjectUtil.isNotEmpty(existUser)) { + throw new BaseException("该工号已存在"); + } + Sys_user oldUser = dao().fetch(Sys_user.class, user.getId()); + if (ObjectUtil.isEmpty(oldUser)) { + throw new BaseException("人员信息不存在"); + } + user.setCreateAt(oldUser.getCreateAt()); + user.setLoginCount(oldUser.getLoginCount()); + user.setDisabled(false); + if (user.getMember() == null) { + user.setMember(oldUser.getMember()); + } + if (user.getWelfareMember() == null) { + user.setWelfareMember(oldUser.getWelfareMember()); + } + dao().updateIgnoreNull(user); + + MemberChangeRecord record = dao().fetch(MemberChangeRecord.class, recordId); + if (ObjectUtil.isEmpty(record)) { + throw new BaseException("补录记录不存在"); + } + Sys_unit unit = dao().fetch(Sys_unit.class, Cnd.where("id", "=", unitId)); + Sys_union union = dao().fetch(Sys_union.class, Cnd.where("id", "=", unionId)); + // 补录列表展示来源于变更记录,编辑时同步更新记录内容,保证列表和详情一致。 + record.setLoginname(user.getLoginname()); + record.setUsername(user.getUsername()); + record.setUnitId(unitId); + record.setUnitName(ObjectUtil.isNotEmpty(unit) ? unit.getName() : ""); + record.setUnionId(unionId); + record.setUnionName(ObjectUtil.isNotEmpty(union) ? union.getName() : ""); + record.setSex(user.getSex()); + record.setBirthday(user.getBirthday()); + record.setIdCard(user.getIdCard()); + record.setNation(user.getNation()); + record.setPolitical(user.getPolitical()); + record.setEducation(user.getEducation()); + record.setAcademicDegree(user.getAcademicDegree()); + record.setPosition(user.getProfessionalTitle()); + record.setUserState(user.getUserState()); + record.setPreparedBy(user.getPreparedBy()); + record.setPersonType(user.getPersonType()); + record.setMobile(user.getMobile()); + record.setEmail(user.getEmail()); + record.setMember(user.getMember()); + record.setWelfareMember(user.getWelfareMember()); + record.setRetireDate(user.getRetireDate()); + record.setFamilies(user.getFamilies()); + record.setPersonalData(user.getPersonalData()); + record.setUserAttribute(user.getUserAttribute()); + record.setCampus(user.getCampus()); + record.setProfessionalTitle(user.getProfessionalTitle()); + record.setAidFundMemberUserType(user.getAidFundMemberUserType()); + dao().updateIgnoreNull(record); + } @Override public Sql getMemberHistorySql(MemberInfoPageForm pageForm) { diff --git a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java index 7c6de756..b83a7b43 100644 --- a/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/staffmanage/member/service/impl/MemberManageServiceImpl.java @@ -95,7 +95,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl implement u.isModelWorker, u.userAttribute, u.aidFundMemberUserType, - u.arrivalAtSchooDate, + u.arrivalAtSchoolDate, his.id hisId, his.changeTypes, his.changeTime @@ -221,10 +221,12 @@ public class MemberManageServiceImpl extends BaseServiceImpl implement allowChangeFieldNames.add("member"); allowChangeFieldNames.add("aidFundMemberUserType"); allowChangeFieldNames.add("userAttribute"); + allowChangeFieldNames.add("arrivalAtSchoolDate"); Map dictMap = dictList.stream().collect(Collectors.toMap(Sys_dict::getCode, Sys_dict::getName)); dictMap.put("member", "会员状态"); dictMap.put("aidFundMemberUserType", "人员分类"); dictMap.put("userAttribute", "人员属性"); + dictMap.put("arrivalAtSchoolDate", "入校时间"); return NutMap.NEW().addv("allowChangeFieldNames", allowChangeFieldNames).addv("dictMap", dictMap); } diff --git a/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/basicForm.js b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/basicForm.js index d19f6c00..86a9eec5 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/basicForm.js +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/basicForm.js @@ -228,7 +228,9 @@ const basicForm = { } }) } else { - this.formData = {} + this.formData = { + category: 'QUIZ' + } } }, onSubmit() { diff --git a/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/subjectForm.js b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/subjectForm.js index 1c22aaf7..26302d27 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/subjectForm.js +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/activity/subjectForm.js @@ -91,7 +91,7 @@ const subjectForm = {
+ :placeholder="'选项' + (optionIndex + 1)"> @@ -119,7 +119,8 @@ const subjectForm = { + active-text="正确答案" + @change="handleCorrectAnswerChange(subject, optionIndex)"> { + if (option) { + this.$set(option, 'isCorrect', false) + } + }) if (subject.type === 'text') { subject.options = [] } @@ -310,7 +317,7 @@ const subjectForm = { addOption(subject) { subject.options.push({ id: this.generateId(), - text: "选项" + subject.options.length + 1, + text: "选项" + (subject.options.length + 1), hint: "", imgUrl: null, isCorrect: false @@ -393,10 +400,67 @@ const subjectForm = { }, + // 单选题切换正确答案时保持只有一个正确选项,避免界面状态与题型规则不一致。 + handleCorrectAnswerChange(subject, optionIndex) { + if (!subject || subject.type !== 'radio') { + return + } + const options = subject.options || [] + const currentOption = options[optionIndex] + if (!currentOption || !currentOption.isCorrect) { + return + } + for (let index = 0; index < options.length; index++) { + if (index !== optionIndex) { + this.$set(options[index], 'isCorrect', false) + } + } + }, + + // 保存前校验选项内容,避免题目存在空选项或缺少正确答案时仍然提交到后端。 + validateSubjectOptions() { + for (let subjectIndex = 0; subjectIndex < this.subjects.length; subjectIndex++) { + const subject = this.subjects[subjectIndex] + if (!subject || subject.type === 'text') { + continue + } + const options = subject.options || [] + if (options.length === 0) { + this.$message.warning('请设置第' + (subjectIndex + 1) + '题的选项') + return false + } + let correctAnswerCount = 0 + for (let optionIndex = 0; optionIndex < options.length; optionIndex++) { + const option = options[optionIndex] + const optionText = option && option.text ? option.text.trim() : '' + if (!optionText) { + this.$message.warning('第' + (subjectIndex + 1) + '题的第' + (optionIndex + 1) + '个选项不能为空') + return false + } + if (option && option.isCorrect) { + correctAnswerCount++ + } + } + if (this.activity.category === 'QUIZ') { + if (subject.type === 'radio' && correctAnswerCount > 1) { + this.$message.warning('第' + (subjectIndex + 1) + '题为单选题,只能设置一个正确答案') + return false + } + if (correctAnswerCount === 0) { + this.$message.warning('第' + (subjectIndex + 1) + '题请至少设置一个正确答案') + return false + } + } + } + return true + }, + //保存 saveQuestionnaire() { - $ - .post("/platform/qsv/activity/saveSubjects", { + if (!this.validateSubjectOptions()) { + return + } + $.post("/platform/qsv/activity/saveSubjects", { activityId: this.id, subjects: JSON.stringify(this.subjects) }) diff --git a/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/answer.js b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/answer.js index 90f0ef49..faad0d66 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/answer.js +++ b/src/main/resources/views/platform/zhgh/dayofficework/qsv/survey/answer.js @@ -53,7 +53,7 @@ const answer = { $.post("/platform/qsv/survey/deleteUserAnswer", { id }).then((res) => { if (res.code === 0) { this.$message.success(res.msg) - this.list() + this.pageData()() } }) }) diff --git a/src/main/resources/views/platform/zhgh/staffmanage/member/change/common/memberChange.js b/src/main/resources/views/platform/zhgh/staffmanage/member/change/common/memberChange.js index 7c9a1634..2c98de84 100644 --- a/src/main/resources/views/platform/zhgh/staffmanage/member/change/common/memberChange.js +++ b/src/main/resources/views/platform/zhgh/staffmanage/member/change/common/memberChange.js @@ -189,7 +189,7 @@ const MEMBER_CHANGE = { - + 会员 @@ -198,7 +198,7 @@ const MEMBER_CHANGE = { - + 福利会员 @@ -206,7 +206,17 @@ const MEMBER_CHANGE = { - + + + + + + +