|
@@ -8,10 +8,16 @@ import com.pharmacopoeia.entity.Question;
|
|
|
import com.pharmacopoeia.repository.DrugRepository;
|
|
import com.pharmacopoeia.repository.DrugRepository;
|
|
|
import com.pharmacopoeia.repository.KnowledgePointRepository;
|
|
import com.pharmacopoeia.repository.KnowledgePointRepository;
|
|
|
import com.pharmacopoeia.repository.QuestionRepository;
|
|
import com.pharmacopoeia.repository.QuestionRepository;
|
|
|
|
|
+import com.pharmacopoeia.repository.QuickAskRepository;
|
|
|
|
|
+import com.pharmacopoeia.repository.QuickAskAuditLogRepository;
|
|
|
|
|
+import com.pharmacopoeia.entity.QuickAsk;
|
|
|
|
|
+import com.pharmacopoeia.entity.QuickAskAuditLog;
|
|
|
import org.springframework.data.domain.PageRequest;
|
|
import org.springframework.data.domain.PageRequest;
|
|
|
|
|
+import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
|
|
|
|
@@ -24,13 +30,20 @@ public class AdminKnowledgeService {
|
|
|
private final JdbcTemplate jdbc;
|
|
private final JdbcTemplate jdbc;
|
|
|
private final ObjectMapper mapper = new ObjectMapper();
|
|
private final ObjectMapper mapper = new ObjectMapper();
|
|
|
|
|
|
|
|
|
|
+ private final QuickAskRepository quickAskRepository;
|
|
|
|
|
+ private final QuickAskAuditLogRepository auditLogRepository;
|
|
|
|
|
+
|
|
|
public AdminKnowledgeService(DrugRepository drugRepository,
|
|
public AdminKnowledgeService(DrugRepository drugRepository,
|
|
|
KnowledgePointRepository knowledgePointRepository,
|
|
KnowledgePointRepository knowledgePointRepository,
|
|
|
QuestionRepository questionRepository,
|
|
QuestionRepository questionRepository,
|
|
|
|
|
+ QuickAskRepository quickAskRepository,
|
|
|
|
|
+ QuickAskAuditLogRepository auditLogRepository,
|
|
|
JdbcTemplate jdbc) {
|
|
JdbcTemplate jdbc) {
|
|
|
this.drugRepository = drugRepository;
|
|
this.drugRepository = drugRepository;
|
|
|
this.knowledgePointRepository = knowledgePointRepository;
|
|
this.knowledgePointRepository = knowledgePointRepository;
|
|
|
this.questionRepository = questionRepository;
|
|
this.questionRepository = questionRepository;
|
|
|
|
|
+ this.quickAskRepository = quickAskRepository;
|
|
|
|
|
+ this.auditLogRepository = auditLogRepository;
|
|
|
this.jdbc = jdbc;
|
|
this.jdbc = jdbc;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -358,47 +371,124 @@ public class AdminKnowledgeService {
|
|
|
// ==================== 快捷提问标签管理 ====================
|
|
// ==================== 快捷提问标签管理 ====================
|
|
|
|
|
|
|
|
/** 获取所有激活的标签,按 sort_order 排序(公开接口,无需鉴权) */
|
|
/** 获取所有激活的标签,按 sort_order 排序(公开接口,无需鉴权) */
|
|
|
- public List<Map<String, Object>> listQuickAsks() {
|
|
|
|
|
- return jdbc.queryForList(
|
|
|
|
|
- "SELECT id, label, question, sort_order FROM quick_asks WHERE is_active = TRUE ORDER BY sort_order, id");
|
|
|
|
|
|
|
+ public List<QuickAsk> listQuickAsks() {
|
|
|
|
|
+ return quickAskRepository.findByIsActiveTrueOrderBySortOrderAscIdAsc();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 管理端:获取所有标签(含禁用) */
|
|
/** 管理端:获取所有标签(含禁用) */
|
|
|
- public List<Map<String, Object>> listAllQuickAsks() {
|
|
|
|
|
- return jdbc.queryForList(
|
|
|
|
|
- "SELECT id, label, question, sort_order, is_active, created_at FROM quick_asks ORDER BY sort_order, id");
|
|
|
|
|
|
|
+ public List<QuickAsk> listAllQuickAsks() {
|
|
|
|
|
+ return quickAskRepository.findAllByOrderBySortOrderAscIdAsc();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 新增标签 */
|
|
/** 新增标签 */
|
|
|
|
|
+ @Transactional
|
|
|
public Map<String, Object> createQuickAsk(String label, String question, int sortOrder) {
|
|
public Map<String, Object> createQuickAsk(String label, String question, int sortOrder) {
|
|
|
- int rows = jdbc.update(
|
|
|
|
|
- "INSERT INTO quick_asks (label, question, sort_order) VALUES (?, ?, ?)",
|
|
|
|
|
- label, question, sortOrder);
|
|
|
|
|
- return Map.of("ok", rows > 0, "message", rows > 0 ? "已创建" : "创建失败");
|
|
|
|
|
|
|
+ if (label == null || label.isBlank()) {
|
|
|
|
|
+ return Map.of("ok", false, "message", "请输入推荐位文字");
|
|
|
|
|
+ }
|
|
|
|
|
+ String trimmedLabel = label.trim();
|
|
|
|
|
+ if (trimmedLabel.length() < 2 || trimmedLabel.length() > 20) {
|
|
|
|
|
+ return Map.of("ok", false, "message", "推荐位文字长度需在2-20个字符之间");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (quickAskRepository.count() >= 6) {
|
|
|
|
|
+ return Map.of("ok", false, "message", "最多只能添加6个推荐位");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (quickAskRepository.countByLabel(trimmedLabel) > 0) {
|
|
|
|
|
+ return Map.of("ok", false, "message", "推荐位文字不能重复");
|
|
|
|
|
+ }
|
|
|
|
|
+ String operator = getCurrentOperator();
|
|
|
|
|
+ QuickAsk qa = QuickAsk.builder()
|
|
|
|
|
+ .label(trimmedLabel)
|
|
|
|
|
+ .question(question != null ? question.trim() : trimmedLabel)
|
|
|
|
|
+ .sortOrder(sortOrder)
|
|
|
|
|
+ .isActive(true)
|
|
|
|
|
+ .createdBy(operator)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ qa = quickAskRepository.save(qa);
|
|
|
|
|
+ auditLogRepository.save(QuickAskAuditLog.builder()
|
|
|
|
|
+ .quickAskId(qa.getId()).action("CREATE")
|
|
|
|
|
+ .label(qa.getLabel()).question(qa.getQuestion())
|
|
|
|
|
+ .sortOrder(qa.getSortOrder()).isActive(qa.getIsActive())
|
|
|
|
|
+ .operator(operator).build());
|
|
|
|
|
+ return Map.of("ok", true, "id", qa.getId(), "message", "已创建");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 更新标签 */
|
|
/** 更新标签 */
|
|
|
|
|
+ @Transactional
|
|
|
public Map<String, Object> updateQuickAsk(int id, String label, String question, Integer sortOrder, Boolean isActive) {
|
|
public Map<String, Object> updateQuickAsk(int id, String label, String question, Integer sortOrder, Boolean isActive) {
|
|
|
- var sql = new StringBuilder("UPDATE quick_asks SET ");
|
|
|
|
|
- var params = new ArrayList<>();
|
|
|
|
|
- if (label != null) { sql.append("label = ?, "); params.add(label); }
|
|
|
|
|
- if (question != null) { sql.append("question = ?, "); params.add(question); }
|
|
|
|
|
- if (sortOrder != null) { sql.append("sort_order = ?, "); params.add(sortOrder); }
|
|
|
|
|
- if (isActive != null) { sql.append("is_active = ?, "); params.add(isActive); }
|
|
|
|
|
- if (params.isEmpty()) return Map.of("ok", false, "message", "无修改字段");
|
|
|
|
|
-
|
|
|
|
|
- sql.setLength(sql.length() - 2); // 去掉末尾 ", "
|
|
|
|
|
- sql.append(" WHERE id = ?");
|
|
|
|
|
- params.add(id);
|
|
|
|
|
-
|
|
|
|
|
- int rows = jdbc.update(sql.toString(), params.toArray());
|
|
|
|
|
- return Map.of("ok", rows > 0, "message", rows > 0 ? "已更新" : "未找到");
|
|
|
|
|
|
|
+ var opt = quickAskRepository.findById(id);
|
|
|
|
|
+ if (opt.isEmpty()) return Map.of("ok", false, "message", "未找到");
|
|
|
|
|
+ QuickAsk qa = opt.get();
|
|
|
|
|
+ if (label != null && !label.isBlank()) {
|
|
|
|
|
+ String trimmedLabel = label.trim();
|
|
|
|
|
+ if (quickAskRepository.countByLabelAndIdNot(trimmedLabel, id) > 0) {
|
|
|
|
|
+ return Map.of("ok", false, "message", "推荐位文字不能重复");
|
|
|
|
|
+ }
|
|
|
|
|
+ qa.setLabel(trimmedLabel);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (question != null) qa.setQuestion(question.trim());
|
|
|
|
|
+ if (sortOrder != null) qa.setSortOrder(sortOrder);
|
|
|
|
|
+ if (isActive != null) qa.setIsActive(isActive);
|
|
|
|
|
+ String operator = getCurrentOperator();
|
|
|
|
|
+ qa.setUpdatedBy(operator);
|
|
|
|
|
+ quickAskRepository.save(qa);
|
|
|
|
|
+ auditLogRepository.save(QuickAskAuditLog.builder()
|
|
|
|
|
+ .quickAskId(id).action("UPDATE")
|
|
|
|
|
+ .label(qa.getLabel()).question(qa.getQuestion())
|
|
|
|
|
+ .sortOrder(qa.getSortOrder()).isActive(qa.getIsActive())
|
|
|
|
|
+ .operator(operator).build());
|
|
|
|
|
+ return Map.of("ok", true, "id", id, "message", "已更新");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 删除标签 */
|
|
/** 删除标签 */
|
|
|
|
|
+ @Transactional
|
|
|
public Map<String, Object> deleteQuickAsk(int id) {
|
|
public Map<String, Object> deleteQuickAsk(int id) {
|
|
|
- int rows = jdbc.update("DELETE FROM quick_asks WHERE id = ?", id);
|
|
|
|
|
- return Map.of("ok", rows > 0, "message", rows > 0 ? "已删除" : "未找到");
|
|
|
|
|
|
|
+ var opt = quickAskRepository.findById(id);
|
|
|
|
|
+ if (opt.isEmpty()) return Map.of("ok", false, "message", "未找到");
|
|
|
|
|
+ QuickAsk qa = opt.get();
|
|
|
|
|
+ String operator = getCurrentOperator();
|
|
|
|
|
+ auditLogRepository.save(QuickAskAuditLog.builder()
|
|
|
|
|
+ .quickAskId(id).action("DELETE")
|
|
|
|
|
+ .label(qa.getLabel()).question(qa.getQuestion())
|
|
|
|
|
+ .sortOrder(qa.getSortOrder()).isActive(qa.getIsActive())
|
|
|
|
|
+ .operator(operator).build());
|
|
|
|
|
+ quickAskRepository.delete(qa);
|
|
|
|
|
+ return Map.of("ok", true, "message", "已删除");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== ?????? ====================
|
|
|
|
|
+
|
|
|
|
|
+ public Map<String, Object> reorderQuickAsks(List<Map<String, Object>> items) {
|
|
|
|
|
+ String operator = getCurrentOperator();
|
|
|
|
|
+ int updated = 0;
|
|
|
|
|
+ for (Map<String, Object> item : items) {
|
|
|
|
|
+ int id = ((Number) item.get("id")).intValue();
|
|
|
|
|
+ int sortOrder = ((Number) item.get("sort_order")).intValue();
|
|
|
|
|
+ updated += quickAskRepository.updateSortOrder(id, sortOrder, operator);
|
|
|
|
|
+ }
|
|
|
|
|
+ return Map.of("ok", updated > 0, "message", "已更新 " + updated + " 条排序");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void writeAuditLog(int quickAskId, String action, String operator,
|
|
|
|
|
+ String label, String question, Integer sortOrder, Boolean isActive) {
|
|
|
|
|
+ auditLogRepository.save(QuickAskAuditLog.builder()
|
|
|
|
|
+ .quickAskId(quickAskId).action(action)
|
|
|
|
|
+ .label(label).question(question)
|
|
|
|
|
+ .sortOrder(sortOrder != null ? sortOrder : 0)
|
|
|
|
|
+ .isActive(isActive != null ? isActive : true)
|
|
|
|
|
+ .operator(operator).build());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public Map<String, Object> listQuickAskAuditLog(int page, int pageSize) {
|
|
|
|
|
+ var pageable = org.springframework.data.domain.PageRequest.of(page - 1, pageSize);
|
|
|
|
|
+ var result = auditLogRepository.findAllByOrderByCreatedAtDesc(pageable);
|
|
|
|
|
+ return Map.of(
|
|
|
|
|
+ "items", result.getContent(),
|
|
|
|
|
+ "page", page,
|
|
|
|
|
+ "page_size", pageSize,
|
|
|
|
|
+ "total", result.getTotalElements(),
|
|
|
|
|
+ "total_pages", result.getTotalPages()
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ==================== Helpers ====================
|
|
// ==================== Helpers ====================
|