diff --git a/src/main/java/cn/teammodel/controller/admin/controller/AdminDutyController.java b/src/main/java/cn/teammodel/controller/admin/controller/AdminDutyController.java index 1022925..dda8765 100644 --- a/src/main/java/cn/teammodel/controller/admin/controller/AdminDutyController.java +++ b/src/main/java/cn/teammodel/controller/admin/controller/AdminDutyController.java @@ -4,8 +4,10 @@ import cn.teammodel.common.R; import cn.teammodel.controller.admin.service.AdminIndexDutyService; import cn.teammodel.model.dto.admin.appraise.TimeRangeDto; import cn.teammodel.model.dto.admin.weekduty.AdminFindDutyRecordDto; +import cn.teammodel.model.vo.admin.AppraiseNodeRankVo; import cn.teammodel.model.vo.admin.DutyIndexData; -import cn.teammodel.model.vo.appraise.RecordVo; +import cn.teammodel.model.vo.admin.DutyNodeRankVo; +import cn.teammodel.model.vo.admin.DutyRankPo; import cn.teammodel.model.vo.weekDuty.DutyRecordVo; import cn.teammodel.service.DutyService; import io.swagger.annotations.Api; @@ -44,12 +46,23 @@ public class AdminDutyController { return R.success(dutyIndexData); } - @PostMapping("index/latestRecord") - @ApiOperation("查询时间范围最近评价(无参则当前周的所有记录)") - public R> latestRecord(@Valid @RequestBody TimeRangeDto timeRangeDto) { - List res = adminIndexDutyService.conditionLatestRecord(timeRangeDto); + @PostMapping("classRank") + @ApiOperation("班级评价活跃排行榜: Top10") + public R> classRank(@Valid @RequestBody TimeRangeDto timeRangeDto) { + List res = adminIndexDutyService.classRank(timeRangeDto); return R.success(res); } - + @PostMapping("teacherRank") + @ApiOperation("老师评价活跃排行榜: Top10") + public R> teacherRank(@Valid @RequestBody TimeRangeDto timeRangeDto) { + List res = adminIndexDutyService.teacherRank(timeRangeDto); + return R.success(res); + } + @PostMapping("dutyNodeRank") + @ApiOperation("评价指标活跃排行榜: Top10") + public R> appraiseNodeRank(@Valid @RequestBody TimeRangeDto timeRangeDto) { + List res = adminIndexDutyService.appraiseNodeRank(timeRangeDto); + return R.success(res); + } } diff --git a/src/main/java/cn/teammodel/controller/admin/service/AdminIndexDutyService.java b/src/main/java/cn/teammodel/controller/admin/service/AdminIndexDutyService.java index e876618..dd1eaf2 100644 --- a/src/main/java/cn/teammodel/controller/admin/service/AdminIndexDutyService.java +++ b/src/main/java/cn/teammodel/controller/admin/service/AdminIndexDutyService.java @@ -2,7 +2,8 @@ package cn.teammodel.controller.admin.service; import cn.teammodel.model.dto.admin.appraise.TimeRangeDto; import cn.teammodel.model.vo.admin.DutyIndexData; -import cn.teammodel.model.vo.appraise.RecordVo; +import cn.teammodel.model.vo.admin.DutyNodeRankVo; +import cn.teammodel.model.vo.admin.DutyRankPo; import java.util.List; @@ -13,5 +14,9 @@ import java.util.List; public interface AdminIndexDutyService { DutyIndexData getIndexData(String periodId); - List conditionLatestRecord(TimeRangeDto timeRangeDto); + List classRank(TimeRangeDto timeRangeDto); + + List teacherRank(TimeRangeDto timeRangeDto); + + List appraiseNodeRank(TimeRangeDto timeRangeDto); } diff --git a/src/main/java/cn/teammodel/controller/admin/service/impl/AdminAppraiseServiceImpl.java b/src/main/java/cn/teammodel/controller/admin/service/impl/AdminAppraiseServiceImpl.java index 23834fb..ad29ac8 100644 --- a/src/main/java/cn/teammodel/controller/admin/service/impl/AdminAppraiseServiceImpl.java +++ b/src/main/java/cn/teammodel/controller/admin/service/impl/AdminAppraiseServiceImpl.java @@ -254,12 +254,13 @@ public class AdminAppraiseServiceImpl implements AdminAppraiseService { // 去重后的 nodes List nodesByName = appraiseRecordRepository.findAppraiseRecordInNames(String.format(PK.PK_APPRAISE_RECORD, schoolId), academicYearId, names); // 正常情况下 name 一一对应 todo: 临时解决 - Map nameNodeMap = nodesByName.stream().collect(Collectors.toMap(AppraiseTreeNode::getName, item -> item, (existing, replacement) -> { - if (replacement.getPath() != null) { - return replacement; - } - return existing; - })); + Map nameNodeMap = nodesByName.stream() + .collect(Collectors.toMap(AppraiseTreeNode::getName, item -> item, (existing, replacement) -> { + if (replacement.getPath() != null) { + return replacement; + } + return existing; + })); rankVoList = rankVoList.stream() .sorted(Comparator.comparing(RankPo::getCount).reversed()) @@ -324,7 +325,7 @@ public class AdminAppraiseServiceImpl implements AdminAppraiseService { Map idNameMap = students.stream().collect(Collectors.toMap(Student::getId, item -> { String[] studentInfo = new String[3]; studentInfo[0] = item.getName(); - studentInfo[1]= item.getClassId(); + studentInfo[1] = item.getClassId(); studentInfo[2] = item.getPicture(); return studentInfo; })); diff --git a/src/main/java/cn/teammodel/controller/admin/service/impl/AdminIndexDutyServiceImpl.java b/src/main/java/cn/teammodel/controller/admin/service/impl/AdminIndexDutyServiceImpl.java index f62eac4..f283abe 100644 --- a/src/main/java/cn/teammodel/controller/admin/service/impl/AdminIndexDutyServiceImpl.java +++ b/src/main/java/cn/teammodel/controller/admin/service/impl/AdminIndexDutyServiceImpl.java @@ -6,13 +6,18 @@ import cn.teammodel.config.exception.ServiceException; import cn.teammodel.controller.admin.service.AdminIndexDutyService; import cn.teammodel.model.dto.admin.appraise.TimeRangeDto; import cn.teammodel.model.entity.User; +import cn.teammodel.model.entity.school.ClassInfo; import cn.teammodel.model.entity.school.School; +import cn.teammodel.model.entity.school.Teacher; +import cn.teammodel.model.entity.weekDuty.WeekDuty; import cn.teammodel.model.vo.admin.DutyIndexData; import cn.teammodel.model.vo.admin.DutyIndexPo; -import cn.teammodel.model.vo.appraise.RecordVo; +import cn.teammodel.model.vo.admin.DutyNodeRankVo; +import cn.teammodel.model.vo.admin.DutyRankPo; +import cn.teammodel.repository.ClassRepository; import cn.teammodel.repository.DutyRecordRepository; -import cn.teammodel.repository.DutyRepository; import cn.teammodel.repository.SchoolRepository; +import cn.teammodel.repository.TeacherRepository; import cn.teammodel.security.utils.SecurityUtil; import cn.teammodel.utils.SchoolDateUtil; import com.azure.spring.data.cosmos.core.query.CosmosPageRequest; @@ -24,10 +29,8 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; import static cn.teammodel.utils.SchoolDateUtil.calculateWeekNum; @@ -42,8 +45,10 @@ public class AdminIndexDutyServiceImpl implements AdminIndexDutyService { private SchoolRepository schoolRepository; @Resource - private DutyRepository dutyRepository; + private TeacherRepository teacherRepository; + @Resource + private ClassRepository classRepository; @Resource private DutyRecordRepository dutyRecordRepository; @@ -116,7 +121,76 @@ public class AdminIndexDutyServiceImpl implements AdminIndexDutyService { } @Override - public List conditionLatestRecord(TimeRangeDto timeRangeDto) { - return null; + public List classRank(TimeRangeDto timeRangeDto) { + Long startTime = timeRangeDto.getStartTime(); + Long endTime = timeRangeDto.getEndTime(); + String academicYearId = timeRangeDto.getAcademicYearId(); + String schoolId = SecurityUtil.getLoginUser().getSchoolId(); + List res = dutyRecordRepository.classRank(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, startTime, endTime); + if (ObjectUtils.isEmpty(res)) return null; + List classIds = res.stream().map(DutyRankPo::getId).collect(Collectors.toList()); + if (ObjectUtils.isEmpty(classIds)) { + return null; + } + List classes = classRepository.findAllByCodeAndIdIn(String.format(PK.CLASS, schoolId), classIds); + Map idNameMap = classes.stream().collect(Collectors.toMap(ClassInfo::getId, ClassInfo::getName)); + // reversed sort by score + res = res.stream().peek(s -> s.setName(idNameMap.get(s.getId()))).sorted((a, b) -> b.getScore() - a.getScore()).collect(Collectors.toList()); + return res; + } + + @Override + public List teacherRank(TimeRangeDto timeRangeDto) { + Long startTime = timeRangeDto.getStartTime(); + Long endTime = timeRangeDto.getEndTime(); + String academicYearId = timeRangeDto.getAcademicYearId(); + String schoolId = SecurityUtil.getLoginUser().getSchoolId(); + List res = dutyRecordRepository.teacherRank(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, startTime, endTime); + // set teacher name + if (ObjectUtils.isEmpty(res)) return null; + Set teacherIdSet = res.stream().map(DutyRankPo::getId).collect(Collectors.toSet()); + if (ObjectUtils.isEmpty(teacherIdSet)) return res; + List teachers = teacherRepository.findAllByCodeAndIdIn(PK.COMMON_BASE, teacherIdSet); + Map idNameMap = teachers.stream().collect(Collectors.toMap(Teacher::getId, Teacher::getName)); + res = res.stream().peek(s -> s.setName(idNameMap.get(s.getId()))).sorted((a, b) -> b.getScore() - a.getScore()).collect(Collectors.toList()); + return res; + } + + @Override + public List appraiseNodeRank(TimeRangeDto timeRangeDto) { + Long startTime = timeRangeDto.getStartTime(); + Long endTime = timeRangeDto.getEndTime(); + String academicYearId = timeRangeDto.getAcademicYearId(); + String schoolId = SecurityUtil.getLoginUser().getSchoolId(); + + List res = dutyRecordRepository.dutyNodeRank(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, startTime, endTime); + if (ObjectUtils.isEmpty(res)) return null; + List names = res.stream().map(DutyNodeRankVo::getName).collect(Collectors.toList()); + if (ObjectUtils.isEmpty(names)) return null; + // 去重后的 nodes + List nodesByName = dutyRecordRepository.findDutyRecordInNames(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, names); + // 正常情况下 name 一一对应 // TODO: 2024/2/29 + Map nameNodeMap = nodesByName.stream() + .collect(Collectors.toMap(WeekDuty.DutyTreeNode::getName, item -> item, (existing, replacement) -> { + if (replacement.getPath() != null) { + return replacement; + } + return existing; + })); + + res = res.stream() + .sorted(Comparator.comparing(DutyNodeRankVo::getCount).reversed()) + // 流中对元素操作但不改变流 + .peek(s -> { + WeekDuty.DutyTreeNode node = nameNodeMap.get(s.getName()); + if (node != null) { + s.setPath(node.getPath()); + s.setScore(node.getScore()); + } + }) + .collect(Collectors.toList()); + return res; + + } } diff --git a/src/main/java/cn/teammodel/model/dto/admin/appraise/TimeRangeDto.java b/src/main/java/cn/teammodel/model/dto/admin/appraise/TimeRangeDto.java index 5720e6b..51c1219 100644 --- a/src/main/java/cn/teammodel/model/dto/admin/appraise/TimeRangeDto.java +++ b/src/main/java/cn/teammodel/model/dto/admin/appraise/TimeRangeDto.java @@ -12,6 +12,6 @@ public class TimeRangeDto { private Long startTime; private Long endTime; @NotNull - // todo: 似乎不需要(如果不传时间那就需要) + // todo: 似乎不需要(有时间范围就不需要这个字段来划分时间,如果不传时间那就需要) private String academicYearId; } diff --git a/src/main/java/cn/teammodel/model/vo/admin/DutyNodeRankVo.java b/src/main/java/cn/teammodel/model/vo/admin/DutyNodeRankVo.java new file mode 100644 index 0000000..3750a0b --- /dev/null +++ b/src/main/java/cn/teammodel/model/vo/admin/DutyNodeRankVo.java @@ -0,0 +1,15 @@ +package cn.teammodel.model.vo.admin; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author winter + * @create 2024-02-29 15:36 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class DutyNodeRankVo extends DutyRankPo { + private Integer count; + private String[] path; +} diff --git a/src/main/java/cn/teammodel/model/vo/admin/DutyRankPo.java b/src/main/java/cn/teammodel/model/vo/admin/DutyRankPo.java new file mode 100644 index 0000000..5c64cd6 --- /dev/null +++ b/src/main/java/cn/teammodel/model/vo/admin/DutyRankPo.java @@ -0,0 +1,14 @@ +package cn.teammodel.model.vo.admin; + +import lombok.Data; + +/** + * @author winter + * @create 2024-02-29 11:39 + */ +@Data +public class DutyRankPo { + private String id; + private String name; + private Integer score; +} diff --git a/src/main/java/cn/teammodel/repository/DutyRecordRepository.java b/src/main/java/cn/teammodel/repository/DutyRecordRepository.java index 61f75b5..d369378 100644 --- a/src/main/java/cn/teammodel/repository/DutyRecordRepository.java +++ b/src/main/java/cn/teammodel/repository/DutyRecordRepository.java @@ -1,6 +1,9 @@ package cn.teammodel.repository; +import cn.teammodel.model.entity.weekDuty.WeekDuty; import cn.teammodel.model.entity.weekDuty.WeekDutyRecord; +import cn.teammodel.model.vo.admin.DutyNodeRankVo; +import cn.teammodel.model.vo.admin.DutyRankPo; import cn.teammodel.model.vo.admin.DutyIndexPo; import cn.teammodel.model.vo.weekDuty.DutyRecordVo; import com.azure.spring.data.cosmos.core.query.CosmosPageRequest; @@ -31,5 +34,35 @@ public interface DutyRecordRepository extends CosmosRepository findAllByAcademicYearId(String code, String academicYearId, CosmosPageRequest pageRequest); + + @Query("select SUM(n.dutyTreeNode.score) as score, c.classId as id from School as c join n in c.nodes where " + + "c.academicYearId = @academicYearId and " + + "c.code = @code and " + + "(IS_NULL(@startTime) or n.createTime >= @startTime) and " + + "(IS_NULL(@endTime) or n.createTime <= @endTime) " + + "group by c.classId") + List classRank(String code, String academicYearId, Long startTime, Long endTime); + + @Query("select count(n.creatorId) as score, n.creatorId as id from School as c join n in c.nodes where " + + "c.academicYearId = @academicYearId and " + + "c.code = @code and " + + "(IS_NULL(@startTime) or n.createTime >= @startTime) and " + + "(IS_NULL(@endTime) or n.createTime <= @endTime) " + + "group by n.creatorId") + List teacherRank(String code, String academicYearId, Long startTime, Long endTime); + + @Query("select count(n.dutyTreeNode.name) as count, n.dutyTreeNode.name from School as c join n in c.nodes where " + + "c.academicYearId = @academicYearId and " + + "c.code = @code and " + + "(IS_NULL(@startTime) or n.createTime >= @startTime) and " + + "(IS_NULL(@endTime) or n.createTime <= @endTime) " + + "group by n.dutyTreeNode.name") + List dutyNodeRank(String code, String academicYearId, Long startTime, Long endTime); + + @Query("select n.dutyTreeNode.name, n.dutyTreeNode.path, n.dutyTreeNode.score from School as c join n in c.nodes where " + + "c.academicYearId = @academicYearId and " + + "c.code = @code and " + + "n.dutyTreeNode.name in (@names)") + List findDutyRecordInNames(String code, String academicYearId, List names); }