feat(plan): 支持学案生成时指定单词数

- 在 AddLessonPlanReqVO 中新增 wordSize 字段
- 修改 LessonPlansService 接口及实现,支持 wordSize 参数
- 优化学案生成逻辑,按指定单词数切分词汇列表
- 更新前端 LessonPlanDialog,添加单词数输入框
- 修改生成学案接口及调用,传递 wordSize 参数
- 增加查询学生词汇掌握详情接口及实现
- 添加学生词汇统计展示组件及页面集成
- 调整词汇相关 Mapper,修正记忆强度条件范围
- 更新权限配置,允许访问学生单词详情接口
This commit is contained in:
lbw
2025-12-27 17:21:25 +08:00
parent d3cfa80613
commit 494ab77486
20 changed files with 148 additions and 19 deletions

View File

@@ -37,6 +37,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
.notMatch("/student/mastery/detail")
.notMatch("/unit/list")
.notMatch("/vocabulary/list")
.notMatch("/vocabulary/student/detail")
.notMatch("/plan/download")
.notMatch("/login/**")
.check(r -> StpUtil.checkLogin());

View File

@@ -41,8 +41,9 @@ public class LessonPlanController {
public Response<String> generateLessonPlan(@RequestBody AddLessonPlanReqVO addLessonPlanReqVO) {
Integer studentId = addLessonPlanReqVO.getStudentId();
Integer unitId = addLessonPlanReqVO.getUnitId();
Integer wordSize = addLessonPlanReqVO.getWordSize();
try {
taskExecutor.execute(() -> lessonPlanService.generateLessonPlans(studentId, unitId));
taskExecutor.execute(() -> lessonPlanService.generateLessonPlans(studentId, unitId, wordSize));
return Response.success("生成学案成功,请等待 10 分钟");
} catch (Exception e) {
log.error(e.getMessage());

View File

@@ -1,6 +1,8 @@
package com.yinlihupo.enlish.service.controller;
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
import com.yinlihupo.enlish.service.model.vo.vocabulary.FindStudentWordDetailReqVO;
import com.yinlihupo.enlish.service.model.vo.vocabulary.FindStudentWordDetailRspVO;
import com.yinlihupo.enlish.service.model.vo.vocabulary.FindWordTitleReqVO;
import com.yinlihupo.enlish.service.model.vo.vocabulary.FindWordTitleRspVO;
import com.yinlihupo.enlish.service.service.VocabularyService;
@@ -30,4 +32,11 @@ public class VocabularyController {
.build();
return Response.success(findWordTitleRspVO);
}
@PostMapping("student/detail")
@ApiOperationLog(description = "查询学生单词详情")
public Response<FindStudentWordDetailRspVO> findStudentWordDetail(@RequestBody FindStudentWordDetailReqVO vo) {
return Response.success(vocabularyService.findStudentWordDetail(vo.getId()));
}
}

View File

@@ -20,4 +20,8 @@ public interface WordMasteryLogDOMapper {
List<WordMasteryLogDO> selectByStudentIdAndLimitTime(@Param("studentId") Integer studentId);
List<WordMasteryLogDO> selectAllByStudentId(@Param("studentId") Integer studentId);
Integer selectMasteryCount(@Param("studentId") Integer studentId);
Integer selectNotMasteryCount(@Param("studentId") Integer studentId);
}

View File

@@ -13,4 +13,5 @@ public class AddLessonPlanReqVO {
private Integer studentId;
private Integer unitId;
private Integer wordSize;
}

View File

@@ -0,0 +1,15 @@
package com.yinlihupo.enlish.service.model.vo.vocabulary;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class FindStudentWordDetailReqVO {
private Integer id;
}

View File

@@ -0,0 +1,27 @@
package com.yinlihupo.enlish.service.model.vo.vocabulary;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class FindStudentWordDetailRspVO {
/**
* 已掌握单词数
*/
private Integer masteredWordCount;
/**
* 未掌握单词数
*/
private Integer unmasteredWordCount;
/**
* 待审查单词数(推荐使用,简洁通用)
*/
private Integer pendingReviewWordCount;
}

View File

@@ -5,7 +5,7 @@ import com.yinlihupo.enlish.service.domain.dataobject.LessonPlansDO;
import java.util.List;
public interface LessonPlansService {
void generateLessonPlans(Integer studentId, Integer unitId);
void generateLessonPlans(Integer studentId, Integer unitId, Integer wordSize);
List<LessonPlansDO> findLessonPlans(List<Integer> ids);

View File

@@ -2,10 +2,13 @@ package com.yinlihupo.enlish.service.service;
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
import com.yinlihupo.enlish.service.model.vo.vocabulary.FindStudentWordDetailRspVO;
import java.util.List;
public interface VocabularyService {
List<VocabularyBankDO> findVocabularyBankDOListById(List<Integer> ids);
FindStudentWordDetailRspVO findStudentWordDetail(Integer studentId);
}

View File

@@ -37,15 +37,10 @@ public class LessonPlansServiceImpl implements LessonPlansService {
@Resource
private DifyArticleClient difyArticleClient;
@Value("${templates.plan.weekday}")
private String planWeekday;
@Value("${templates.plan.weekend}")
private String planWeekend;
@Override
@Transactional(rollbackFor = Exception.class)
public void generateLessonPlans(Integer studentId, Integer unitId) {
public void generateLessonPlans(Integer studentId, Integer unitId, Integer wordSize) {
List<VocabularyBankDO> vocabularyBankDOS = vocabularyBankDOMapper.selectVocabularyBankDOAllByUnitId(unitId);
UnitDO unitDO = unitDOMapper.selectByPrimaryKey(unitId);
GradeUnitDO gradeUnitDO = gradeUnitDOMapper.selectByUnitId(unitId);
@@ -58,12 +53,19 @@ public class LessonPlansServiceImpl implements LessonPlansService {
int countGap = gapSize / 5;
int syncSize = vocabularyBankDOS.size();
int countSync = syncSize / 5;
wordSize = wordSize <= 0 ? syncSize / 5 : wordSize;
int checkTotal = 50;
List<List<VocabularyBankDO>> weeksSync = new ArrayList<>();
List<List<VocabularyBankDO>> weeksGap = new ArrayList<>();
for (int i = 0; i < 5; i++) {
List<VocabularyBankDO> syncVocabList = vocabularyBankDOS.subList(i * countSync, Math.min((i + 1) * countSync, syncSize));
List<VocabularyBankDO> syncVocabList;
if ((i + 1) * wordSize < syncSize) {
syncVocabList = vocabularyBankDOS.subList(i * wordSize, (i + 1) * wordSize);
} else if (i == 4) {
syncVocabList = vocabularyBankDOS.subList(i * wordSize, syncSize);
} else {
syncVocabList = vocabularyBankDOS.subList((syncSize - i) * wordSize, Math.min((syncSize - i + 1) * wordSize, syncSize));
}
List<VocabularyBankDO> gapVocabList = vocabularyBankListStudentNotMaster.subList(i * countGap, Math.min(i * countGap + countGap, gapSize));
weeksSync.add(syncVocabList);
weeksGap.add(gapVocabList);

View File

@@ -2,6 +2,8 @@ package com.yinlihupo.enlish.service.service.vocabulary;
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
import com.yinlihupo.enlish.service.domain.mapper.WordMasteryLogDOMapper;
import com.yinlihupo.enlish.service.model.vo.vocabulary.FindStudentWordDetailRspVO;
import com.yinlihupo.enlish.service.service.VocabularyService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@@ -14,9 +16,19 @@ public class VocabularyServiceImpl implements VocabularyService {
@Resource
private VocabularyBankDOMapper vocabularyBankDOMapper;
@Resource
private WordMasteryLogDOMapper wordMasteryLogDOMapper;
@Override
public List<VocabularyBankDO> findVocabularyBankDOListById(List<Integer> ids) {
return vocabularyBankDOMapper.selectVocabularyBankDOListByIds(ids);
}
@Override
public FindStudentWordDetailRspVO findStudentWordDetail(Integer studentId) {
Integer wordMastery = wordMasteryLogDOMapper.selectMasteryCount(studentId);
Integer wordNotMastery = wordMasteryLogDOMapper.selectNotMasteryCount(studentId);
Integer total = vocabularyBankDOMapper.selectWordTotal();
return FindStudentWordDetailRspVO.builder().masteredWordCount(wordMastery).unmasteredWordCount(wordNotMastery).pendingReviewWordCount(total - wordMastery - wordNotMastery).build();
}
}

View File

@@ -26,7 +26,7 @@ templates:
count: 100
data: C:\project\tess
plan:
weekday: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\tem_study_plan_v1.docx
weekday: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\tem_study_plan_v2.docx
weekend: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\study_plan_review_v1.docx
plan_day: 7
tmp:

View File

@@ -94,7 +94,7 @@
and id in (
select word_id
from word_mastery_log
where memory_strength < 0
where memory_strength <= 0
and student_id = #{studentId}
)
]]>

View File

@@ -22,6 +22,7 @@
order by memory_strength desc
limit #{limit}
</select>
<select id="selectStudentStrengthCount" resultType="java.lang.Integer">
select count(*)
from word_mastery_log
@@ -58,9 +59,27 @@
where student_id = #{studentId}
and update_time between date_sub(now(), interval 7 day) and now()
</select>
<select id="selectAllByStudentId" resultMap="BaseResultMap">
select *
from word_mastery_log
where student_id = #{studentId}
</select>
<select id="selectMasteryCount" resultType="java.lang.Integer">
select count(*)
from word_mastery_log
where student_id = #{studentId}
and memory_strength >= 1
</select>
<select id="selectNotMasteryCount" resultType="java.lang.Integer">
<![CDATA[
select count(*)
from word_mastery_log
where student_id = #{studentId}
and memory_strength < 0
]]>
</select>
</mapper>

View File

@@ -13,6 +13,6 @@ public class PlanTest {
@Test
public void test() {
lessonPlansService.generateLessonPlans(2, 146);
}
}