refactor(ai): 重构AI客户端类并添加句子分析接口

- 将 DifyArticleClient 重命名为 DifyClient,调整相关调用引用
- 增加 sendSentenceAnalyze 方法,实现批量词汇句子分析功能
- 更新配置文件,新增 analyzeKey 和 sentenceKey 两个AI接口密钥配置
- 修改LessonPlansServiceImpl中生成连词成句功能,调用新句子分析接口
- 优化LessonPlanConstant常量,调整部分键名格式,去除空格
- 修改相关测试类适配 DifyClient 改动
- 相关VO类添加学生姓名和试题名称字段,丰富展示数据
- 更新前端table组件,替换显示学生姓名、班级名、年级名等信息字段
- 调整路由首页路径为“/”,修改Header组件对应链接
- 其他若干细节修改,如异常日志优化、时间格式展示等
This commit is contained in:
lbw
2025-12-30 10:30:26 +08:00
parent 5ebf40101d
commit 0f5169c1d7
21 changed files with 147 additions and 59 deletions

View File

@@ -113,6 +113,8 @@ public class ExamWordsController {
.builder() .builder()
.id(examWordsJudgeResultDO.getId()) .id(examWordsJudgeResultDO.getId())
.studentId(examWordsJudgeResultDO.getStudentId()) .studentId(examWordsJudgeResultDO.getStudentId())
.studentName(studentService.getStudentById(examWordsJudgeResultDO.getStudentId()).getName())
.examWordsTitle(examWordsService.getExamWordsDOById(examWordsJudgeResultDO.getExamWordsId()).getTitle())
.examWordsId(examWordsJudgeResultDO.getExamWordsId()) .examWordsId(examWordsJudgeResultDO.getExamWordsId())
.startDate(examWordsJudgeResultDO.getStartDate()) .startDate(examWordsJudgeResultDO.getStartDate())
.correctWordCount(examWordsJudgeResultDO.getCorrectWordCount()) .correctWordCount(examWordsJudgeResultDO.getCorrectWordCount())

View File

@@ -48,6 +48,8 @@ public class StudentController {
.id(studentDO.getId()) .id(studentDO.getId())
.name(studentDO.getName()) .name(studentDO.getName())
.classId(studentDO.getClassId()) .classId(studentDO.getClassId())
.className(classService.findClassById(studentDO.getClassId()).getTitle())
.gradeName(gradeService.findByClassId(studentDO.getGradeId()).getTitle())
.gradeId(studentDO.getGradeId()) .gradeId(studentDO.getGradeId())
.build()).toList(); .build()).toList();

View File

@@ -0,0 +1,27 @@
package com.yinlihupo.enlish.service.model.bo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Sentence {
@JsonProperty("target_word")
private String targetWord;
@JsonProperty("grade_level")
private String gradeLevel;
@JsonProperty("question")
private String question;
@JsonProperty("chinese_clue")
private String chineseClue;
@JsonProperty("correct_answer")
private String correctAnswer;
@JsonProperty("grammar_point")
private String grammarPoint;
}

View File

@@ -12,6 +12,7 @@ import java.time.LocalDateTime;
@Data @Data
@Builder @Builder
public class ExamWordsResultRspVO { public class ExamWordsResultRspVO {
private Integer id; private Integer id;
private String ansSheetPath; private String ansSheetPath;
@@ -20,6 +21,10 @@ public class ExamWordsResultRspVO {
private Integer examWordsId; private Integer examWordsId;
private String studentName;
private String examWordsTitle;
private Integer correctWordCount; private Integer correctWordCount;
private Integer wrongWordCount; private Integer wrongWordCount;

View File

@@ -15,4 +15,6 @@ public class StudentItemRspVO {
private String name; private String name;
private Integer classId; private Integer classId;
private Integer gradeId; private Integer gradeId;
private String className;
private String gradeName;
} }

View File

@@ -13,4 +13,6 @@ public interface ExamWordsService {
int saveExamWordsPngToDbAndLocal(MultipartFile file); int saveExamWordsPngToDbAndLocal(MultipartFile file);
void updateExamWordsWordIdsOrder(ExamWordsDO examWordsDO); void updateExamWordsWordIdsOrder(ExamWordsDO examWordsDO);
ExamWordsDO getExamWordsDOById(Integer id);
} }

View File

@@ -191,5 +191,10 @@ public class ExamWordsServiceImpl implements ExamWordsService {
examWordsDOMapper.updateWordIdsOrder(examWordsDO); examWordsDOMapper.updateWordIdsOrder(examWordsDO);
} }
@Override
public ExamWordsDO getExamWordsDOById(Integer id) {
return examWordsDOMapper.selectById(id);
}
} }

