Compare commits

...
2 Commits
Author SHA1 Message Date
wanghu f7e5bf0de0 学科
build / build-push (push) Successful in 1m29s
2026-09-23 08:34:09 +08:00
wanghu 76493683c3 学科 2026-09-23 08:33:57 +08:00
8 changed files with 126 additions and 29 deletions
@@ -52,6 +52,8 @@ public class HomeworkStatisticsVo {
private Integer id; private Integer id;
private String title; private String title;
private String subject; private String subject;
/** 学科名称(本校学科字典解析,未命中回退编码) */
private String subjectName;
/** 旧契约四态派生值:draft / collecting / closed / done */ /** 旧契约四态派生值:draft / collecting / closed / done */
private String hwStatus; private String hwStatus;
private String hwStatusDesc; private String hwStatusDesc;
@@ -56,6 +56,9 @@ public class HomeworkVo {
/** 学科(字典值) */ /** 学科(字典值) */
private String subject; private String subject;
/** 学科名称(本校学科字典解析,未命中回退编码) */
private String subjectName;
/** 截止时间(前端契约字段名 deadline) */ /** 截止时间(前端契约字段名 deadline) */
private LocalDateTime deadline; private LocalDateTime deadline;
@@ -16,9 +16,12 @@ public class HomeworkV2Vo {
private String title; private String title;
/** 学科 */ /** 学科编码 */
private String subject; private String subject;
/** 学科名称(本校学科字典解析,未命中回退编码) */
private String subjectName;
/** 作业说明(富文本;列表场景可置空省流) */ /** 作业说明(富文本;列表场景可置空省流) */
private String description; private String description;
@@ -17,6 +17,9 @@ public class StudentHomeworkVo {
/** 学科 */ /** 学科 */
private String subject; private String subject;
/** 学科名称(本校学科字典解析,未命中回退编码) */
private String subjectName;
/** 任课教师(发布人姓名) */ /** 任课教师(发布人姓名) */
private String teacherName; private String teacherName;
@@ -92,6 +92,9 @@ public class HomeworkService implements IHomeworkService {
@Autowired @Autowired
private IDictService dictService; private IDictService dictService;
@Autowired
private SubjectDictService subjectDictService;
private static final int PUBLISHED = HomeworkStatusEnum.PUBLISHED.getCode(); private static final int PUBLISHED = HomeworkStatusEnum.PUBLISHED.getCode();
// ============================ 发作业 ============================ // ============================ 发作业 ============================
@@ -269,8 +272,9 @@ public class HomeworkService implements IHomeworkService {
Page<Homework> page = homeworkRepository.findAll(userSpec(query, readIds), pageable); Page<Homework> page = homeworkRepository.findAll(userSpec(query, readIds), pageable);
Map<String, String> subjectNames = subjectDictService.nameMap();
List<HomeworkVo> content = page.getContent().stream() List<HomeworkVo> content = page.getContent().stream()
.map(n -> toVo(n, readIds.contains(n.getId()))) .map(n -> toVo(n, readIds.contains(n.getId()), subjectNames))
.collect(Collectors.toList()); .collect(Collectors.toList());
long unreadCount = 0; long unreadCount = 0;
@@ -322,8 +326,9 @@ public class HomeworkService implements IHomeworkService {
@Override @Override
public BasePageResult<HomeworkVo> adminList(HomeworkQuery query, Pageable pageable) { public BasePageResult<HomeworkVo> adminList(HomeworkQuery query, Pageable pageable) {
Page<Homework> page = homeworkRepository.findAll(adminSpec(query), pageable); Page<Homework> page = homeworkRepository.findAll(adminSpec(query), pageable);
Map<String, String> subjectNames = subjectDictService.nameMap();
List<HomeworkVo> content = page.getContent().stream() List<HomeworkVo> content = page.getContent().stream()
.map(n -> toVo(n, false)) .map(n -> toVo(n, false, subjectNames))
.collect(Collectors.toList()); .collect(Collectors.toList());
// 批量填充附件ID串("1,2,3"):列表页"附件下载"入口依赖 UpFile 字段 // 批量填充附件ID串("1,2,3"):列表页"附件下载"入口依赖 UpFile 字段
if (!content.isEmpty()) { if (!content.isEmpty()) {
@@ -431,7 +436,7 @@ public class HomeworkService implements IHomeworkService {
.orElseThrow(() -> new BizException(ErrorCode.FORBIDDEN, "作业不存在: " + id)); .orElseThrow(() -> new BizException(ErrorCode.FORBIDDEN, "作业不存在: " + id));
Integer userId = UserContext.getUserId(); Integer userId = UserContext.getUserId();
boolean read = homeworkReadRepository.existsByHomeworkIdAndReaderId(id, userId); boolean read = homeworkReadRepository.existsByHomeworkIdAndReaderId(id, userId);
HomeworkVo vo = toVo(entity, read); HomeworkVo vo = toVo(entity, read, subjectDictService.nameMap());
if (!read) { if (!read) {
markRead(id); markRead(id);
vo.setRead(true); vo.setRead(true);
@@ -445,7 +450,7 @@ public class HomeworkService implements IHomeworkService {
public HomeworkVo getDetail(Integer id) { public HomeworkVo getDetail(Integer id) {
Homework entity = homeworkRepository.findById(id) Homework entity = homeworkRepository.findById(id)
.orElseThrow(() -> new BizException(ErrorCode.FORBIDDEN, "作业不存在: " + id)); .orElseThrow(() -> new BizException(ErrorCode.FORBIDDEN, "作业不存在: " + id));
HomeworkVo vo = toVo(entity, false); HomeworkVo vo = toVo(entity, false, subjectDictService.nameMap());
vo.setReadCount(homeworkReadRepository.countByHomeworkId(entity.getId())); vo.setReadCount(homeworkReadRepository.countByHomeworkId(entity.getId()));
return vo; return vo;
} }
@@ -779,6 +784,7 @@ public class HomeworkService implements IHomeworkService {
Map<Integer, List<Integer>> classMap = homeworkClassRepository.findByHomeworkIds(hwIds).stream() Map<Integer, List<Integer>> classMap = homeworkClassRepository.findByHomeworkIds(hwIds).stream()
.collect(Collectors.groupingBy(HomeworkClass::getHomeworkId, .collect(Collectors.groupingBy(HomeworkClass::getHomeworkId,
Collectors.mapping(HomeworkClass::getClassId, Collectors.toList()))); Collectors.mapping(HomeworkClass::getClassId, Collectors.toList())));
Map<String, String> subjectNames = subjectDictService.nameMap();
long pendingTotal = 0; long pendingTotal = 0;
double submitRateSum = 0; double submitRateSum = 0;
@@ -794,6 +800,7 @@ public class HomeworkService implements IHomeworkService {
d.setId(h.getId()); d.setId(h.getId());
d.setTitle(h.getTitle()); d.setTitle(h.getTitle());
d.setSubject(h.getSubject()); d.setSubject(h.getSubject());
d.setSubjectName(subjectDictService.resolve(h.getSubject(), subjectNames));
String legacy = legacyHwStatus(h); String legacy = legacyHwStatus(h);
d.setHwStatus(legacy); d.setHwStatus(legacy);
d.setHwStatusDesc(legacyHwStatusDesc(legacy)); d.setHwStatusDesc(legacyHwStatusDesc(legacy));
@@ -1009,7 +1016,7 @@ public class HomeworkService implements IHomeworkService {
} }
} }
private HomeworkVo toVo(Homework entity, boolean read) { private HomeworkVo toVo(Homework entity, boolean read, Map<String, String> subjectNames) {
HomeworkVo vo = new HomeworkVo(); HomeworkVo vo = new HomeworkVo();
BeanUtils.copyProperties(entity, vo); BeanUtils.copyProperties(entity, vo);
vo.setTypeDesc(HomeworkTypeEnum.of(entity.getType()).getDesc()); vo.setTypeDesc(HomeworkTypeEnum.of(entity.getType()).getDesc());
@@ -1017,6 +1024,7 @@ public class HomeworkService implements IHomeworkService {
// V2 扩展字段回填(hwStatus 输出旧四态派生值,submitType/deadline 手工映射) // V2 扩展字段回填(hwStatus 输出旧四态派生值,submitType/deadline 手工映射)
vo.setDeadline(entity.getDeadlineAt()); vo.setDeadline(entity.getDeadlineAt());
vo.setSubmitType(SubmitTypes.parse(entity.getSubmitType())); vo.setSubmitType(SubmitTypes.parse(entity.getSubmitType()));
vo.setSubjectName(subjectDictService.resolve(entity.getSubject(), subjectNames));
String legacy = legacyHwStatus(entity); String legacy = legacyHwStatus(entity);
vo.setHwStatus(legacy); vo.setHwStatus(legacy);
vo.setHwStatusDesc(legacyHwStatusDesc(legacy)); vo.setHwStatusDesc(legacyHwStatusDesc(legacy));
@@ -71,6 +71,9 @@ public class StudentHomeworkService {
@Autowired @Autowired
private RosterService rosterService; private RosterService rosterService;
@Autowired
private SubjectDictService subjectDictService;
// ============================ 页 1:作业列表 ============================ // ============================ 页 1:作业列表 ============================
/** /**
@@ -96,8 +99,9 @@ public class StudentHomeworkService {
.collect(Collectors.toMap(HomeworkSubmission::getHomeworkId, s -> s, (a, b) -> a)); .collect(Collectors.toMap(HomeworkSubmission::getHomeworkId, s -> s, (a, b) -> a));
List<StudentHomeworkVo> rows = new ArrayList<>(); List<StudentHomeworkVo> rows = new ArrayList<>();
Map<String, String> subjectNames = subjectDictService.nameMap();
for (Homework h : homeworks) { for (Homework h : homeworks) {
StudentHomeworkVo vo = toVo(h, myLatest.get(h.getId())); StudentHomeworkVo vo = toVo(h, myLatest.get(h.getId()), subjectNames);
rows.add(vo); rows.add(vo);
} }
rows = filterByTab(rows, tab); rows = filterByTab(rows, tab);
@@ -150,7 +154,7 @@ public class StudentHomeworkService {
HomeworkSubmission latest = myLatest(homework.getId()); HomeworkSubmission latest = myLatest(homework.getId());
StudentHomeworkDetailVo vo = new StudentHomeworkDetailVo(); StudentHomeworkDetailVo vo = new StudentHomeworkDetailVo();
copyBase(vo, homework, latest); copyBase(vo, homework, latest, subjectDictService.nameMap());
vo.setDescription(homework.getContent()); vo.setDescription(homework.getContent());
vo.setAttachments(homeworkAttachmentRepository.findByHomeworkIdOrderBySortAscIdAsc(id).stream() vo.setAttachments(homeworkAttachmentRepository.findByHomeworkIdOrderBySortAscIdAsc(id).stream()
.map(this::toAttachmentItem).collect(Collectors.toList())); .map(this::toAttachmentItem).collect(Collectors.toList()));
@@ -398,16 +402,18 @@ public class StudentHomeworkService {
.orElse(null); .orElse(null);
} }
private StudentHomeworkVo toVo(Homework h, HomeworkSubmission latest) { private StudentHomeworkVo toVo(Homework h, HomeworkSubmission latest, Map<String, String> subjectNames) {
StudentHomeworkVo vo = new StudentHomeworkVo(); StudentHomeworkVo vo = new StudentHomeworkVo();
copyBase(vo, h, latest); copyBase(vo, h, latest, subjectNames);
return vo; return vo;
} }
private void copyBase(StudentHomeworkVo vo, Homework h, HomeworkSubmission latest) { private void copyBase(StudentHomeworkVo vo, Homework h, HomeworkSubmission latest,
Map<String, String> subjectNames) {
vo.setId(h.getId()); vo.setId(h.getId());
vo.setTitle(h.getTitle()); vo.setTitle(h.getTitle());
vo.setSubject(h.getSubject()); vo.setSubject(h.getSubject());
vo.setSubjectName(subjectDictService.resolve(h.getSubject(), subjectNames));
vo.setTeacherName(h.getPublisherName()); vo.setTeacherName(h.getPublisherName());
vo.setDeadlineAt(h.getDeadlineAt()); vo.setDeadlineAt(h.getDeadlineAt());
vo.setSubmitType(SubmitTypes.parse(h.getSubmitType())); vo.setSubmitType(SubmitTypes.parse(h.getSubmitType()));
@@ -0,0 +1,78 @@
package com.yunhai.homework.service.impl;
import com.yunhai.homework.model.bsch.SchInfoDto;
import com.yunhai.homework.model.bsch.SchSubjectDto;
import com.yunhai.homework.service.IClassService;
import com.yunhai.homework.utils.UserContext;
import com.yunhai.platform.apistd.BizException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 本校学科字典门面(bschclass SubInfo/GetSchSublist):
* 学科编码 → 名称解析,供各作业列表回填 subjectName 与学科清单输出共用。
* 无学校身份或远端不可用时降级为空字典,仅影响名称展示(回退编码),不阻断业务本身。
*/
@Service
public class SubjectDictService {
private static final Logger log = LoggerFactory.getLogger(SubjectDictService.class);
private final IClassService classService;
public SubjectDictService(IClassService classService) {
this.classService = classService;
}
/**
* 当前登录人学校的学科字典(保留 SubInfo 排序号,学科清单场景按其排序输出)。
*/
public List<SchSubjectDto> dictionary() {
try {
Integer schId = UserContext.getSchId();
if (schId == null) {
return Collections.emptyList();
}
SchInfoDto sch = classService.getSchFirst(schId);
if (sch == null || !StringUtils.hasText(sch.getSchSerId())) {
return Collections.emptyList();
}
return classService.getSchSubList(sch.getSchSerId());
} catch (BizException e) {
log.warn("[subjectDict] 本校学科字典拉取失败, 降级为编码展示: {}", e.getMessage());
return Collections.emptyList();
}
}
/**
* 学科编码 → 名称映射(列表回填 subjectName 用,一次批量外呼)。
*/
public Map<String, String> nameMap() {
Map<String, String> names = new HashMap<>();
for (SchSubjectDto subject : dictionary()) {
if (subject != null && StringUtils.hasText(subject.getSubId())
&& StringUtils.hasText(subject.getSubName())) {
names.put(subject.getSubId(), subject.getSubName());
}
}
return names;
}
/**
* 学科编码 → 名称:映射命中取名称,未命中或映射缺失时回退编码本身。
*/
public String resolve(String code, Map<String, String> names) {
if (!StringUtils.hasText(code)) {
return null;
}
String name = names == null ? null : names.get(code);
return StringUtils.hasText(name) ? name : code;
}
}
@@ -125,6 +125,9 @@ public class TeacherHomeworkV2Service {
@Autowired @Autowired
private IClassService classService; private IClassService classService;
@Autowired
private SubjectDictService subjectDictService;
// ============================ 页 1:创建 / 编辑 ============================ // ============================ 页 1:创建 / 编辑 ============================
/** /**
@@ -254,7 +257,8 @@ public class TeacherHomeworkV2Service {
Arrays.asList(HwStatusEnum.DRAFT_UNPUBLISHED.getCode(), HwStatusEnum.DRAFT_SCHEDULED.getCode()), Arrays.asList(HwStatusEnum.DRAFT_UNPUBLISHED.getCode(), HwStatusEnum.DRAFT_SCHEDULED.getCode()),
query), query),
PageUtils.toPageable(query, sort == null ? Sort.by(Sort.Direction.DESC, "updateTime") : sort)); PageUtils.toPageable(query, sort == null ? Sort.by(Sort.Direction.DESC, "updateTime") : sort));
return PageUtils.toResult(page.map(h -> toVo(h, false, false))); Map<String, String> subjectNames = subjectDictService.nameMap();
return PageUtils.toResult(page.map(h -> toVo(h, false, false, subjectNames)));
} }
// ============================ 页 3:已发布列表 ============================ // ============================ 页 3:已发布列表 ============================
@@ -271,7 +275,8 @@ public class TeacherHomeworkV2Service {
Page<Homework> page = homeworkRepository.findAll( Page<Homework> page = homeworkRepository.findAll(
ownedStatusSpec(UserContext.getUserId(), statuses, query), ownedStatusSpec(UserContext.getUserId(), statuses, query),
PageUtils.toPageable(query, sort == null ? Sort.by(Sort.Direction.DESC, "publishedAt") : sort)); PageUtils.toPageable(query, sort == null ? Sort.by(Sort.Direction.DESC, "publishedAt") : sort));
return PageUtils.toResult(page.map(h -> toVo(h, false, true))); Map<String, String> subjectNames = subjectDictService.nameMap();
return PageUtils.toResult(page.map(h -> toVo(h, false, true, subjectNames)));
} }
private Specification<Homework> ownedStatusSpec(Integer publisherId, List<String> statuses, TeacherHomeworkQuery query) { private Specification<Homework> ownedStatusSpec(Integer publisherId, List<String> statuses, TeacherHomeworkQuery query) {
@@ -391,7 +396,7 @@ public class TeacherHomeworkV2Service {
@Transactional(readOnly = true) @Transactional(readOnly = true)
public HomeworkV2Vo detail(Integer id) { public HomeworkV2Vo detail(Integer id) {
Homework homework = stateService.requireOwned(id, UserContext.getUserId()); Homework homework = stateService.requireOwned(id, UserContext.getUserId());
return toVo(homework, true, !HwStatusEnum.of(homework.getHwStatus()).isDraft()); return toVo(homework, true, !HwStatusEnum.of(homework.getHwStatus()).isDraft(), subjectDictService.nameMap());
} }
/** /**
@@ -1068,20 +1073,7 @@ public class TeacherHomeworkV2Service {
* 仅影响名称解析(学科名称回退为编码),不阻断学科清单本身。 * 仅影响名称解析(学科名称回退为编码),不阻断学科清单本身。
*/ */
private List<SchSubjectDto> subjectDictionary() { private List<SchSubjectDto> subjectDictionary() {
try { return subjectDictService.dictionary();
Integer schId = UserContext.getSchId();
if (schId == null) {
return Collections.emptyList();
}
SchInfoDto sch = classService.getSchFirst(schId);
if (sch == null || !StringUtils.hasText(sch.getSchSerId())) {
return Collections.emptyList();
}
return classService.getSchSubList(sch.getSchSerId());
} catch (BizException e) {
log.warn("[subjectDictionary] 本校学科字典拉取失败, 降级为编码展示: {}", e.getMessage());
return Collections.emptyList();
}
} }
/** /**
@@ -1120,11 +1112,13 @@ public class TeacherHomeworkV2Service {
// ============================ VO 组装 ============================ // ============================ VO 组装 ============================
private HomeworkV2Vo toVo(Homework h, boolean withAttachments, boolean withProgress) { private HomeworkV2Vo toVo(Homework h, boolean withAttachments, boolean withProgress,
Map<String, String> subjectNames) {
HomeworkV2Vo vo = new HomeworkV2Vo(); HomeworkV2Vo vo = new HomeworkV2Vo();
vo.setId(h.getId()); vo.setId(h.getId());
vo.setTitle(h.getTitle()); vo.setTitle(h.getTitle());
vo.setSubject(h.getSubject()); vo.setSubject(h.getSubject());
vo.setSubjectName(subjectDictService.resolve(h.getSubject(), subjectNames));
vo.setDescription(withAttachments ? h.getContent() : null); vo.setDescription(withAttachments ? h.getContent() : null);
vo.setHwStatus(h.getHwStatus()); vo.setHwStatus(h.getHwStatus());
vo.setHwStatusDesc(HwStatusEnum.of(h.getHwStatus()).getDesc()); vo.setHwStatusDesc(HwStatusEnum.of(h.getHwStatus()).getDesc());