bug整改

This commit is contained in:
2026-04-23 17:38:05 +08:00
parent 473240441f
commit 8bd5c01c26
18 changed files with 412 additions and 100 deletions
@@ -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();
}
@@ -114,29 +114,8 @@ public class H5EduController {
return Result.error("用户未登录");
}
// 获取课程总视频数
List<EduChapters> chapters = dao.query(EduChapters.class, Cnd.where(EduChapters::getCourseId, "=", courseId));
List<String> chapterIds = chapters.stream().map(EduChapters::getId).toList();
int totalVideos = dao.count(EduVideos.class, Cnd.where(EduVideos::getChapterId, "in", chapterIds));
// 获取已完成的视频ID列表
List<EduStudyRecords> completedRecords = dao.query(EduStudyRecords.class,
Cnd.where(EduStudyRecords::getUserId, "=", userId)
.and(EduStudyRecords::getCourseId, "=", courseId)
.and(EduStudyRecords::getIsCompleted, "=", 1));
List<String> completedVideoIds = completedRecords.stream()
.map(EduStudyRecords::getVideoId)
.collect(java.util.stream.Collectors.toList());
int completedVideos = completedVideoIds.size();
java.util.Map<String, Object> 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("获取课程进度失败");
@@ -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<EduStudyRecords> {
*/
StudyProgressStats getCourseProgressStats(String userId, String courseId);
/**
* 按课程当前仍存在的视频重新计算学习进度,避免已删除视频的历史记录继续参与统计。
* @param userId 用户ID
* @param courseId 课程ID
* @return 当前课程学习进度数据
*/
Map<String, Object> getCurrentCourseProgress(String userId, String courseId);
/**
* 删除视频时同步清理该视频的学习记录,避免历史脏数据影响后续进度统计。
* @param videoId 视频ID
*/
void deleteStudyRecordsByVideoId(String videoId);
/**
* 学习进度统计信息
*/
@@ -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<EduStudyRecords>
return new StudyProgressStats(0, 0, 0, 0);
}
}
@Override
public Map<String, Object> getCurrentCourseProgress(String userId, String courseId) {
try {
List<EduChapters> chapters = dao().query(EduChapters.class,
Cnd.where(EduChapters::getCourseId, "=", courseId));
List<String> chapterIds = chapters.stream().map(EduChapters::getId).collect(Collectors.toList());
Map<String, Object> progressData = new HashMap<>();
if (chapterIds.isEmpty()) {
progressData.put("totalVideos", 0);
progressData.put("completedVideos", 0);
progressData.put("completedVideoIds", Collections.emptyList());
return progressData;
}
List<EduVideos> currentVideos = dao().query(EduVideos.class,
Cnd.where(EduVideos::getChapterId, "in", chapterIds));
List<String> 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<EduStudyRecords> completedRecords = dao().query(EduStudyRecords.class,
Cnd.where(EduStudyRecords::getUserId, "=", userId)
.and(EduStudyRecords::getCourseId, "=", courseId)
.and(EduStudyRecords::getIsCompleted, "=", 1)
.and(EduStudyRecords::getVideoId, "in", currentVideoIds));
List<String> 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<String, Object> 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);
}
}
}
@@ -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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<QsvSubject> subjects = dao.query(QsvSubject.class, cnd);
dao.fetchLinks(subjects, "options", Cnd.NEW().asc("sortNum"));
@@ -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
* @nameMemberInfoInputController
* @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());
}
}
}
@@ -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;
}
@@ -40,6 +40,23 @@ public interface MemberInfoService extends BaseService<Sys_user> {
*/
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
@@ -268,6 +268,98 @@ public class MemberInfoServiceImpl extends BaseServiceImpl<Sys_user> 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) {
@@ -95,7 +95,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> 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<Sys_user> implement
allowChangeFieldNames.add("member");
allowChangeFieldNames.add("aidFundMemberUserType");
allowChangeFieldNames.add("userAttribute");
allowChangeFieldNames.add("arrivalAtSchoolDate");
Map<String, String> 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);
}
@@ -228,7 +228,9 @@ const basicForm = {
}
})
} else {
this.formData = {}
this.formData = {
category: 'QUIZ'
}
}
},
onSubmit() {
@@ -91,7 +91,7 @@ const subjectForm = {
<div class="option-content">
<el-input
v-model="option.text"
:placeholder="'选项'+optionIndex + 1">
:placeholder="'选项' + (optionIndex + 1)">
<template slot="prepend">选项{{optionIndex + 1}}</template>
</el-input>
<!-- <el-input-->
@@ -119,7 +119,8 @@ const subjectForm = {
<el-switch
v-if="activity.category==='QUIZ'"
v-model="option.isCorrect"
active-text="正确答案">
active-text="正确答案"
@change="handleCorrectAnswerChange(subject, optionIndex)">
</el-switch>
<el-button
@@ -286,6 +287,12 @@ const subjectForm = {
//题目类型切换
subjectTypeChange(subject, subjectIndex) {
// 切换题型时先清空当前题目的正确答案状态,避免沿用旧题型下的答案配置。
;(subject.options || []).forEach((option) => {
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)
})
@@ -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()()
}
})
})
@@ -189,7 +189,7 @@ const MEMBER_CHANGE = {
<!-- <el-descriptions-item></el-descriptions-item>-->
</template>
<el-descriptions-item label="会员状态" :span="1.5">
<el-descriptions-item label="会员状态" >
<el-form-item prop="member">
<el-radio-group v-model="formData.member" size="small">
<el-radio border :label="true">会员</el-radio>
@@ -198,7 +198,7 @@ const MEMBER_CHANGE = {
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="福利会员状态" :span="1.5">
<el-descriptions-item label="福利会员状态">
<el-form-item prop="welfareMember">
<el-radio-group v-model="formData.welfareMember" size="small">
<el-radio border :label="true">福利会员</el-radio>
@@ -206,7 +206,17 @@ const MEMBER_CHANGE = {
</el-radio-group>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="入校时间">
<el-form-item>
<el-date-picker v-model="formData.arrivalAtSchoolDate"
type="date"
placeholder="请选择入校时间"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<template v-if="formData.loginname == $store.state.user.loginname">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-form-item prop="families">
@@ -457,7 +467,8 @@ const MEMBER_CHANGE = {
mobile,
email,
families,
personalData
personalData,
arrivalAtSchoolDate
} = this.user
this.$set(this.formData, "userId", id)
@@ -488,6 +499,7 @@ const MEMBER_CHANGE = {
this.$set(this.formData, "email", email)
this.$set(this.formData, "families", families ? families : [])
this.$set(this.formData, "personalData", personalData)
this.$set(this.formData, "arrivalAtSchoolDate", arrivalAtSchoolDate)
}
}
},
@@ -570,7 +570,6 @@ layout("/layouts/platform.html"){
{ prop: "arrivalAtSchoolDate", label: "来校时间", width: 120, sortable: true, checked: 0 },
{ prop: "teachingTime", label: "从教年月", width: 120, sortable: true, checked: 0 },
{ prop: "expectedLeaveSchoolDate", label: "预计/最后离校时间", width: 120, sortable: true, checked: 0 },
{ prop: "arrivalAtSchooDate", label: "入校时间", width: 120, sortable: true, checked: 0 },
],
changeTypeData: [],
@@ -255,7 +255,27 @@
"USER_STATE", "USER_PREPARED_BY_TYPE", "USER_PERSON_TYPE", "USER_MARRIAGE","AIDFUND_MEMBER_USER_TYPE","USER_ATTRIBUTE"],
data() {
return {
formData: {
formData: {},
formRules: {
loginname: [{ required: true, message: '请输入工号', trigger: 'blur' }],
username: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
idCard: [{ required: true, message: '请输入身份证号码', trigger: 'blur' }],
mobile: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
unitId: [{ required: true, message: '请选择工作单位', trigger: 'change' }],
unionId: [{ required: true, message: '请选择所属工会', trigger: 'change' }],
userState: [{ required: true, message: '请选择在职状态', trigger: 'change' }]
},
units: [],
unions: [],
submitLoading: false
}
},
methods: {
getDefaultFormData() {
return {
id: '',
recordId: '',
loginname: '',
username: '',
sex: '男',
@@ -282,23 +302,26 @@
specialty: '',
member: false,
welfareMember: false
},
formRules: {
loginname: [{ required: true, message: '请输入工号', trigger: 'blur' }],
username: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
idCard: [{ required: true, message: '请输入身份证号码', trigger: 'blur' }],
mobile: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
unitId: [{ required: true, message: '请选择工作单位', trigger: 'change' }],
unionId: [{ required: true, message: '请选择所属工会', trigger: 'change' }],
userState: [{ required: true, message: '请选择在职状态', trigger: 'change' }]
},
units: [],
unions: [],
submitLoading: false
}
},
methods: {
}
},
onOpen(params) {
this.formData = this.getDefaultFormData()
if (this.$refs.formRef) {
this.$refs.formRef.resetFields()
}
if (params && params.recordId && params.userId) {
// 编辑时回填当前补录记录,继续复用新增表单。
$.post('/platform/member/info/input/findOne', params).then(res => {
if (res.code === 0 && res.data) {
this.formData = Object.assign(this.getDefaultFormData(), res.data)
this.formData.families = this.formData.families || []
}
})
}
this.$nextTick(() => {
this.$refs.formRef && this.$refs.formRef.clearValidate()
})
},
async initUnits() {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.units = await this.$businessTool.listUnit()
@@ -325,10 +348,10 @@
type: "warning"
}).then(() => {
const loading = createLoading()
this.$axios.post('/platform/member/info/input/add', this.formData).then(res => {
const submitUrl = this.formData.recordId ? '/platform/member/info/input/update' : '/platform/member/info/input/add'
this.$axios.post(submitUrl, this.formData).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
commonUtil.pjaxPush("/platform/member/info/input")
}
}).finally(() => {
loading.close()
@@ -338,11 +361,12 @@
},
handleCancel() {
this.$refs.formRef.resetFields()
this.formData.families = []
this.formData = this.getDefaultFormData()
this.$parent.$parent.close()
}
},
created() {
this.formData = this.getDefaultFormData()
this.initUnits()
}
}
@@ -78,9 +78,10 @@ layout("/layouts/platform.html"){
:prop="column.prop"
:sortable="column.sortable"
></el-table-column>
<el-table-column label="操作" width="150px">
<el-table-column label="操作" width="220px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini">查看</el-button>
<el-button @click="openEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button @click="doDelete(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
@@ -111,7 +112,7 @@ layout("/layouts/platform.html"){
data() {
return {
pageForm: {
year: new Date().getFullYear() - 1 + "",
year: new Date().getFullYear() + "",
memberSearchName: "",
memberSearchKeyWord: ""
},
@@ -140,7 +141,15 @@ layout("/layouts/platform.html"){
methods: {
openAdd() {
this.$refs.guava.edit(() => {
// 可以在这里初始化表单数据
this.$refs.memberAddFormRef.onOpen()
})
},
openEdit(row) {
this.$refs.guava.edit(() => {
this.$refs.memberAddFormRef.onOpen({
recordId: row.id,
userId: row.userId
})
})
},
handleAddSuccess() {
@@ -245,6 +245,14 @@ layout("/layouts/platform_h5.html"){
return
}
const selectedOptionIds = subject.userSelectOptionIds || []
const hasSelected = selectedOptionIds.includes(optionId)
// 多选题达到最大可选数量后禁止继续勾选,但允许取消已选项。
if (subject.type === "checkbox" && !hasSelected && subject.maxMulti && subject.maxMulti > 0 && selectedOptionIds.length >= subject.maxMulti) {
this.$toast("本题最多选择" + subject.maxMulti + "项")
return
}
if (subject.type === "radio") {
this.$refs["subject" + subject.id][0].toggleAll(false)
}