refactor(ai): 重构AI客户端类并添加句子分析接口
- 将 DifyArticleClient 重命名为 DifyClient,调整相关调用引用 - 增加 sendSentenceAnalyze 方法,实现批量词汇句子分析功能 - 更新配置文件,新增 analyzeKey 和 sentenceKey 两个AI接口密钥配置 - 修改LessonPlansServiceImpl中生成连词成句功能,调用新句子分析接口 - 优化LessonPlanConstant常量,调整部分键名格式,去除空格 - 修改相关测试类适配 DifyClient 改动 - 相关VO类添加学生姓名和试题名称字段,丰富展示数据 - 更新前端table组件,替换显示学生姓名、班级名、年级名等信息字段 - 调整路由首页路径为“/”,修改Header组件对应链接 - 其他若干细节修改,如异常日志优化、时间格式展示等
This commit is contained in:
@@ -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())
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)) // 读取超时
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Binary file not shown.
@@ -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();
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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: '班级'
|
||||||
|
|||||||
Reference in New Issue
Block a user