View File

@@ -3,14 +3,14 @@ package com.yinlihupo.enlish.service.service.plan;
import com.yinlihupo.enlish.service.constant.LessonPlanConstant; import com.yinlihupo.enlish.service.constant.LessonPlanConstant;
import com.yinlihupo.enlish.service.domain.dataobject.*; import com.yinlihupo.enlish.service.domain.dataobject.*;
import com.yinlihupo.enlish.service.domain.mapper.*; import com.yinlihupo.enlish.service.domain.mapper.*;
import com.yinlihupo.enlish.service.model.bo.Sentence;
import com.yinlihupo.enlish.service.service.LessonPlansService; import com.yinlihupo.enlish.service.service.LessonPlansService;
import com.yinlihupo.enlish.service.utils.DifyArticleClient; import com.yinlihupo.enlish.service.utils.DifyClient;
import com.yinlihupo.enlish.service.utils.StringToPlanMapUtil; import com.yinlihupo.enlish.service.utils.StringToPlanMapUtil;
import com.yinlihupo.framework.common.util.JsonUtils; import com.yinlihupo.framework.common.util.JsonUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -35,11 +35,10 @@ public class LessonPlansServiceImpl implements LessonPlansService {
@Resource @Resource
private GradeDOMapper gradeDOMapper; private GradeDOMapper gradeDOMapper;
@Resource @Resource
private DifyArticleClient difyArticleClient; private DifyClient difyClient;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void generateLessonPlans(Integer studentId, Integer unitId, Integer wordSize) { public void generateLessonPlans(Integer studentId, Integer unitId, Integer wordSize) {
List<VocabularyBankDO> vocabularyBankDOS = vocabularyBankDOMapper.selectVocabularyBankDOAllByUnitId(unitId); List<VocabularyBankDO> vocabularyBankDOS = vocabularyBankDOMapper.selectVocabularyBankDOAllByUnitId(unitId);
UnitDO unitDO = unitDOMapper.selectByPrimaryKey(unitId); UnitDO unitDO = unitDOMapper.selectByPrimaryKey(unitId);
@@ -57,14 +56,13 @@ public class LessonPlansServiceImpl implements LessonPlansService {
int checkTotal = 50; int checkTotal = 50;
List<List<VocabularyBankDO>> weeksSync = new ArrayList<>(); List<List<VocabularyBankDO>> weeksSync = new ArrayList<>();
List<List<VocabularyBankDO>> weeksGap = new ArrayList<>(); List<List<VocabularyBankDO>> weeksGap = new ArrayList<>();
int j = 0;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
List<VocabularyBankDO> syncVocabList; List<VocabularyBankDO> syncVocabList;
if ((i + 1) * wordSize < syncSize) { if ((i + 1) * wordSize < syncSize) {
syncVocabList = vocabularyBankDOS.subList(i * wordSize, (i + 1) * wordSize); syncVocabList = vocabularyBankDOS.subList(i * wordSize, (i + 1) * wordSize);
} else if (i == 4) {
syncVocabList = vocabularyBankDOS.subList(i * wordSize, syncSize);
} else { } else {
syncVocabList = vocabularyBankDOS.subList((syncSize - i) * wordSize, Math.min((syncSize - i + 1) * wordSize, syncSize)); syncVocabList = new ArrayList<>(weeksSync.get(Math.min(j++, weeksSync.size() - 1)));
} }
List<VocabularyBankDO> gapVocabList = vocabularyBankListStudentNotMaster.subList(i * countGap, Math.min(i * countGap + countGap, gapSize)); List<VocabularyBankDO> gapVocabList = vocabularyBankListStudentNotMaster.subList(i * countGap, Math.min(i * countGap + countGap, gapSize));
weeksSync.add(syncVocabList); weeksSync.add(syncVocabList);
@@ -119,7 +117,7 @@ public class LessonPlansServiceImpl implements LessonPlansService {
studentLessonPlansDOMapper.insert(studentLessonPlansDO); studentLessonPlansDOMapper.insert(studentLessonPlansDO);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); log.info("生成第{}天计划失败,失败原因 {}", i + 1, e.getMessage());
} }
log.info("生成第{}天计划成功", i + 1); log.info("生成第{}天计划成功", i + 1);
} }
@@ -241,6 +239,11 @@ public class LessonPlansServiceImpl implements LessonPlansService {
data.put("articleBans", mapB.get(LessonPlanConstant.ANSWER_KEY_EXPLANATION)); data.put("articleBans", mapB.get(LessonPlanConstant.ANSWER_KEY_EXPLANATION));
data.put("articleBtran", mapB.get(LessonPlanConstant.FULL_TRANSLATION)); data.put("articleBtran", mapB.get(LessonPlanConstant.FULL_TRANSLATION));
// 连词成句
List<Sentence> sentences = difyClient.sendSentenceAnalyze(syncVocabList.subList(0, Math.max(10, syncVocabList.size())), gradeDO.getTitle());
data.put("sentences", sentences);
data.put("sentencesAns", sentences);
log.info( "生成连词成句成功");
// LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); // LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
// Configure config = Configure.builder() // Configure config = Configure.builder()
// .bind("syncVocabList", policy) // .bind("syncVocabList", policy)
@@ -271,7 +274,7 @@ public class LessonPlansServiceImpl implements LessonPlansService {
int i = 0; int i = 0;
do { do {
log.info("第{}次生成文章中文开始", ++i); log.info("第{}次生成文章中文开始", ++i);
String answer = difyArticleClient.sendChat(string, String.valueOf(studentId) + UUID.randomUUID(), null).getAnswer(); String answer = difyClient.sendChat(string, String.valueOf(studentId) + UUID.randomUUID(), null).getAnswer();
map = StringToPlanMapUtil.parseTextToMap(answer); map = StringToPlanMapUtil.parseTextToMap(answer);
} while (map.get(LessonPlanConstant.TITLE) == null } while (map.get(LessonPlanConstant.TITLE) == null
|| map.get(LessonPlanConstant.PASSAGE) == null || map.get(LessonPlanConstant.PASSAGE) == null

View File

@@ -9,11 +9,10 @@ import com.yinlihupo.enlish.service.model.bo.exam.ExamWordsJudgeResultDetail;
import com.yinlihupo.enlish.service.model.bo.exam.WordMasteryDetail; import com.yinlihupo.enlish.service.model.bo.exam.WordMasteryDetail;
import com.yinlihupo.enlish.service.model.vo.student.AddStudentReqVO; import com.yinlihupo.enlish.service.model.vo.student.AddStudentReqVO;
import com.yinlihupo.enlish.service.service.StudentService; import com.yinlihupo.enlish.service.service.StudentService;
import com.yinlihupo.enlish.service.utils.DifyArticleClient; import com.yinlihupo.enlish.service.utils.DifyClient;
import com.yinlihupo.framework.common.util.JsonUtils; import com.yinlihupo.framework.common.util.JsonUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -37,7 +36,7 @@ public class StudentServiceImpl implements StudentService {
@Resource @Resource
private ExamWordsJudgeResultDOMapper examWordsJudgeResultDOMapper; private ExamWordsJudgeResultDOMapper examWordsJudgeResultDOMapper;
@Resource @Resource
private DifyArticleClient difyArticleClient; private DifyClient difyClient;
@Resource @Resource
private RedisTemplate<String, Object> redisTemplate; private RedisTemplate<String, Object> redisTemplate;
@Resource @Resource
@@ -159,7 +158,7 @@ public class StudentServiceImpl implements StudentService {
studentStudyInfo.put("单词掌握情况", wordMasteryDetails); studentStudyInfo.put("单词掌握情况", wordMasteryDetails);
try { try {
String analyze = difyArticleClient.sendStudentAnalyze(JsonUtils.toJsonString(studentStudyInfo)).getAnswer(); String analyze = difyClient.sendStudentAnalyze(JsonUtils.toJsonString(studentStudyInfo)).getAnswer();
// 设置过期时间 3 天 // 设置过期时间 3 天
redisTemplate.opsForValue().set(key, analyze); redisTemplate.opsForValue().set(key, analyze);
redisTemplate.expire(key, 3, TimeUnit.DAYS); redisTemplate.expire(key, 3, TimeUnit.DAYS);

View File

@@ -3,6 +3,9 @@ package com.yinlihupo.enlish.service.utils; // 修改为你的包名
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
import com.yinlihupo.enlish.service.model.bo.Sentence;
import com.yinlihupo.framework.common.util.JsonUtils;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@@ -14,21 +17,25 @@ import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.time.Duration; import java.time.Duration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
@Component @Component
public class DifyArticleClient { public class DifyClient {
@Value("${ai.key}") @Value("${ai.key}")
private String apiKey; private String apiKey;
private String anaKey = "app-hrUFcopdcpnflsvpHWRuBfCp"; @Value("${ai.analyzeKey}")
private String analyzeKey;
@Value("${ai.sentenceKey}")
private String sentenceKey;
@Value("${ai.url}") @Value("${ai.url}")
private String baseUrl; private String baseUrl;
private final HttpClient httpClient; private final HttpClient httpClient;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
// 构造函数 // 构造函数
public DifyArticleClient() { public DifyClient() {
this.httpClient = HttpClient.newBuilder() this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10)) // 连接超时 .connectTimeout(Duration.ofSeconds(10)) // 连接超时
@@ -36,6 +43,48 @@ public class DifyArticleClient {
this.objectMapper = new ObjectMapper(); this.objectMapper = new ObjectMapper();
} }
public List<Sentence> sendSentenceAnalyze(List<VocabularyBankDO> list, String grade) throws Exception {
// 1. 构建请求体对象
ChatRequest payload = new ChatRequest();
payload.setQuery(JsonUtils.toJsonString(list.stream().map(VocabularyBankDO::getWord).toList()));
payload.setUser("admin");
HashMap<String, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("grade", grade);
payload.setResponseMode("blocking"); // 使用阻塞模式一次性返回
payload.setInputs(objectObjectHashMap);
// 2. 序列化为 JSON 字符串
String jsonBody = objectMapper.writeValueAsString(payload);
// 3. 构建 HTTP 请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl))
.header("Authorization", "Bearer " + sentenceKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.timeout(Duration.ofSeconds(30)) // 读取超时
.build();
// 4. 发送请求
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// 5. 检查状态码
if (response.statusCode() != 200) {
throw new RuntimeException("Dify 请求失败: HTTP " + response.statusCode() + " | Body: " + response.body());
}
// 6. 反序列化响应体
DifyResponse difyResponse = objectMapper.readValue(response.body(), DifyResponse.class);
String answer = difyResponse.getAnswer();
answer = answer.replace("json", "");
answer = answer.replace("```", "");
return JsonUtils.parseList(answer, Sentence.class);
}
public DifyResponse sendStudentAnalyze(String query) throws Exception { public DifyResponse sendStudentAnalyze(String query) throws Exception {
String endpoint = this.baseUrl; String endpoint = this.baseUrl;
@@ -52,7 +101,7 @@ public class DifyArticleClient {
// 3. 构建 HTTP 请求 // 3. 构建 HTTP 请求
HttpRequest request = HttpRequest.newBuilder() HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint)) .uri(URI.create(endpoint))
.header("Authorization", "Bearer " + anaKey) .header("Authorization", "Bearer " + analyzeKey)
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody)) .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.timeout(Duration.ofSeconds(30)) // 读取超时 .timeout(Duration.ofSeconds(30)) // 读取超时

View File

@@ -50,6 +50,8 @@ public class WordExportUtil {
.bind("mixedDrill", policyLessonPlanWeekday) .bind("mixedDrill", policyLessonPlanWeekday)
.bind("checkList", policyLessonPlanWeekday) .bind("checkList", policyLessonPlanWeekday)
.bind("checkListAns", policyLessonPlanWeekday) .bind("checkListAns", policyLessonPlanWeekday)
.bind("sentences", policyLessonPlanWeekday)
.bind("sentencesAns", policyLessonPlanWeekday)
.build(); .build();
LoopRowTableRenderPolicy policyLessonPlan = new LoopRowTableRenderPolicy(); LoopRowTableRenderPolicy policyLessonPlan = new LoopRowTableRenderPolicy();

View File

@@ -35,7 +35,7 @@ templates:
count: 100 count: 100
data: C:\project\tess data: C:\project\tess
plan: plan:
weekday: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\tem_study_plan_v3.docx weekday: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\tem_study_plan_v4.docx
weekend: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\study_plan_review_v1.docx weekend: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\study_plan_review_v1.docx
plan_day: 7 plan_day: 7
tmp: tmp:
@@ -43,6 +43,8 @@ tmp:
ai: ai:
key: app-loC6IrJpj4cS54MAYp73QtGl key: app-loC6IrJpj4cS54MAYp73QtGl
analyzeKey: app-hrUFcopdcpnflsvpHWRuBfCp
sentenceKey: app-Emk5YQBaD2YruRXuE5sK1vEU
url: https://chat.cosonggle.com/v1/chat-messages url: https://chat.cosonggle.com/v1/chat-messages
aliyun: aliyun:

View File

@@ -1,47 +1,35 @@
package com.yinlihupo.enlish.service.ai; package com.yinlihupo.enlish.service.ai;
import com.yinlihupo.enlish.service.utils.DifyArticleClient; import com.yinlihupo.enlish.service.domain.dataobject.VocabularyBankDO;
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
import com.yinlihupo.enlish.service.model.bo.Sentence;
import com.yinlihupo.enlish.service.utils.DifyClient;
import com.yinlihupo.enlish.service.utils.StringToPlanMapUtil; import com.yinlihupo.enlish.service.utils.StringToPlanMapUtil;
import com.yinlihupo.framework.common.util.JsonUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Map; import java.util.Map;
@SpringBootTest @SpringBootTest
public class AITest { public class AITest {
@Resource @Resource
private DifyArticleClient client; private DifyClient client;
@Resource
private VocabularyBankDOMapper vocabularyBankDOMapper;
@Test @Test
public void test1() throws IOException { public void test1() throws IOException {
try { try {
// 2. 第一轮对话 (没有 conversation_id)
System.out.println("--- Round 1 ---");
String userId = "user-1001";
DifyArticleClient.DifyResponse response1 = client.sendChat("ruler, pencil, eraser, crayon, bag, pen, book, red, green, yellow, blue, face, ear, eye, nose, mouth, duck, pig, cat, bear, dog, elephant, monkey, bird, tiger, panda, bread, juice, egg, milk", userId, null);
//System.out.println("AI 回复: " + response1.getAnswer()); List<VocabularyBankDO> vocabularyBankDOS = vocabularyBankDOMapper.selectVocabularyBankDOAllByUnitId(269);
System.out.println("当前会话ID: " + response1.getConversationId()); List<Sentence> sentences = client.sendSentenceAnalyze(vocabularyBankDOS, "小学4年级");
// // 3. 第二轮对话 (传入上一轮的 conversation_id 以保持记忆)
// System.out.println("\n--- Round 2 ---");
// // 注意这里传入了 response1.getConversationId()
// DifyClient.DifyResponse response2 = client.sendChat("我刚才说了我叫什么?", userId, response1.getConversationId());
//
// System.out.println("AI 回复: " + response2.getAnswer());
System.out.println("\n--- Round 2 ---");
Map<String, String> stringStringMap = StringToPlanMapUtil.parseTextToMap(response1.getAnswer());
System.out.println(stringStringMap.get("Title"));
System.out.println(stringStringMap.get("The Passage"));
System.out.println(stringStringMap.get("Quiz"));
System.out.println(stringStringMap.get("Answer Key & Explanation"));
System.out.println(stringStringMap.get("Full Translation"));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@@ -9,7 +9,7 @@ import com.yinlihupo.enlish.service.model.bo.CoordinatesXY;
import com.yinlihupo.enlish.service.model.bo.StudentExamId; import com.yinlihupo.enlish.service.model.bo.StudentExamId;
import com.yinlihupo.enlish.service.service.ExamWordsJudgeService; import com.yinlihupo.enlish.service.service.ExamWordsJudgeService;
import com.yinlihupo.enlish.service.service.StudentService; import com.yinlihupo.enlish.service.service.StudentService;
import com.yinlihupo.enlish.service.utils.DifyArticleClient; import com.yinlihupo.enlish.service.utils.DifyClient;
import com.yinlihupo.enlish.service.utils.PngUtil; import com.yinlihupo.enlish.service.utils.PngUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -28,7 +28,7 @@ public class ExamWordsJudgeServiceTest {
@Resource @Resource
private StudentService studentService; private StudentService studentService;
@Resource @Resource
private DifyArticleClient difyArticleClient; private DifyClient difyClient;
@Resource @Resource
private ExamWordsDOMapper examWordsDOMapper; private ExamWordsDOMapper examWordsDOMapper;
@Resource @Resource
@@ -64,7 +64,7 @@ public class ExamWordsJudgeServiceTest {
public void selectExamWordsJudgeResult2() { public void selectExamWordsJudgeResult2() {
String s = studentService.analyzeStudentStudy(1); String s = studentService.analyzeStudentStudy(1);
try { try {
DifyArticleClient.DifyResponse difyResponse = difyArticleClient.sendStudentAnalyze(s); DifyClient.DifyResponse difyResponse = difyClient.sendStudentAnalyze(s);
String answer = difyResponse.getAnswer(); String answer = difyResponse.getAnswer();
log.info("answer:{}", answer); log.info("answer:{}", answer);
} catch (Exception e) { } catch (Exception e) {

View File

@@ -59,7 +59,7 @@
aria-current="page">Home</a> aria-current="page">Home</a>
</li> </li>
<li> <li>
<router-link to="/class" <router-link to="/"
class="block py-2 pr-4 pl-3 text-gray-700 border-b border-gray-100 hover:bg-gray-50 lg:hover:bg-transparent lg:border-0 lg:hover:text-primary-700 lg:p-0 dark:text-gray-400 lg:dark:hover:text-white dark:hover:bg-gray-700 dark:hover:text-white lg:dark:hover:bg-transparent dark:border-gray-700"> class="block py-2 pr-4 pl-3 text-gray-700 border-b border-gray-100 hover:bg-gray-50 lg:hover:bg-transparent lg:border-0 lg:hover:text-primary-700 lg:p-0 dark:text-gray-400 lg:dark:hover:text-white dark:hover:bg-gray-700 dark:hover:text-white lg:dark:hover:bg-transparent dark:border-gray-700">
班级 班级
</router-link> </router-link>

View File

@@ -155,7 +155,7 @@ async function userLogin() {
if (mode.value === 'login') { if (mode.value === 'login') {
try { setToken(data.data) } catch { } try { setToken(data.data) } catch { }
ElMessage.success('登录成功') ElMessage.success('登录成功')
router.push('/class') router.push('/')
} else { } else {
ElMessage.success('注册成功') ElMessage.success('注册成功')
mode.value = 'login' mode.value = 'login'

View File

@@ -13,7 +13,6 @@
<div class="text-lg font-semibold mb-4">班级列表</div> <div class="text-lg font-semibold mb-4">班级列表</div>
<el-table ref="classTableRef" :data="classes" border class="w-full" v-loading="loading" highlight-current-row <el-table ref="classTableRef" :data="classes" border class="w-full" v-loading="loading" highlight-current-row
row-key="id" :current-row-key="selectedClassId" @row-click="onClassRowClick"> row-key="id" :current-row-key="selectedClassId" @row-click="onClassRowClick">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="title" label="班级名称" min-width="120" /> <el-table-column prop="title" label="班级名称" min-width="120" />
<el-table-column prop="gradeName" label="年级" min-width="120" /> <el-table-column prop="gradeName" label="年级" min-width="120" />
<el-table-column label="操作" width="120" fixed="right"> <el-table-column label="操作" width="120" fixed="right">
@@ -57,10 +56,9 @@
<el-table ref="studentTableRef" :data="students" border class="w-full" <el-table ref="studentTableRef" :data="students" border class="w-full"
v-loading="studentLoading" @selection-change="onStudentSelectionChange"> v-loading="studentLoading" @selection-change="onStudentSelectionChange">
<el-table-column type="selection" width="48" /> <el-table-column type="selection" width="48" />
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="name" label="姓名" min-width="120" /> <el-table-column prop="name" label="姓名" min-width="120" />
<el-table-column prop="classId" label="班级ID" width="100" /> <el-table-column prop="className" label="班级" min-width="120" />
<el-table-column prop="gradeId" label="年级ID" width="100" /> <el-table-column prop="gradeName" label="年级" min-width="120" />
<el-table-column label="操作" width="180" fixed="right"> <el-table-column label="操作" width="180" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" size="small" @click.stop="onViewStudent(row)">详情</el-button> <el-button type="primary" size="small" @click.stop="onViewStudent(row)">详情</el-button>
@@ -94,7 +92,6 @@
<div class="text-lg font-semibold mb-4">年级列表</div> <div class="text-lg font-semibold mb-4">年级列表</div>
<el-table ref="gradeTableRef" :data="grades" border class="w-full" highlight-current-row <el-table ref="gradeTableRef" :data="grades" border class="w-full" highlight-current-row
row-key="id" :current-row-key="selectedGradeId" @row-click="onGradeRowClick"> row-key="id" :current-row-key="selectedGradeId" @row-click="onGradeRowClick">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="title" label="年级名称" min-width="160" /> <el-table-column prop="title" label="年级名称" min-width="160" />
</el-table> </el-table>
<div class="mt-4 flex justify-end"> <div class="mt-4 flex justify-end">

View File

@@ -26,9 +26,8 @@
v-loading="loading" v-loading="loading"
@row-click="handleRowClick" @row-click="handleRowClick"
> >
<el-table-column prop="id" label="ID" width="80" /> <el-table-column prop="studentName" label="学生姓名" min-width="70" />
<el-table-column prop="studentId" label="学生ID" width="100" /> <el-table-column prop="examWordsTitle" label="试题名称" min-width="100" />
<el-table-column prop="examWordsId" label="试题ID" width="100" />
<el-table-column prop="correctWordCount" label="正确词数" width="110" /> <el-table-column prop="correctWordCount" label="正确词数" width="110" />
<el-table-column prop="wrongWordCount" label="错误词数" width="110" /> <el-table-column prop="wrongWordCount" label="错误词数" width="110" />
<el-table-column label="完成状态" width="110"> <el-table-column label="完成状态" width="110">
@@ -38,7 +37,11 @@
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="startDate" label="开始时间" min-width="160" /> <el-table-column prop="startDate" label="开始时间" min-width="160">
<template #default="{ row }">
{{ row.startDate.replace('T', ' ') }}
</template>
</el-table-column>
<el-table-column prop="msg" label="判卷结算" min-width="160" /> <el-table-column prop="msg" label="判卷结算" min-width="160" />
</el-table> </el-table>
<div class="mt-4 flex justify-end"> <div class="mt-4 flex justify-end">

View File

@@ -10,7 +10,7 @@ import Login from '@/pages/Login.vue'
// 统一在这里声明所有路由 // 统一在这里声明所有路由
const routes = [ const routes = [
{ {
path: '/class', path: '/',
component: Class, component: Class,
meta: { meta: {
title: '班级' title: '班级'