CaseInfoService.java 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package com.qingjian.module.plat.service;
  2. import cn.hutool.core.io.FileUtil;
  3. import cn.hutool.core.lang.Assert;
  4. import cn.hutool.core.util.RandomUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7. import com.qingjian.common.cache.CaseDataCache;
  8. import com.qingjian.common.constants.PathConst;
  9. import com.qingjian.common.constants.StrConsts;
  10. import com.qingjian.common.exception.ServerException;
  11. import com.qingjian.common.model.plat.dto.UpdateCasePwdDTO;
  12. import com.qingjian.common.model.plat.entity.CaseInfo;
  13. import com.qingjian.common.utils.LuceneManager;
  14. import com.qingjian.common.utils.StateManager;
  15. import com.qingjian.module.plat.mapper.CaseInfoMapper;
  16. import lombok.extern.slf4j.Slf4j;
  17. import org.noear.solon.Solon;
  18. import org.noear.solon.annotation.Inject;
  19. import org.noear.solon.annotation.Managed;
  20. import org.noear.solon.core.Props;
  21. import org.noear.solon.data.datasource.DsUtils;
  22. import org.noear.solon.data.dynamicds.DynamicDataSource;
  23. import org.noear.solon.data.dynamicds.DynamicDs;
  24. import javax.sql.DataSource;
  25. import java.nio.file.Files;
  26. import java.nio.file.Path;
  27. import java.time.LocalDateTime;
  28. /**
  29. * 案件服务
  30. */
  31. @Slf4j
  32. @Managed
  33. @DynamicDs(StrConsts.DS_KEY_PLAT)
  34. public class CaseInfoService extends ServiceImpl<CaseInfoMapper, CaseInfo> {
  35. @Inject("db1")
  36. private DynamicDataSource dynamicDataSource;
  37. @Inject
  38. private SseService sseService;
  39. /**
  40. * 创建案件
  41. *
  42. * @param caseInfo 案件信息
  43. */
  44. public void create(CaseInfo caseInfo) {
  45. String caseName = StrUtil.trim(caseInfo.getName());
  46. if (caseInfo.getId() != null) {
  47. CaseInfo dbCaseInfo = getById(caseInfo.getId());
  48. if (dbCaseInfo == null) {
  49. throw ServerException.spe("案件不存在!");
  50. }
  51. if (!StrUtil.equals(dbCaseInfo.getPwd(), caseInfo.getPwd())) {
  52. throw ServerException.spe("案件密码错误!");
  53. }
  54. long duplicateCount = lambdaQuery()
  55. .eq(CaseInfo::getName, caseName)
  56. .ne(CaseInfo::getId, caseInfo.getId())
  57. .count();
  58. if (duplicateCount > 0) {
  59. throw ServerException.spe("案件名称已存在!");
  60. }
  61. caseInfo.setPwd(null);
  62. caseInfo.setName(caseName);
  63. updateById(caseInfo);
  64. return;
  65. }
  66. long duplicateCount = lambdaQuery()
  67. .eq(CaseInfo::getName, caseName)
  68. .count();
  69. if (duplicateCount > 0) {
  70. throw ServerException.spe("案件名称已存在!");
  71. }
  72. caseInfo.setName(caseName);
  73. caseInfo.setCreateTime(LocalDateTime.now());
  74. save(caseInfo);
  75. String caseDb = RandomUtil.randomString(8) + caseInfo.getId();
  76. Path casePath = PathConst.WORKSPACE.resolve(caseInfo.getId().toString());
  77. FileUtil.mkdir(casePath);
  78. Path caseSession = PathConst.AGENT_PATH.resolve("sessions").resolve(caseInfo.getId().toString());
  79. FileUtil.mkdir(caseSession);
  80. Path caseDbPath = casePath.resolve(caseDb);
  81. if (Files.notExists(caseDbPath)) {
  82. if (Files.notExists(PathConst.BASE_CASE_DB_PATH)) {
  83. log.error("基础数据库不存在!");
  84. return;
  85. }
  86. FileUtil.copy(PathConst.BASE_CASE_DB_PATH, caseDbPath);
  87. }
  88. caseInfo.setDbPath(caseDbPath.toString());
  89. caseInfo.setDb(caseDb);
  90. updateById(caseInfo);
  91. }
  92. /**
  93. * 删除案件
  94. *
  95. * @param id 案件 ID
  96. * @param pwd 案件密码
  97. */
  98. public void delete(Integer id, String pwd) {
  99. CaseInfo caseInfo = getById(id);
  100. if (caseInfo == null) {
  101. throw new ServerException("案件不存在!");
  102. }
  103. if (!caseInfo.getPwd().equals(pwd)) {
  104. throw new ServerException("案件密码错误!");
  105. }
  106. removeById(id);
  107. Path casePath = PathConst.WORKSPACE.resolve(caseInfo.getId().toString());
  108. FileUtil.del(casePath);
  109. }
  110. /**
  111. * 更新密码
  112. *
  113. * @param updateCasePwdDTO 更新用密码
  114. */
  115. public void updatePwd(UpdateCasePwdDTO updateCasePwdDTO) {
  116. CaseInfo caseInfo = getById(updateCasePwdDTO.getId());
  117. if (caseInfo == null) {
  118. throw new ServerException("案件不存在!");
  119. }
  120. caseInfo.setPwd(updateCasePwdDTO.getNewPwd());
  121. updateById(caseInfo);
  122. }
  123. /**
  124. * 开启案件
  125. *
  126. * @param id 案件 ID
  127. * @param pwd 案件密码
  128. */
  129. public void open(Integer id, String pwd) {
  130. // 根据id和密码查询 sql 语句
  131. CaseInfo ci = getById(id);
  132. Assert.notNull(ci, () -> ServerException.spe("案件不存在!"));
  133. Assert.isTrue(ci.getPwd().equals(pwd), () -> ServerException.spe("案件密码错误!"));
  134. Path caseDbPath = Path.of(ci.getDbPath());
  135. closeOldDb();
  136. openNewDb(caseDbPath.toString());
  137. LuceneManager.createWriter(PathConst.WORKSPACE.resolve(ci.getId().toString()).resolve("lucene"));
  138. StateManager.instance().setCaseInfo(ci);
  139. CaseDataCache.initCache();
  140. }
  141. private void closeOldDb() {
  142. try {
  143. LuceneManager.close();
  144. dynamicDataSource.removeTargetDataSource(StrConsts.DS_KEY_CASE);
  145. CaseDataCache.cleanCache();
  146. sseService.closeSee();
  147. } catch (Exception e) {
  148. log.error("关闭数据库连接失败", e);
  149. throw ServerException.spe("关闭资源失败!");
  150. }
  151. }
  152. private void openNewDb(String dbPath) {
  153. Props props = Solon.cfg().getProp("qingjian.db1.case");
  154. props.setProperty("url", "jdbc:duckdb:" + dbPath);
  155. DataSource dataSource = DsUtils.buildDs(props);
  156. dynamicDataSource.setDefaultTargetDataSource(dataSource);
  157. dynamicDataSource.addTargetDataSource(StrConsts.DS_KEY_CASE, dataSource);
  158. }
  159. public void exit() {
  160. closeOldDb();
  161. openNewDb(PathConst.TEMP_DB_PATH.toString());
  162. StateManager.instance().cleanCase();
  163. }
  164. }