From c6c301c53234f2d91b44bb192ac71eb44c29794f Mon Sep 17 00:00:00 2001 From: "hhb@hotmail.com" Date: Fri, 28 Mar 2025 16:13:46 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E6=8A=A5=E5=91=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E6=9B=B4=E6=96=B0=E4=BB=A5=E5=8F=8A=E8=AF=84?= =?UTF-8?q?=E4=BB=B7=E5=BE=97=E6=89=B9=E9=87=8F=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/LaborEducationServiceImpl.java | 12 +- .../impl/MoralEducationServiceImpl.java | 12 +- .../model/dto/Appraise/AppraiseVoteDto.java | 7 +- .../repository/AppraiseRecordRepository.java | 8 +- .../repository/AppraiseRepository.java | 4 +- .../repository/StudentRepository.java | 2 +- .../service/impl/EvaluationServiceImpl.java | 226 +++++++++++------- 7 files changed, 165 insertions(+), 106 deletions(-) diff --git a/src/main/java/cn/teammodel/controller/admin/service/impl/LaborEducationServiceImpl.java b/src/main/java/cn/teammodel/controller/admin/service/impl/LaborEducationServiceImpl.java index 6d32e03..f7797fe 100644 --- a/src/main/java/cn/teammodel/controller/admin/service/impl/LaborEducationServiceImpl.java +++ b/src/main/java/cn/teammodel/controller/admin/service/impl/LaborEducationServiceImpl.java @@ -233,7 +233,7 @@ public class LaborEducationServiceImpl implements LaborEducationService { List res; try { exams = examRepository.findExamByClassId(String.format(PK.EXAM, findDto.getTmdId()), findDto.getClassId(), findDto.getPeriodId(), findDto.getSubjectId()); - res= appraiseRecordRepository.getRecords(String.format(PK.PK_APPRAISE_RECORD, findDto.getCode()),findDto.getAcademicYearId(), findDto.getClassId(), findDto.getStudentId()); + res= appraiseRecordRepository.getRecords(String.format(PK.PK_APPRAISE_RECORD, findDto.getCode()),findDto.getAcademicYearId(), findDto.getClassId(), findDto.getStudentId(),"德育"); resMap.put("exams",exams); resMap.put("res", res); }catch (Exception e){ @@ -1404,6 +1404,7 @@ public Map>> getStudentMonthlyScores(LaborDto la if (laborDto.getClassId() == null) { res = appraiseRecordRepository.getStudentRecords( String.format(PK.PK_APPRAISE_RECORD, schoolId), + laborDto.getAcademicYearId(), laborDto.getStudentId(), laborDto.getStartTime(), laborDto.getEndTime(), @@ -1441,13 +1442,12 @@ public Map>> getStudentMonthlyScores(LaborDto la .findFirst() .map(RGroupList::getName) .orElse("未知班级"); // 如果未找到则返回默认值 "未知班级"*/ - res = appraiseRecordRepository.latestRecords( + res = appraiseRecordRepository.getRecords( String.format(PK.PK_APPRAISE_RECORD, schoolId), laborDto.getAcademicYearId(), - laborDto.getStartTime(), - laborDto.getEndTime(), - "德育", - classIds + laborDto.getClassId(), + laborDto.getStudentId(), + "德育" ); //表扬的次数 rightCount = (int) res.stream().filter(RecordVo::isPraise).count(); diff --git a/src/main/java/cn/teammodel/controller/admin/service/impl/MoralEducationServiceImpl.java b/src/main/java/cn/teammodel/controller/admin/service/impl/MoralEducationServiceImpl.java index 73682f3..3e690ca 100644 --- a/src/main/java/cn/teammodel/controller/admin/service/impl/MoralEducationServiceImpl.java +++ b/src/main/java/cn/teammodel/controller/admin/service/impl/MoralEducationServiceImpl.java @@ -231,7 +231,7 @@ public class MoralEducationServiceImpl implements MoralEducationService { List res; try { exams = examRepository.findExamByClassId(String.format(PK.EXAM, findDto.getTmdId()), findDto.getClassId(), findDto.getPeriodId(), findDto.getSubjectId()); - res= appraiseRecordRepository.getRecords(String.format(PK.PK_APPRAISE_RECORD, findDto.getCode()),findDto.getAcademicYearId(), findDto.getClassId(), findDto.getStudentId()); + res= appraiseRecordRepository.getRecords(String.format(PK.PK_APPRAISE_RECORD, findDto.getCode()),findDto.getAcademicYearId(), findDto.getClassId(), findDto.getStudentId(),"劳育"); resMap.put("exams",exams); resMap.put("res", res); }catch (Exception e){ @@ -1342,6 +1342,7 @@ public class MoralEducationServiceImpl implements MoralEducationService { if (laborDto.getClassId() == null) { res = appraiseRecordRepository.getStudentRecords( String.format(PK.PK_APPRAISE_RECORD, schoolId), + laborDto.getAcademicYearId(), laborDto.getStudentId(), laborDto.getStartTime(), laborDto.getEndTime(), @@ -1379,13 +1380,12 @@ public class MoralEducationServiceImpl implements MoralEducationService { .findFirst() .map(RGroupList::getName) .orElse("未知班级"); // 如果未找到则返回默认值 "未知班级"*/ - res = appraiseRecordRepository.latestRecords( + res = appraiseRecordRepository.getRecords( String.format(PK.PK_APPRAISE_RECORD, schoolId), laborDto.getAcademicYearId(), - laborDto.getStartTime(), - laborDto.getEndTime(), - "劳育", - classIds + laborDto.getClassId(), + laborDto.getStudentId(), + "德育" ); //表扬的次数 rightCount = (int) res.stream().filter(RecordVo::isPraise).count(); diff --git a/src/main/java/cn/teammodel/model/dto/Appraise/AppraiseVoteDto.java b/src/main/java/cn/teammodel/model/dto/Appraise/AppraiseVoteDto.java index 4af0c04..dfd1366 100644 --- a/src/main/java/cn/teammodel/model/dto/Appraise/AppraiseVoteDto.java +++ b/src/main/java/cn/teammodel/model/dto/Appraise/AppraiseVoteDto.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; +import java.util.List; /** * @author winter @@ -13,7 +14,7 @@ import javax.validation.constraints.NotNull; public class AppraiseVoteDto { @NotNull @ApiModelProperty(value = "评价对象 Id") - private String targetId; + private List targetIds; @NotNull @ApiModelProperty(value = "评价对象类型:", allowableValues = "student ,class") @@ -25,11 +26,11 @@ public class AppraiseVoteDto { @ApiModelProperty(value = "是否推送给家长(评价 STUDENT 时生效)") private boolean pushParent; /** - * 可以当作唯一 id + * 可以当作唯一 id集合 */ @NotNull @ApiModelProperty(value = "评价项唯一 id", required = true) - private String appraiseId; + private List appraiseIds; @ApiModelProperty(value = "评价来源") private String device; } diff --git a/src/main/java/cn/teammodel/repository/AppraiseRecordRepository.java b/src/main/java/cn/teammodel/repository/AppraiseRecordRepository.java index 19e5888..4e456d4 100644 --- a/src/main/java/cn/teammodel/repository/AppraiseRecordRepository.java +++ b/src/main/java/cn/teammodel/repository/AppraiseRecordRepository.java @@ -88,21 +88,23 @@ public interface AppraiseRecordRepository extends CosmosRepository= @startTime) and " + "(IS_NULL(@endTime) or n.createTime <= @endTime) and " + "(IS_NULL(@typeName) or array_contains(n.appraiseNode.path ,@typeName)) " ) - List getStudentRecords(String code, String studentId, Long startTime, Long endTime,String typeName); + List getStudentRecords(String code,String academicYearId ,String studentId, Long startTime, Long endTime,String typeName); @Query("select c.id as recordId, c.name as targetName, c.avatar, c.classId,c.className, n.id as recordNodeId, c.targetId, c.targetType, n.creator, n.createTime, n.appraiseNode.name as appraiseName, n.appraiseNode.isPraise, n.device,n.appraiseNode.path from Student as c join n in c.nodes where " + "c.code = @code and " + "c.academicYearId = @academicYearId and " + "c.classId = @classId and " + - "c.targetId = @studentId " + "(IS_NULL(@studentId) or c.targetId = @studentId) and " + + "(IS_NULL(@typeName) or array_contains(n.appraiseNode.path ,@typeName)) " ) - List getRecords(String code, String academicYearId, String classId,String studentId); + List getRecords(String code, String academicYearId, String classId,String studentId,String typeName); @Query("select c.classId as id, count(1) as count from Student as c join n in c.nodes where( " + diff --git a/src/main/java/cn/teammodel/repository/AppraiseRepository.java b/src/main/java/cn/teammodel/repository/AppraiseRepository.java index a674f4c..0f94330 100644 --- a/src/main/java/cn/teammodel/repository/AppraiseRepository.java +++ b/src/main/java/cn/teammodel/repository/AppraiseRepository.java @@ -33,8 +33,8 @@ public interface AppraiseRepository extends CosmosRepository { List findTemplateTree(); @Query("SELECT value n FROM School AS s join n in s.nodes where s.code = @code and n.id = @nodeId and s.periodId = @periodId") List findNodeById(@Param("code") String code, @Param("nodeId") String nodeId,@Param("periodId") String periodId); - @Query("select n.id, n.name from School as c join n in c.nodes where c.code = @code and n.id in (@ids)") - List findAllByCodeAndIdIn(String code, Set ids); + @Query("select value n from School as c join n in c.nodes where c.code = @code and n.id in (@ids) and c.periodId = @periodId") + List findAllByCodeAndIdIn(String code, Set ids,String periodId); @Query("SELECT c.id, c.achievementRules FROM School AS c where c.code = 'Appraise' and c.schoolId = @schoolId and c.periodId = @periodId") List findRulesById(String schoolId, String periodId); } diff --git a/src/main/java/cn/teammodel/repository/StudentRepository.java b/src/main/java/cn/teammodel/repository/StudentRepository.java index 9f22b6e..7f87e8d 100644 --- a/src/main/java/cn/teammodel/repository/StudentRepository.java +++ b/src/main/java/cn/teammodel/repository/StudentRepository.java @@ -18,7 +18,7 @@ public interface StudentRepository extends CosmosRepository { @Query("select c.pk, c.code, c.id, c.name, c.gender, c.schoolId, c.periodId, c.year, c.createTime, c.picture, c.mail, c.mobile, c.country, c.classId, c.no, c.groupId, c.groupName, c.guardians, c.irs, c.salt from Student as c where c.id = @id and c.code = @code") List findByIdAndCode(String id, String code); - @Query("select c.id, c.name, c.classId, c.picture, c.periodId from Student as c where c.code = @code and c.id in (@ids)") + @Query("select c.pk, c.code, c.id, c.name, c.gender, c.schoolId, c.periodId, c.year, c.createTime, c.picture, c.mail, c.mobile, c.country, c.classId, c.no, c.groupId, c.groupName, c.guardians, c.irs, c.salt from Student as c where c.code = @code and c.id in (@ids)") List findAllByCodeAndIdIn(String code, Set ids); int countByClassIdAndCode(String classId, String code); diff --git a/src/main/java/cn/teammodel/service/impl/EvaluationServiceImpl.java b/src/main/java/cn/teammodel/service/impl/EvaluationServiceImpl.java index 823dbb3..9a01b15 100644 --- a/src/main/java/cn/teammodel/service/impl/EvaluationServiceImpl.java +++ b/src/main/java/cn/teammodel/service/impl/EvaluationServiceImpl.java @@ -30,6 +30,7 @@ import com.azure.spring.data.cosmos.core.query.CosmosPageRequest; import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; +import lombok.Data; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.jfree.chart.ChartUtils; @@ -41,6 +42,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; @@ -313,124 +315,178 @@ public class EvaluationServiceImpl implements EvaluationService { return buildTree(appraiseRepository.save(appraise)); } + // 定义辅助类(可选) + @Data + private static class TargetInfo { + private String classId; + private String className; + private String periodId; + private String name; + private String avatar; + private String gender; + + public TargetInfo(Student student) { + this.classId = student.getClassId(); + this.periodId = student.getPeriodId(); + this.name = student.getName(); + this.avatar = student.getPicture(); + this.gender = student.getGender(); + } + + public TargetInfo(ClassInfo classInfo) { + this.classId = classInfo.getId(); + this.className = classInfo.getName(); + this.periodId = classInfo.getPeriodId(); + this.name = classInfo.getName(); + } + } + @Override + @Transactional(rollbackFor = Exception.class) public void vote(AppraiseVoteDto appraiseVoteDto) { - String targetId = appraiseVoteDto.getTargetId(); + // 1. 获取基础参数 + List targetIds = appraiseVoteDto.getTargetIds(); + List appraiseIds = appraiseVoteDto.getAppraiseIds(); boolean spread = appraiseVoteDto.isSpread(); boolean pushParent = appraiseVoteDto.isPushParent(); String targetType = appraiseVoteDto.getTargetType(); - String appraiseId = appraiseVoteDto.getAppraiseId(); String from = appraiseVoteDto.getDevice(); User loginUser = SecurityUtil.getLoginUser(); String schoolId = loginUser.getSchoolId(); - String classId; - String className; - String periodId; - String name; - String avatar = null; - String gender = null; - // 分别对班级和学生的关键信息取值 + + // 2. 参数校验 + if (targetIds == null || targetIds.isEmpty()) { + throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "目标ID列表不能为空"); + } + if (appraiseIds == null || appraiseIds.isEmpty()) { + throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "评价项ID列表不能为空"); + } + + // 3. 批量查询目标信息 + Map targetInfoMap = getTargetInfos(targetIds, targetType, schoolId); + + // 4. 处理每个目标 + for (String targetId : targetIds) { + TargetInfo targetInfo = targetInfoMap.get(targetId); + processSingleTarget( + targetId, targetInfo, appraiseIds, spread, pushParent, targetType, + schoolId, loginUser, from + ); + } + } + + private Map getTargetInfos(List targetIds, String targetType, String schoolId) { + if (targetType.equals(TARGET_STUDENT)) { - List list = studentRepository.findByIdAndCode(targetId, String.format(PK.STUDENT, schoolId)); - Student student = RepositoryUtil.findOne(list, "该学生不存在"); - - classId = student.getClassId(); - periodId = student.getPeriodId(); - name = student.getName(); - avatar = student.getPicture(); - gender = student.getGender(); - - // 获取班级信息 - ClassInfo classInfo = classRepository.findClassByIdAndCode(classId, String.format(PK.CLASS, schoolId)); - className = classInfo.getName(); + + Set targetIdsSet = new HashSet<>(targetIds); + List students = studentRepository.findAllByCodeAndIdIn(String.format(PK.STUDENT, schoolId),targetIdsSet); + + return students.stream().collect(Collectors.toMap(Student::getId, TargetInfo::new)); + } else if (targetType.equals(TARGET_CLASS)) { - ClassInfo classInfo = classRepository.findClassByIdAndCode(targetId, String.format(PK.CLASS, schoolId)); - if (classInfo == null) { - throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "班级不存在"); - } - classId = targetId; - periodId = classInfo.getPeriodId(); - name = classInfo.getName(); - className = classInfo.getName(); + + List classes = classRepository.findAllByCodeAndIdIn(String.format(PK.CLASS, schoolId), targetIds); + + return classes.stream().collect(Collectors.toMap(ClassInfo::getId, TargetInfo::new)); + } else { - throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "不受支持的评价对象"); - } - // 获取评价项节点 - List nodes = appraiseRepository.findNodeById(PK.PK_APPRAISE, appraiseId,periodId); - AppraiseTreeNode appraiseTreeNode = RepositoryUtil.findOne(nodes, "该评价项不存在"); - if (appraiseTreeNode.getPath() == null) { - throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "仅能评价三级评价项"); + throw new ServiceException("不受支持的评价对象类型"); + } - // 通过 periodId 获取 semesters - List periodById = schoolRepository.findPeriodById(schoolId, periodId); + } + + private void processSingleTarget( + String targetId, TargetInfo targetInfo, List appraiseIds, + boolean spread, boolean pushParent, String targetType, + String schoolId, User loginUser, String from + ) { + // 1. 获取学段和学年学期信息 + List periodById = schoolRepository.findPeriodById(schoolId, targetInfo.getPeriodId()); School.Period period = RepositoryUtil.findOne(periodById, "获取学段失败"); List semesters = period.getSemesters(); - - // 获取当前学年学期组合 ID String academicYearId = SchoolDateUtil.calculateAcademicYearId(semesters, LocalDate.now()); - // 查询是否存在记录 - AppraiseRecord record = appraiseRecordRepository.findAppraiseRecordByTargetIdAndClassIdAndAcademicYearIdAndCode( - targetId, - classId, - academicYearId, - String.format(PK.PK_APPRAISE_RECORD, schoolId) - ); + // 2. 批量查询评价项节点 + Set appraiseIdsSet = new HashSet<>(appraiseIds); + List allNodes = appraiseRepository.findAllByCodeAndIdIn(PK.PK_APPRAISE, appraiseIdsSet, targetInfo.getPeriodId()); + Map nodeMap = allNodes.stream() + .collect(Collectors.toMap(AppraiseTreeNode::getId, node -> node)); + + // 3. 校验评价项有效性 + for (String appraiseId : appraiseIds) { + AppraiseTreeNode node = nodeMap.get(appraiseId); + //RepositoryUtil.findOne(nodeMap, "获取评价项失败: " + appraiseId) + if (node == null) { + throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "评价项不存在: " + appraiseId); + } + if (node.getPath() == null) { + throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "仅能评价三级评价项: " + appraiseId); + } + } - // 初始化新的评价节点 - AppraiseRecordItem item = new AppraiseRecordItem(); - item.setId(UUID.randomUUID().toString()); - item.setAppraiseNode(appraiseTreeNode); - item.setCreator(loginUser.getName()); - item.setCreatorId(loginUser.getId()); - item.setCreateTime(Instant.now().toEpochMilli()); - item.setDevice(from); - // 处理学校与学生的差异 - if (targetType.equals(TARGET_CLASS)) { - item.setSpread(spread); - } else { - item.setPushParent(pushParent); + // 4. 构建评价记录项并统计值 + int totalPraise = 0; + int totalCriticize = 0; + int totalScoreIncrement = 0; + List items = new ArrayList<>(); + for (String appraiseId : appraiseIds) { + AppraiseTreeNode node = nodeMap.get(appraiseId); + AppraiseRecordItem item = new AppraiseRecordItem(); + item.setId(UUID.randomUUID().toString()); + item.setAppraiseNode(node); + item.setCreator(loginUser.getName()); + item.setCreatorId(loginUser.getId()); + item.setCreateTime(Instant.now().toEpochMilli()); + item.setDevice(from); + if (TARGET_CLASS.equals(targetType)) { + item.setSpread(spread); + } else { + item.setPushParent(pushParent); + } + items.add(item); + + if (node.isPraise()) { + totalPraise++; + totalScoreIncrement += 1; + } else { + totalCriticize++; + totalScoreIncrement -= 1; + } } - // 不存在或者学生的班级不一样则创建一条新的,存在则处理一下分值后再向其 nodes 中插入一条 item + // 5. 创建或更新评价记录 + String classId = targetInfo.getClassId(); + AppraiseRecord record = appraiseRecordRepository.findAppraiseRecordByTargetIdAndClassIdAndAcademicYearIdAndCode( + targetId, classId, academicYearId, String.format(PK.PK_APPRAISE_RECORD, schoolId) + ); if (record == null || !classId.equals(record.getClassId())) { - List items = Collections.singletonList(item); - record = new AppraiseRecord(); record.setTargetId(targetId); record.setTargetType(targetType); record.setClassId(classId); - record.setClassName(className); - record.setName(name); - record.setAvatar(avatar); - record.setGender(gender); + record.setClassName(targetInfo.getClassName()); + record.setName(targetInfo.getName()); + record.setAvatar(targetInfo.getAvatar()); + record.setGender(targetInfo.getGender()); record.setAcademicYearId(academicYearId); - record.setPraiseCount(appraiseTreeNode.isPraise() ? 1 : 0); - record.setCriticizeCount(appraiseTreeNode.isPraise() ? 0 : 1); - record.setScore(appraiseTreeNode.isPraise() ? 1 : 0); + record.setPraiseCount(totalPraise); + record.setCriticizeCount(totalCriticize); + record.setScore(Math.max(totalScoreIncrement, 0)); record.setNodes(items); record.setCode(String.format(PK.PK_APPRAISE_RECORD, schoolId)); appraiseRecordRepository.save(record); } else { CosmosPatchOperations operations = CosmosPatchOperations.create(); - operations.add("/nodes/-", item); - // 表扬 (待改进不会减少表扬数) - if (appraiseTreeNode.isPraise()) { - operations.increment("/praiseCount", 1); - }else { - operations.increment("/criticizeCount", 1); - } - // 加分 - //nt scoreToPlus = ObjectUtils.isEmpty(appraiseTreeNode.getScore()) ? 0 : appraiseTreeNode.getScore(); - int incrementValue = appraiseTreeNode.isPraise() ? 1 : -1; - if (record.getScore() + incrementValue < 0) { - operations.set("/score", 0); - }else { - operations.increment("/score", incrementValue); + for (AppraiseRecordItem item : items) { + operations.add("/nodes/-", item); } - // patch doc + operations.increment("/praiseCount", totalPraise); + operations.increment("/criticizeCount", totalCriticize); + int newScore = record.getScore() + totalScoreIncrement; + operations.set("/score", Math.max(newScore, 0)); appraiseRecordRepository.save(record.getId(), PK.buildOf(PK.PK_APPRAISE_RECORD, schoolId), AppraiseRecord.class, operations); } }