|
|
@@ -0,0 +1,258 @@
|
|
|
+package com.pharmacopoeia.service;
|
|
|
+
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.pharmacopoeia.entity.Drug;
|
|
|
+import com.pharmacopoeia.entity.KnowledgePoint;
|
|
|
+import com.pharmacopoeia.entity.Question;
|
|
|
+import com.pharmacopoeia.repository.DrugRepository;
|
|
|
+import com.pharmacopoeia.repository.KnowledgePointRepository;
|
|
|
+import com.pharmacopoeia.repository.QuestionRepository;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class AdminKnowledgeService {
|
|
|
+
|
|
|
+ private final DrugRepository drugRepository;
|
|
|
+ private final KnowledgePointRepository knowledgePointRepository;
|
|
|
+ private final QuestionRepository questionRepository;
|
|
|
+ private final ObjectMapper mapper = new ObjectMapper();
|
|
|
+
|
|
|
+ public AdminKnowledgeService(DrugRepository drugRepository,
|
|
|
+ KnowledgePointRepository knowledgePointRepository,
|
|
|
+ QuestionRepository questionRepository) {
|
|
|
+ this.drugRepository = drugRepository;
|
|
|
+ this.knowledgePointRepository = knowledgePointRepository;
|
|
|
+ this.questionRepository = questionRepository;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Drug CRUD ====================
|
|
|
+
|
|
|
+ public List<Map<String, Object>> listDrugs(String keyword, String category, int page, int pageSize) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Optional<Map<String, Object>> getDrug(String drugId) {
|
|
|
+ return drugRepository.findByDrugId(drugId).map(this::drugToMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> createDrug(Map<String, Object> req) {
|
|
|
+ Drug drug = Drug.builder()
|
|
|
+ .drugId((String) req.get("drugId"))
|
|
|
+ .name((String) req.get("name"))
|
|
|
+ .nameEn((String) req.get("nameEn"))
|
|
|
+ .pinyin((String) req.get("pinyin"))
|
|
|
+ .category((String) req.get("category"))
|
|
|
+ .subcategory((String) req.get("subcategory"))
|
|
|
+ .approvalNumber((String) req.get("approvalNumber"))
|
|
|
+ .sourceVersion((String) req.get("sourceVersion"))
|
|
|
+ .sourceVolume((String) req.get("sourceVolume"))
|
|
|
+ .sourcePage((String) req.get("sourcePage"))
|
|
|
+ .isActive(true)
|
|
|
+ .build();
|
|
|
+ drug.setSections(castToMap(req.get("sections")));
|
|
|
+ drugRepository.save(drug);
|
|
|
+ return toMap("drug_id", drug.getDrugId(), "message", "已创建");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> updateDrug(String drugId, Map<String, Object> req) {
|
|
|
+ return drugRepository.findByDrugId(drugId).map(d -> {
|
|
|
+ if (req.containsKey("name")) d.setName((String) req.get("name"));
|
|
|
+ if (req.containsKey("nameEn")) d.setNameEn((String) req.get("nameEn"));
|
|
|
+ if (req.containsKey("pinyin")) d.setPinyin((String) req.get("pinyin"));
|
|
|
+ if (req.containsKey("category")) d.setCategory((String) req.get("category"));
|
|
|
+ if (req.containsKey("subcategory")) d.setSubcategory((String) req.get("subcategory"));
|
|
|
+ if (req.containsKey("approvalNumber")) d.setApprovalNumber((String) req.get("approvalNumber"));
|
|
|
+ if (req.containsKey("sections")) d.setSections(castToMap(req.get("sections")));
|
|
|
+ if (req.containsKey("sourceVersion")) d.setSourceVersion((String) req.get("sourceVersion"));
|
|
|
+ if (req.containsKey("sourceVolume")) d.setSourceVolume((String) req.get("sourceVolume"));
|
|
|
+ if (req.containsKey("sourcePage")) d.setSourcePage((String) req.get("sourcePage"));
|
|
|
+ if (req.containsKey("isActive")) d.setIsActive((Boolean) req.get("isActive"));
|
|
|
+ drugRepository.save(d);
|
|
|
+ return toMap("drug_id", drugId, "message", "已更新");
|
|
|
+ }).orElseGet(() -> toMap("drug_id", drugId, "message", "药品不存在"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> deleteDrug(String drugId) {
|
|
|
+ return drugRepository.findByDrugId(drugId).map(d -> {
|
|
|
+ d.setIsActive(false);
|
|
|
+ drugRepository.save(d);
|
|
|
+ return toMap("drug_id", drugId, "message", "已标记删除");
|
|
|
+ }).orElseGet(() -> toMap("drug_id", drugId, "message", "药品不存在"));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== KnowledgePoint CRUD ====================
|
|
|
+
|
|
|
+ public List<Map<String, Object>> listKnowledgePoints(String subject, String chapterId,
|
|
|
+ Integer difficulty, String frequency,
|
|
|
+ int page, int pageSize) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Optional<KnowledgePoint> getKnowledgePoint(String pointId) {
|
|
|
+ return knowledgePointRepository.findByPointId(pointId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> createKnowledgePoint(Map<String, Object> req) {
|
|
|
+ KnowledgePoint kp = KnowledgePoint.builder()
|
|
|
+ .pointId((String) req.get("pointId"))
|
|
|
+ .subject((String) req.get("subject"))
|
|
|
+ .chapterId((String) req.get("chapterId"))
|
|
|
+ .chapterName((String) req.get("chapterName"))
|
|
|
+ .title((String) req.get("title"))
|
|
|
+ .content((String) req.get("content"))
|
|
|
+ .difficulty(req.get("difficulty") != null ? (Integer) req.get("difficulty") : 1)
|
|
|
+ .frequency((String) req.get("frequency"))
|
|
|
+ .source((String) req.get("source"))
|
|
|
+ .build();
|
|
|
+ if (req.get("relatedDrugs") != null) {
|
|
|
+ try { kp.setRelatedDrugs(mapper.writeValueAsString(req.get("relatedDrugs"))); } catch (JsonProcessingException ignored) {}
|
|
|
+ }
|
|
|
+ knowledgePointRepository.save(kp);
|
|
|
+ return toMap("point_id", kp.getPointId(), "message", "已创建");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> updateKnowledgePoint(String pointId, Map<String, Object> req) {
|
|
|
+ return knowledgePointRepository.findByPointId(pointId).map(kp -> {
|
|
|
+ if (req.containsKey("chapterName")) kp.setChapterName((String) req.get("chapterName"));
|
|
|
+ if (req.containsKey("title")) kp.setTitle((String) req.get("title"));
|
|
|
+ if (req.containsKey("content")) kp.setContent((String) req.get("content"));
|
|
|
+ if (req.containsKey("difficulty")) kp.setDifficulty((Integer) req.get("difficulty"));
|
|
|
+ if (req.containsKey("frequency")) kp.setFrequency((String) req.get("frequency"));
|
|
|
+ if (req.containsKey("source")) kp.setSource((String) req.get("source"));
|
|
|
+ if (req.containsKey("relatedDrugs")) {
|
|
|
+ try { kp.setRelatedDrugs(mapper.writeValueAsString(req.get("relatedDrugs"))); } catch (JsonProcessingException ignored) {}
|
|
|
+ }
|
|
|
+ knowledgePointRepository.save(kp);
|
|
|
+ return toMap("point_id", pointId, "message", "已更新");
|
|
|
+ }).orElseGet(() -> toMap("point_id", pointId, "message", "知识点不存在"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> deleteKnowledgePoint(String pointId) {
|
|
|
+ knowledgePointRepository.findByPointId(pointId).ifPresent(knowledgePointRepository::delete);
|
|
|
+ return toMap("point_id", pointId, "message", "已删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Question CRUD ====================
|
|
|
+
|
|
|
+ public List<Map<String, Object>> listQuestions(String subject, String chapterId,
|
|
|
+ String questionType, Integer difficulty,
|
|
|
+ Boolean audited, int page, int pageSize) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Optional<Question> getQuestion(String questionId) {
|
|
|
+ return questionRepository.findByQuestionId(questionId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> createQuestion(Map<String, Object> req) {
|
|
|
+ Question q = Question.builder()
|
|
|
+ .questionId((String) req.get("questionId"))
|
|
|
+ .questionType((String) req.get("questionType"))
|
|
|
+ .subject((String) req.get("subject"))
|
|
|
+ .chapterId((String) req.get("chapterId"))
|
|
|
+ .difficulty(req.get("difficulty") != null ? (Integer) req.get("difficulty") : 1)
|
|
|
+ .content((String) req.get("content"))
|
|
|
+ .answer((String) req.get("answer"))
|
|
|
+ .explanation((String) req.get("explanation"))
|
|
|
+ .frequency((String) req.get("frequency"))
|
|
|
+ .source((String) req.get("source"))
|
|
|
+ .audited(false)
|
|
|
+ .correctCount(0)
|
|
|
+ .attemptCount(0)
|
|
|
+ .build();
|
|
|
+ try {
|
|
|
+ if (req.get("options") != null) q.setOptions(mapper.writeValueAsString(req.get("options")));
|
|
|
+ if (req.get("knowledgePointIds") != null) q.setKnowledgePointIds(mapper.writeValueAsString(req.get("knowledgePointIds")));
|
|
|
+ } catch (JsonProcessingException ignored) {}
|
|
|
+ questionRepository.save(q);
|
|
|
+ return toMap("question_id", q.getQuestionId(), "message", "已创建");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> updateQuestion(String questionId, Map<String, Object> req) {
|
|
|
+ return questionRepository.findByQuestionId(questionId).map(q -> {
|
|
|
+ if (req.containsKey("questionType")) q.setQuestionType((String) req.get("questionType"));
|
|
|
+ if (req.containsKey("subject")) q.setSubject((String) req.get("subject"));
|
|
|
+ if (req.containsKey("chapterId")) q.setChapterId((String) req.get("chapterId"));
|
|
|
+ if (req.containsKey("difficulty")) q.setDifficulty((Integer) req.get("difficulty"));
|
|
|
+ if (req.containsKey("content")) q.setContent((String) req.get("content"));
|
|
|
+ if (req.containsKey("answer")) q.setAnswer((String) req.get("answer"));
|
|
|
+ if (req.containsKey("explanation")) q.setExplanation((String) req.get("explanation"));
|
|
|
+ if (req.containsKey("frequency")) q.setFrequency((String) req.get("frequency"));
|
|
|
+ if (req.containsKey("source")) q.setSource((String) req.get("source"));
|
|
|
+ if (req.containsKey("audited")) q.setAudited((Boolean) req.get("audited"));
|
|
|
+ try {
|
|
|
+ if (req.get("options") != null) q.setOptions(mapper.writeValueAsString(req.get("options")));
|
|
|
+ if (req.get("knowledgePointIds") != null) q.setKnowledgePointIds(mapper.writeValueAsString(req.get("knowledgePointIds")));
|
|
|
+ } catch (JsonProcessingException ignored) {}
|
|
|
+ questionRepository.save(q);
|
|
|
+ return toMap("question_id", questionId, "message", "已更新");
|
|
|
+ }).orElseGet(() -> toMap("question_id", questionId, "message", "题目不存在"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> deleteQuestion(String questionId) {
|
|
|
+ questionRepository.findByQuestionId(questionId).ifPresent(questionRepository::delete);
|
|
|
+ return toMap("question_id", questionId, "message", "已删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public Map<String, Object> batchAudit(List<String> questionIds, boolean audited) {
|
|
|
+ for (String qid : questionIds) {
|
|
|
+ questionRepository.findByQuestionId(qid).ifPresent(q -> {
|
|
|
+ q.setAudited(audited);
|
|
|
+ questionRepository.save(q);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ Map<String, Object> r = new LinkedHashMap<>();
|
|
|
+ r.put("message", "批量审核完成");
|
|
|
+ r.put("question_ids", questionIds);
|
|
|
+ r.put("audited", audited);
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== Helpers ====================
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private Map<String, Object> castToMap(Object obj) {
|
|
|
+ if (obj instanceof Map) return (Map<String, Object>) obj;
|
|
|
+ return new HashMap<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> drugToMap(Drug d) {
|
|
|
+ Map<String, Object> m = new LinkedHashMap<>();
|
|
|
+ m.put("drug_id", d.getDrugId());
|
|
|
+ m.put("name", d.getName());
|
|
|
+ m.put("name_en", d.getNameEn());
|
|
|
+ m.put("pinyin", d.getPinyin());
|
|
|
+ m.put("category", d.getCategory());
|
|
|
+ m.put("subcategory", d.getSubcategory());
|
|
|
+ m.put("approval_number", d.getApprovalNumber());
|
|
|
+ m.put("sections", d.getSections());
|
|
|
+ m.put("source_version", d.getSourceVersion());
|
|
|
+ m.put("source_volume", d.getSourceVolume());
|
|
|
+ m.put("source_page", d.getSourcePage());
|
|
|
+ m.put("is_active", d.getIsActive());
|
|
|
+ m.put("created_at", d.getCreatedAt());
|
|
|
+ m.put("updated_at", d.getUpdatedAt());
|
|
|
+ return m;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> toMap(String k1, Object v1, String k2, Object v2) {
|
|
|
+ Map<String, Object> m = new LinkedHashMap<>();
|
|
|
+ m.put(k1, v1);
|
|
|
+ m.put(k2, v2);
|
|
|
+ return m;
|
|
|
+ }
|
|
|
+}
|