From 4bd793e1e2531b4d4ae6470230b50075d89a8795 Mon Sep 17 00:00:00 2001 From: xueqingkun Date: Mon, 15 Jul 2024 11:17:50 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 191 ++++++ .../supervision/SpringAiDemoApplication.java | 15 + .../common/constant/Constants.java | 69 ++ .../java/com/supervision/common/domain/R.java | 147 +++++ .../common/enums/ResultStatusEnum.java | 51 ++ .../common/exception/CustomException.java | 29 + .../supervision/common/utils/ExcelReader.java | 277 ++++++++ .../com/supervision/common/utils/IPages.java | 28 + .../supervision/common/utils/ListUtils.java | 88 +++ .../supervision/common/utils/StringUtils.java | 619 ++++++++++++++++++ .../config/BeanPostProcessorConfig.java | 54 ++ .../com/supervision/config/CorsConfig.java | 33 + .../com/supervision/config/MinioConfig.java | 41 ++ .../config/MyMetaObjectHandler.java | 26 + .../supervision/config/MybatisPlusConfig.java | 43 ++ .../com/supervision/config/Neo4jConfig.java | 32 + .../minio/client/MinioTemplate.java | 214 ++++++ .../minio/controller/MinioController.java | 34 + .../supervision/minio/domain/MinioFile.java | 49 ++ .../minio/exception/SysObsException.java | 21 + .../minio/mapper/MinioFileMapper.java | 15 + .../minio/service/MinioService.java | 17 + .../minio/service/impl/MinioServiceImpl.java | 67 ++ .../neo4j/controller/Neo4jController.java | 83 +++ .../supervision/neo4j/domain/CaseNode.java | 58 ++ .../com/supervision/neo4j/domain/Rel.java | 36 + .../com/supervision/neo4j/dto/ResultDTO.java | 29 + .../neo4j/repository/CaseNodeRepository.java | 40 ++ .../neo4j/service/Neo4jService.java | 31 + .../neo4j/service/impl/Neo4jServiceImpl.java | 283 ++++++++ .../supervision/neo4j/utils/Neo4jUtils.java | 91 +++ .../controller/ComDictionaryController.java | 61 ++ .../controller/ModelCaseController.java | 107 +++ .../police/controller/ModelController.java | 26 + .../controller/ModelIndexController.java | 102 +++ .../police/controller/RecordController.java | 122 ++++ .../supervision/police/domain/CasePerson.java | 49 ++ .../police/domain/ComDictionary.java | 90 +++ .../police/domain/ModelAtomicIndex.java | 103 +++ .../police/domain/ModelAtomicResult.java | 59 ++ .../supervision/police/domain/ModelCase.java | 130 ++++ .../supervision/police/domain/ModelIndex.java | 98 +++ .../police/domain/ModelIndexResult.java | 54 ++ .../police/domain/ModelRecordType.java | 39 ++ .../supervision/police/domain/NotePrompt.java | 29 + .../supervision/police/domain/NoteRecord.java | 71 ++ .../police/domain/NoteRecords.java | 104 +++ .../supervision/police/domain/TripleInfo.java | 88 +++ .../police/dto/AnalyseCaseDTO.java | 19 + .../supervision/police/dto/AtomicData.java | 21 + .../police/dto/AtomicIndexDTO.java | 28 + .../police/dto/DictionaryByTypeParam.java | 23 + .../supervision/police/dto/IndexDetail.java | 40 ++ .../supervision/police/dto/JudgeLogic.java | 28 + .../police/dto/KeyAndNameObject.java | 12 + .../com/supervision/police/dto/ListDTO.java | 12 + .../com/supervision/police/dto/SignParam.java | 32 + .../police/mapper/CasePersonMapper.java | 15 + .../police/mapper/ComDictionaryMapper.java | 53 ++ .../police/mapper/ModelAtomicIndexMapper.java | 23 + .../mapper/ModelAtomicResultMapper.java | 19 + .../police/mapper/ModelCaseMapper.java | 33 + .../police/mapper/ModelIndexMapper.java | 20 + .../police/mapper/ModelIndexResultMapper.java | 19 + .../police/mapper/ModelRecordTypeMapper.java | 19 + .../police/mapper/NoteCheckRecordMapper.java | 18 + .../police/mapper/NotePromptMapper.java | 13 + .../police/mapper/NoteRecordMapper.java | 17 + .../police/mapper/NoteRecordsMapper.java | 15 + .../police/mapper/TripleInfoMapper.java | 13 + .../police/service/ComDictionaryService.java | 33 + .../police/service/ModelCaseService.java | 34 + .../police/service/ModelIndexService.java | 29 + .../service/ModelRecordTypeService.java | 25 + .../police/service/ModelService.java | 10 + .../service/NoteCheckRecordService.java | 13 + .../police/service/RecordService.java | 20 + .../impl/ComDictionaryServiceImpl.java | 192 ++++++ .../service/impl/ModelCaseServiceImpl.java | 222 +++++++ .../service/impl/ModelIndexServiceImpl.java | 154 +++++ .../impl/ModelRecordTypeServiceImpl.java | 218 ++++++ .../police/service/impl/ModelServiceImpl.java | 185 ++++++ .../impl/NoteCheckRecordServiceImpl.java | 22 + .../service/impl/RecordServiceImpl.java | 228 +++++++ .../controller/ChatController.java | 336 ++++++++++ .../controller/ExampleChatController.java | 256 ++++++++ .../controller/NewTestController.java | 106 +++ .../controller/RzChatController.java | 118 ++++ .../controller/SimilarityController.java | 146 +++++ .../SimilarityQuestionController.java | 44 ++ .../controller/VPTestController.java | 83 +++ .../VirtualPatientTestController.java | 90 +++ .../springaidemo/domain/ModelMetric.java | 76 +++ .../domain/ModelMetricExample.java | 35 + .../springaidemo/domain/NoteCheckRecord.java | 83 +++ .../domain/VpAskTemplateQuestionLibrary.java | 81 +++ .../springaidemo/domain/VpCommonDic.java | 86 +++ .../springaidemo/dto/AnswerDTO.java | 11 + .../springaidemo/dto/GlobalResult.java | 45 ++ .../springaidemo/dto/MetricResultDTO.java | 13 + .../springaidemo/dto/QARecordNodeDTO.java | 28 + .../dto/paddlespeech/req/AsrReqDTO.java | 21 + .../dto/paddlespeech/req/TtsReqDTO.java | 23 + .../dto/paddlespeech/res/AsrResultDTO.java | 10 + .../paddlespeech/res/PaddleSpeechResDTO.java | 15 + .../dto/paddlespeech/res/TtsResultDTO.java | 23 + .../mapper/ModelMetricExampleMapper.java | 18 + .../mapper/ModelMetricMapper.java | 18 + .../VpAskTemplateQuestionLibraryMapper.java | 18 + .../mapper/VpCommonDicMapper.java | 18 + .../service/ModelMetricExampleService.java | 13 + .../service/ModelMetricService.java | 13 + .../VpAskTemplateQuestionLibraryService.java | 13 + .../service/VpCommonDicService.java | 13 + .../impl/ModelMetricExampleServiceImpl.java | 22 + .../service/impl/ModelMetricServiceImpl.java | 22 + ...AskTemplateQuestionLibraryServiceImpl.java | 22 + .../service/impl/VpCommonDicServiceImpl.java | 22 + .../springaidemo/thread/RunCheckThread.java | 91 +++ .../thread/RunCheckThreadPool.java | 10 + .../springaidemo/util/RecordRegexUtil.java | 38 ++ .../springaidemo/util/TtsUtil.java | 33 + .../springaidemo/util/WordReadUtil.java | 57 ++ .../supervision/swagger/OpenAPIConfig.java | 34 + src/main/resources/application-dev.yml | 85 +++ src/main/resources/application.yml | 15 + .../resources/mapper/CasePersonMapper.xml | 5 + .../resources/mapper/ComDictionaryMapper.xml | 47 ++ src/main/resources/mapper/MinioFileMapper.xml | 5 + .../mapper/ModelAtomicIndexMapper.xml | 32 + .../mapper/ModelAtomicResultMapper.xml | 8 + src/main/resources/mapper/ModelCaseMapper.xml | 56 ++ .../resources/mapper/ModelIndexMapper.xml | 7 + .../mapper/ModelIndexResultMapper.xml | 8 + .../mapper/ModelMetricExampleMapper.xml | 16 + .../resources/mapper/ModelMetricMapper.xml | 23 + .../mapper/ModelRecordTypeMapper.xml | 20 + .../mapper/NoteCheckRecordMapper.xml | 27 + .../resources/mapper/NotePromptMapper.xml | 10 + .../resources/mapper/NoteRecordMapper.xml | 20 + .../resources/mapper/NoteRecordsMapper.xml | 5 + .../resources/mapper/TripleInfoMapper.xml | 19 + .../resources/mapper/VpCommonDicMapper.xml | 30 + .../SpringAiDemoApplicationTests.java | 74 +++ 144 files changed, 8736 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/com/supervision/SpringAiDemoApplication.java create mode 100644 src/main/java/com/supervision/common/constant/Constants.java create mode 100644 src/main/java/com/supervision/common/domain/R.java create mode 100644 src/main/java/com/supervision/common/enums/ResultStatusEnum.java create mode 100644 src/main/java/com/supervision/common/exception/CustomException.java create mode 100644 src/main/java/com/supervision/common/utils/ExcelReader.java create mode 100644 src/main/java/com/supervision/common/utils/IPages.java create mode 100644 src/main/java/com/supervision/common/utils/ListUtils.java create mode 100644 src/main/java/com/supervision/common/utils/StringUtils.java create mode 100644 src/main/java/com/supervision/config/BeanPostProcessorConfig.java create mode 100644 src/main/java/com/supervision/config/CorsConfig.java create mode 100644 src/main/java/com/supervision/config/MinioConfig.java create mode 100644 src/main/java/com/supervision/config/MyMetaObjectHandler.java create mode 100644 src/main/java/com/supervision/config/MybatisPlusConfig.java create mode 100644 src/main/java/com/supervision/config/Neo4jConfig.java create mode 100644 src/main/java/com/supervision/minio/client/MinioTemplate.java create mode 100644 src/main/java/com/supervision/minio/controller/MinioController.java create mode 100644 src/main/java/com/supervision/minio/domain/MinioFile.java create mode 100644 src/main/java/com/supervision/minio/exception/SysObsException.java create mode 100644 src/main/java/com/supervision/minio/mapper/MinioFileMapper.java create mode 100644 src/main/java/com/supervision/minio/service/MinioService.java create mode 100644 src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java create mode 100644 src/main/java/com/supervision/neo4j/controller/Neo4jController.java create mode 100644 src/main/java/com/supervision/neo4j/domain/CaseNode.java create mode 100644 src/main/java/com/supervision/neo4j/domain/Rel.java create mode 100644 src/main/java/com/supervision/neo4j/dto/ResultDTO.java create mode 100644 src/main/java/com/supervision/neo4j/repository/CaseNodeRepository.java create mode 100644 src/main/java/com/supervision/neo4j/service/Neo4jService.java create mode 100644 src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java create mode 100644 src/main/java/com/supervision/neo4j/utils/Neo4jUtils.java create mode 100644 src/main/java/com/supervision/police/controller/ComDictionaryController.java create mode 100644 src/main/java/com/supervision/police/controller/ModelCaseController.java create mode 100644 src/main/java/com/supervision/police/controller/ModelController.java create mode 100644 src/main/java/com/supervision/police/controller/ModelIndexController.java create mode 100644 src/main/java/com/supervision/police/controller/RecordController.java create mode 100644 src/main/java/com/supervision/police/domain/CasePerson.java create mode 100644 src/main/java/com/supervision/police/domain/ComDictionary.java create mode 100644 src/main/java/com/supervision/police/domain/ModelAtomicIndex.java create mode 100644 src/main/java/com/supervision/police/domain/ModelAtomicResult.java create mode 100644 src/main/java/com/supervision/police/domain/ModelCase.java create mode 100644 src/main/java/com/supervision/police/domain/ModelIndex.java create mode 100644 src/main/java/com/supervision/police/domain/ModelIndexResult.java create mode 100644 src/main/java/com/supervision/police/domain/ModelRecordType.java create mode 100644 src/main/java/com/supervision/police/domain/NotePrompt.java create mode 100644 src/main/java/com/supervision/police/domain/NoteRecord.java create mode 100644 src/main/java/com/supervision/police/domain/NoteRecords.java create mode 100644 src/main/java/com/supervision/police/domain/TripleInfo.java create mode 100644 src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java create mode 100644 src/main/java/com/supervision/police/dto/AtomicData.java create mode 100644 src/main/java/com/supervision/police/dto/AtomicIndexDTO.java create mode 100644 src/main/java/com/supervision/police/dto/DictionaryByTypeParam.java create mode 100644 src/main/java/com/supervision/police/dto/IndexDetail.java create mode 100644 src/main/java/com/supervision/police/dto/JudgeLogic.java create mode 100644 src/main/java/com/supervision/police/dto/KeyAndNameObject.java create mode 100644 src/main/java/com/supervision/police/dto/ListDTO.java create mode 100644 src/main/java/com/supervision/police/dto/SignParam.java create mode 100644 src/main/java/com/supervision/police/mapper/CasePersonMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/ComDictionaryMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/ModelAtomicIndexMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/ModelAtomicResultMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/ModelCaseMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/ModelIndexMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/ModelIndexResultMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/ModelRecordTypeMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/NoteCheckRecordMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/NotePromptMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/NoteRecordMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/NoteRecordsMapper.java create mode 100644 src/main/java/com/supervision/police/mapper/TripleInfoMapper.java create mode 100644 src/main/java/com/supervision/police/service/ComDictionaryService.java create mode 100644 src/main/java/com/supervision/police/service/ModelCaseService.java create mode 100644 src/main/java/com/supervision/police/service/ModelIndexService.java create mode 100644 src/main/java/com/supervision/police/service/ModelRecordTypeService.java create mode 100644 src/main/java/com/supervision/police/service/ModelService.java create mode 100644 src/main/java/com/supervision/police/service/NoteCheckRecordService.java create mode 100644 src/main/java/com/supervision/police/service/RecordService.java create mode 100644 src/main/java/com/supervision/police/service/impl/ComDictionaryServiceImpl.java create mode 100644 src/main/java/com/supervision/police/service/impl/ModelCaseServiceImpl.java create mode 100644 src/main/java/com/supervision/police/service/impl/ModelIndexServiceImpl.java create mode 100644 src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java create mode 100644 src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java create mode 100644 src/main/java/com/supervision/police/service/impl/NoteCheckRecordServiceImpl.java create mode 100644 src/main/java/com/supervision/police/service/impl/RecordServiceImpl.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/ChatController.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/ExampleChatController.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/NewTestController.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/RzChatController.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/SimilarityController.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/SimilarityQuestionController.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/VPTestController.java create mode 100644 src/main/java/com/supervision/springaidemo/controller/VirtualPatientTestController.java create mode 100644 src/main/java/com/supervision/springaidemo/domain/ModelMetric.java create mode 100644 src/main/java/com/supervision/springaidemo/domain/ModelMetricExample.java create mode 100644 src/main/java/com/supervision/springaidemo/domain/NoteCheckRecord.java create mode 100644 src/main/java/com/supervision/springaidemo/domain/VpAskTemplateQuestionLibrary.java create mode 100644 src/main/java/com/supervision/springaidemo/domain/VpCommonDic.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/AnswerDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/GlobalResult.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/MetricResultDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/QARecordNodeDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/AsrReqDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/TtsReqDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/AsrResultDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/PaddleSpeechResDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/TtsResultDTO.java create mode 100644 src/main/java/com/supervision/springaidemo/mapper/ModelMetricExampleMapper.java create mode 100644 src/main/java/com/supervision/springaidemo/mapper/ModelMetricMapper.java create mode 100644 src/main/java/com/supervision/springaidemo/mapper/VpAskTemplateQuestionLibraryMapper.java create mode 100644 src/main/java/com/supervision/springaidemo/mapper/VpCommonDicMapper.java create mode 100644 src/main/java/com/supervision/springaidemo/service/ModelMetricExampleService.java create mode 100644 src/main/java/com/supervision/springaidemo/service/ModelMetricService.java create mode 100644 src/main/java/com/supervision/springaidemo/service/VpAskTemplateQuestionLibraryService.java create mode 100644 src/main/java/com/supervision/springaidemo/service/VpCommonDicService.java create mode 100644 src/main/java/com/supervision/springaidemo/service/impl/ModelMetricExampleServiceImpl.java create mode 100644 src/main/java/com/supervision/springaidemo/service/impl/ModelMetricServiceImpl.java create mode 100644 src/main/java/com/supervision/springaidemo/service/impl/VpAskTemplateQuestionLibraryServiceImpl.java create mode 100644 src/main/java/com/supervision/springaidemo/service/impl/VpCommonDicServiceImpl.java create mode 100644 src/main/java/com/supervision/springaidemo/thread/RunCheckThread.java create mode 100644 src/main/java/com/supervision/springaidemo/thread/RunCheckThreadPool.java create mode 100644 src/main/java/com/supervision/springaidemo/util/RecordRegexUtil.java create mode 100644 src/main/java/com/supervision/springaidemo/util/TtsUtil.java create mode 100644 src/main/java/com/supervision/springaidemo/util/WordReadUtil.java create mode 100644 src/main/java/com/supervision/swagger/OpenAPIConfig.java create mode 100644 src/main/resources/application-dev.yml create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/mapper/CasePersonMapper.xml create mode 100644 src/main/resources/mapper/ComDictionaryMapper.xml create mode 100644 src/main/resources/mapper/MinioFileMapper.xml create mode 100644 src/main/resources/mapper/ModelAtomicIndexMapper.xml create mode 100644 src/main/resources/mapper/ModelAtomicResultMapper.xml create mode 100644 src/main/resources/mapper/ModelCaseMapper.xml create mode 100644 src/main/resources/mapper/ModelIndexMapper.xml create mode 100644 src/main/resources/mapper/ModelIndexResultMapper.xml create mode 100644 src/main/resources/mapper/ModelMetricExampleMapper.xml create mode 100644 src/main/resources/mapper/ModelMetricMapper.xml create mode 100644 src/main/resources/mapper/ModelRecordTypeMapper.xml create mode 100644 src/main/resources/mapper/NoteCheckRecordMapper.xml create mode 100644 src/main/resources/mapper/NotePromptMapper.xml create mode 100644 src/main/resources/mapper/NoteRecordMapper.xml create mode 100644 src/main/resources/mapper/NoteRecordsMapper.xml create mode 100644 src/main/resources/mapper/TripleInfoMapper.xml create mode 100644 src/main/resources/mapper/VpCommonDicMapper.xml create mode 100644 src/test/java/com/supervision/springaidemo/SpringAiDemoApplicationTests.java diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..cb688e2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,191 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + + + com.supervision + spring-ai-demo + 1.0.0 + spring-ai-demo + spring-ai-demo + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + io.springboot.ai + spring-ai-ollama-spring-boot-starter + + + + cn.hutool + hutool-all + 5.8.26 + + + + org.apache.poi + poi-ooxml + 4.1.2 + + + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.5 + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + mysql + mysql-connector-java + 8.0.26 + + + + com.alibaba + druid-spring-boot-3-starter + 1.2.21 + + + + + org.neo4j.driver + neo4j-java-driver + 5.21.0 + + + org.springframework.boot + spring-boot-starter-data-neo4j + 2.2.5.RELEASE + + + + com.github.xiaoymin + knife4j-spring-boot-starter + 2.0.8 + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.1.0 + + + + org.springdoc + springdoc-openapi-starter-webmvc-api + 2.1.0 + + + + javax.servlet + javax.servlet-api + 4.0.1 + + + + jakarta.validation + jakarta.validation-api + 2.0.2 + + + + org.hibernate.validator + hibernate-validator + 6.1.7.Final + + + + + org.glassfish + jakarta.el + 3.0.3 + + + + org.apache.commons + commons-lang3 + 3.9 + + + + + io.minio + minio + 8.2.2 + + + + + + + + + io.springboot.ai + spring-ai-bom + 1.0.3 + pom + import + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + diff --git a/src/main/java/com/supervision/SpringAiDemoApplication.java b/src/main/java/com/supervision/SpringAiDemoApplication.java new file mode 100644 index 0000000..f4e0920 --- /dev/null +++ b/src/main/java/com/supervision/SpringAiDemoApplication.java @@ -0,0 +1,15 @@ +package com.supervision; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@MapperScan(basePackages = {"com.supervision.**.mapper"}) +@SpringBootApplication(scanBasePackages = {"com.supervision.**"}) +public class SpringAiDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringAiDemoApplication.class, args); + } + +} diff --git a/src/main/java/com/supervision/common/constant/Constants.java b/src/main/java/com/supervision/common/constant/Constants.java new file mode 100644 index 0000000..05a4d07 --- /dev/null +++ b/src/main/java/com/supervision/common/constant/Constants.java @@ -0,0 +1,69 @@ +package com.supervision.common.constant; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 通用常量信息 + * + * @author qimaoyu + * @version 1.0.0 2020/10/20 11:07 + * @since JDK17 + */ +public class Constants {//常量类 + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 成功标记 + */ + public static final Integer SUCCESS = 200; + + /** + * 失败标记 + */ + public static final Integer FAIL = 500; + + /** + * 短信字符集 + */ + public static final String PHONE_ENCODING = "UTF-8"; + + + /** + * jwt: + * secret: XX$^^&^%%VHGZ!@@$#%@#%$%$^VBJHA7938217649&*^GBHU + * issuer: dareway.user + * expires: 12 + * 令牌有效期(小时) + */ + public static final String SECRET = "XX$^^&^%%VHGZ!@@$#%@#%$%$^VBJHA7938217649&*^GBHU"; + public static final String ISSUER = "dareway.user"; + public static final int EXPIRES_TIME = 12; + + public static final String TOTAL_COUNT = "total"; + public static final String RESULT_LIST = "result"; + + public static final String COMMA = ","; + + public static final String CONTENT_TYPE_OCTET_STREAM = "application/octet-stream"; + +} diff --git a/src/main/java/com/supervision/common/domain/R.java b/src/main/java/com/supervision/common/domain/R.java new file mode 100644 index 0000000..832b4de --- /dev/null +++ b/src/main/java/com/supervision/common/domain/R.java @@ -0,0 +1,147 @@ +package com.supervision.common.domain; + + +import com.supervision.common.constant.Constants; +import com.supervision.common.enums.ResultStatusEnum; +import lombok.Data; + +import java.io.Serializable; +import java.util.*; + +/** + * 响应信息主体 + * + * @author qimaoyu + */ +@Data +public class R implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final String TOTAL_COUNT = "total"; + public static final String RESULT_LIST = "result"; + + /** 成功 */ + public static final int SUCCESS = Constants.SUCCESS; + + /** 失败 */ + public static final int FAIL = Constants.FAIL; + + private int code; + + private String msg; + + private T data; + + public static R ok() { + return restResult(null, SUCCESS, null); + } + + public static R okMsg(String msg) { + return restResult(null, SUCCESS, msg); + } + + public static R ok(T data) { + return restResult(data, SUCCESS, null); + } + + public static R ok(T data, String msg) { + return restResult(data, SUCCESS, msg); + } + + public static R fail() { + return restResult(null, FAIL, null); + } + + public static R fail(String msg) { + return restResult(null, FAIL, msg); + } + + public static R fail(T data) { + return restResult(data, FAIL, null); + } + + public static R fail(T data, String msg) { + return restResult(data, FAIL, msg); + } + + public static R fail(int code, String msg) { + return restResult(null, code, msg); + } + + public static R fail(ResultStatusEnum resultStatusEnum) { + return restResult(resultStatusEnum); + } + + public static R fail(ResultStatusEnum resultStatusEnum, T data) {return restResult(resultStatusEnum,data);} + + private static R restResult(ResultStatusEnum resultStatusEnum, T data) { + R apiResult = new R<>(); + apiResult.setCode(resultStatusEnum.getCode()); + apiResult.setData(data); + apiResult.setMsg(resultStatusEnum.getMessage()); + return apiResult; + } + + private static R restResult(ResultStatusEnum resultStatusEnum) { + R apiResult = new R<>(); + apiResult.setCode(resultStatusEnum.getCode()); + apiResult.setData(null); + apiResult.setMsg(resultStatusEnum.getMessage()); + return apiResult; + } + + private static R restResult(T data, int code, String msg) { + R apiResult = new R<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } + + + + public static Map buildDataMap(List list) { + Map dataMap = new HashMap<>(); + if (list == null) { + dataMap.put(TOTAL_COUNT, 0); + dataMap.put(RESULT_LIST, new ArrayList<>()); + } else { + dataMap.put(TOTAL_COUNT, list.size()); + dataMap.put(RESULT_LIST, list); + } + return dataMap; + } + + public static Map buildDataMap(List list, Long total) { + Map dataMap = new HashMap<>(); + dataMap.put(TOTAL_COUNT, total); + dataMap.put(RESULT_LIST, list); + return dataMap; + } + + public static Map buildDataMap(Set list) { + Map dataMap = new HashMap<>(); + if (list == null) { + dataMap.put(TOTAL_COUNT, 0); + dataMap.put(RESULT_LIST, new ArrayList<>()); + } else { + dataMap.put(TOTAL_COUNT, list.size()); + dataMap.put(RESULT_LIST, list); + } + return dataMap; + } + + public static Map buildDataMap(Object object) { + if (object == null) { + return null; + } + List resultList = new ArrayList<>(); + resultList.add(object); + Map dataMap = new HashMap<>(); + dataMap.put(TOTAL_COUNT, resultList.size()); + dataMap.put(RESULT_LIST, resultList); + return dataMap; + } + +} diff --git a/src/main/java/com/supervision/common/enums/ResultStatusEnum.java b/src/main/java/com/supervision/common/enums/ResultStatusEnum.java new file mode 100644 index 0000000..33a979e --- /dev/null +++ b/src/main/java/com/supervision/common/enums/ResultStatusEnum.java @@ -0,0 +1,51 @@ +package com.supervision.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * 响应结果状态枚举类 + * @author qimaoyu + * @create 2019-07-14 10:22 + */ +@NoArgsConstructor +@AllArgsConstructor +public enum ResultStatusEnum { + + AUTHENTICATION_FAILED(320, "token失效,请重新登录!"), + NO_ACCESS_TO_THIS_INTERFACE(320, "无权访问此接口!"), + FAILED_TO_GENERATE_TOKEN(321, "生成token失败!"), + ACCOUNT_PASSWORD_INCORRECT(322, "账号或密码错误!"), + ACCOUNT_NOT_CREATE(323, "账号未创建!"), + HAS_BEEN_PULLED_BLACK(324, "已被删除或禁用,无法登录!"), + USERNAME_MAIL_IS_EXIST(341, "登录名称已经被注册!"), + USERNAME_IS_BLANK(342, "登录名称为空!"), + VERIFICATION_CODE_EXPIRED(350,"验证码已过期,请重新获取。"), + VERIFICATION_CODE_FAILURE(351,"验证码输入错误。"), + OPERATE_FAIL(360,"修改毕业生信息失败。"), + DATA_IS_EMPTY(370,"查询到的结果为空"), + SYSTEM_ABNORMAL(500, "系统繁忙,请稍后重试!"), + UPLOAD_EXCEPTION(501, "文件上传异常!"), + EXPORT_EXCEPTION(502, "文件导出异常!"), + INCORRECT_FILE_FORMAT(503, "文件格式不正确!"), + PARAMETER_CANNOT_BE_EMPTY(504, "参数不能为空,操作失败!"), + NO_TEMP_UPLOADFILEPATH(505,"未配置文件上传临时存储路径"), + USER_DOES_NOT_EXIST(507, "用户不存在,操作失败!"), + IMPORT_COMPANY_FORMAT_ERROR(521,"Excel表格格式错误!"), + IMPORT_COMPANY_FAIL(522,"部分数据导入失败"), + INSERT_FAIL(600,"新增失败"), + DuplicateKeyException(601,"该条信息已经存在,请勿重复添加"), + UPDATE_FAIL(700,"更新失败"), + DELETE_FAIL(800,"删除失败"), + YEAR_IS_CLOSE(1001,"该年度暂未开启"); + + @Getter + @Setter + private int code; + + @Getter + @Setter + private String message; +} diff --git a/src/main/java/com/supervision/common/exception/CustomException.java b/src/main/java/com/supervision/common/exception/CustomException.java new file mode 100644 index 0000000..0f32f01 --- /dev/null +++ b/src/main/java/com/supervision/common/exception/CustomException.java @@ -0,0 +1,29 @@ +package com.supervision.common.exception; + +import com.supervision.common.enums.ResultStatusEnum; +import lombok.Getter; + +/** + * 自定制异常类 + * @create 2019-07-14 10:33 + * @author qmy + */ +@Getter +public class CustomException extends RuntimeException { + private int code; + private String message; + + public CustomException(int code, String message) { + this.code = code; + this.message = message; + } + + public CustomException(ResultStatusEnum resultStatusEnum) { + this.code = resultStatusEnum.getCode(); + this.message = resultStatusEnum.getMessage(); + } + + public CustomException setEnum(ResultStatusEnum resultStatusEnum){ + return new CustomException(resultStatusEnum.getCode(),resultStatusEnum.getMessage()); + } +} \ No newline at end of file diff --git a/src/main/java/com/supervision/common/utils/ExcelReader.java b/src/main/java/com/supervision/common/utils/ExcelReader.java new file mode 100644 index 0000000..791945f --- /dev/null +++ b/src/main/java/com/supervision/common/utils/ExcelReader.java @@ -0,0 +1,277 @@ +package com.supervision.common.utils; + +import com.supervision.common.constant.Constants; +import com.supervision.police.domain.ModelCase; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class ExcelReader { + + /** + * Excel读取 操作 xls文件 + */ + public static List> readExcelLow2007(InputStream is, String sheetName) throws IOException { + HSSFWorkbook wb = null; + try { + wb = new HSSFWorkbook(is); + } catch (IOException e) { + e.printStackTrace(); + } + Sheet sheet; + if (StringUtils.isEmpty(sheetName)) { + sheet = wb.getSheetAt(0); + } else { + // 得到第一个sheet + sheet = wb.getSheet(sheetName); + } + // 得到Excel的行数 + int totalRows = sheet.getPhysicalNumberOfRows(); + + // 得到Excel的列数 + int totalCells = 0; + if (totalRows >= 1 && sheet.getRow(0) != null) { + totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); + } + + List> dataLst = new ArrayList<>(); + // 循环Excel的行 + for (int r = 0; r < totalRows; r++) { + Row row = sheet.getRow(r); + if (row == null) { + continue; + } + List rowLst = new ArrayList<>(); + // 循环Excel的列 + for (int c = 0; c < totalCells; c++) { + Cell cell = row.getCell(c); + String cellValue = ""; + if (null != cell) { + // 以下是判断数据的类 + switch (cell.getCellType()) { + case NUMERIC: // 数字 + cell.setCellType(CellType.STRING); + cellValue = String.valueOf(cell.getRichStringCellValue().getString()); + break; + case STRING: // 字符串 + cellValue = String.valueOf(cell.getStringCellValue()); + break; + case BOOLEAN: // Boolean + cellValue = String.valueOf(cell.getBooleanCellValue()); + break; + case FORMULA: // 公式 + //判断嵌入单元格的图片 + if (cell.getStringCellValue().contains("=DISPIMG(")) { + cellValue = ""; + } else { + cellValue = String.valueOf(cell.getNumericCellValue()); + } + break; + case BLANK: // 空值 + cellValue = null; + break; + case ERROR: // 故障 + cellValue = "非法字符"; + break; + default: + cellValue = "未知类型"; + break; + } + } + rowLst.add(cellValue); + } + //如果出现空行,则结束 + boolean isNull = false; + for (String str : rowLst) { + if (StringUtils.isNotEmpty(str)) { + isNull = false; + break; + } + isNull = true; + } + if (isNull) { + return dataLst; + } + // 保存第r行的第c列 + dataLst.add(rowLst); + } + return dataLst; + } + + /** + * Excel读取 操作 2007+版本 xlsx文件 + */ + public static List> readExcel2007(InputStream is, String sheetName) throws IOException { + XSSFWorkbook wb = null; + try { + wb = new XSSFWorkbook(is); + } catch (IOException e) { + e.printStackTrace(); + } + Sheet sheet; + if (StringUtils.isEmpty(sheetName)) { + sheet = wb.getSheetAt(0); + } else { + // 得到第一个sheet + sheet = wb.getSheet(sheetName); + } + // 得到Excel的行数 + int totalRows = sheet.getPhysicalNumberOfRows(); + + // 得到Excel的列数 + int totalCells = 0; + if (totalRows >= 1 && sheet.getRow(0) != null) { + totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); + } + + List> dataLst = new ArrayList<>(); + // 循环Excel的行 + for (int r = 0; r < totalRows; r++) { + Row row = sheet.getRow(r); + if (row == null) { + continue; + } + List rowLst = new ArrayList<>(); + // 循环Excel的列 + for (int c = 0; c < totalCells; c++) { + Cell cell = row.getCell(c); + String cellValue = ""; + if (null != cell) { + // 以下是判断数据的类 + switch (cell.getCellType()) { + case NUMERIC: // 数字 +// cell.setCellType(Cell.CELL_TYPE_STRING); + cell.setCellType(CellType.STRING); + cellValue = String.valueOf(cell.getRichStringCellValue().getString()); + break; + case STRING: // 字符串 + cellValue = String.valueOf(cell.getStringCellValue()); + break; + case BOOLEAN: // Boolean + cellValue = String.valueOf(cell.getBooleanCellValue()); + break; + case FORMULA: // 公式 + if (cell.getCellFormula().contains("=DISPIMG(")) { + cellValue = ""; + } else { + cellValue = cell.getCellFormula(); + } + break; + case BLANK: // 空值 + cellValue = null; + break; + case ERROR: // 故障 + cellValue = "非法字符"; + break; + default: + cellValue = "未知类型"; + break; + } + } + rowLst.add(cellValue); + } + //如果出现空行,则结束 + boolean isNull = false; + for (String str : rowLst) { + if (StringUtils.isNotEmpty(str)) { + isNull = false; + break; + } + isNull = true; + } + if (isNull) { + return dataLst; + } + // 保存第r行的第c列 + dataLst.add(rowLst); + } + return dataLst; + } + + /** + * 根据excel生成 实体类 + * + * @param is + * @return + * @throws IOException + */ + public static List getCaseList(InputStream is, String fileSuffix, String sheetName) throws IOException { + List> list = new ArrayList<>(); + + if ("xls".equals(fileSuffix)) { + list = ExcelReader.readExcelLow2007(is, sheetName); + } else if ("xlsx".equals(fileSuffix)) { + list = ExcelReader.readExcel2007(is, sheetName); + } + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + //遍历数据到实体集合开始 + List listBean = new ArrayList<>(); + for (int i = 1; i < list.size(); i++) { // i=1是因为第一行不要 + ModelCase uBean = new ModelCase(); + List listStr = list.get(i); + for (int j = 0; j < listStr.size(); j++) { + //.replace((char)12288, ' ') 替换中文全角空格(全角空格无法用trim去掉)为半角空格 + String str = listStr.get(j) == null ? null : listStr.get(j).replace((char)12288, ' ').trim(); + switch (j) { + case 0: + //案件编号 + uBean.setCaseNo(str); + break; + case 1: + //案件名称 + uBean.setCaseName(str); + break; + case 2: + //案件类型 + uBean.setCaseTypeName(str); + break; + case 3: + //案件状态 + uBean.setCaseStatusName(str); + break; + case 4: + //作案方式 + uBean.setCrimeModeName(str); + break; + case 5: + //案件描述 + uBean.setCaseDetail(str); + break; + case 6: + try { + //立案时间 + uBean.setRegisterTime(format.parse(str)); + } catch (Exception e) { + uBean.setRegisterTime(null); + } + break; + case 7: + try { + //受理时间 + uBean.setAcceptTime(format.parse(str)); + } catch (Exception e) { + uBean.setAcceptTime(null); + } + break; + default: + } + } + listBean.add(uBean); + } //遍历数据到实体集合结束 + return listBean; + } + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/common/utils/IPages.java b/src/main/java/com/supervision/common/utils/IPages.java new file mode 100644 index 0000000..a97419b --- /dev/null +++ b/src/main/java/com/supervision/common/utils/IPages.java @@ -0,0 +1,28 @@ +package com.supervision.common.utils; + +import com.baomidou.mybatisplus.core.metadata.IPage; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.supervision.common.constant.Constants.RESULT_LIST; +import static com.supervision.common.constant.Constants.TOTAL_COUNT; + +public class IPages { + + public static Map buildDataMap(IPage iPage) { + Map dataMap = new HashMap<>(); + dataMap.put(TOTAL_COUNT, iPage.getTotal()); + dataMap.put(RESULT_LIST, iPage.getRecords()); + return dataMap; + } + + public static Map buildDataMap(List list, int total) { + Map dataMap = new HashMap(); + dataMap.put(TOTAL_COUNT, total); + dataMap.put(RESULT_LIST, list); + return dataMap; + } + +} diff --git a/src/main/java/com/supervision/common/utils/ListUtils.java b/src/main/java/com/supervision/common/utils/ListUtils.java new file mode 100644 index 0000000..ae531cb --- /dev/null +++ b/src/main/java/com/supervision/common/utils/ListUtils.java @@ -0,0 +1,88 @@ +package com.supervision.common.utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author qmy + * @description + * @createTime 2022/4/22 + */ +public class ListUtils { + + /** + * list分页器 + * 注意:分页时一定要将list按统一顺序排序。 + * @param pageSize + * @param pageIndex + * @param list + * @param + * @return + */ + public static List Pager(int pageSize, int pageIndex, List list){ + //使用list 中的sublist方法分页 + List dataList = new ArrayList<>(); + // 每页显示多少条记录 + + int currentPage; //当前第几页数据 + // 一共多少条记录 + int totalRecord = list.size(); + // 一共多少页 + int totalPage = totalRecord % pageSize; + if (totalPage > 0) { + totalPage = totalRecord / pageSize + 1; + } else { + totalPage = totalRecord / pageSize; + } + + System.out.println("总页数:" + totalPage); + + // 当前第几页数据 + currentPage = totalPage < pageIndex ? totalPage : pageIndex; + + // 起始索引 + int fromIndex = pageSize * (currentPage - 1); + fromIndex = fromIndex > 0 ? fromIndex : 0; + + // 结束索引 + int toIndex = pageSize * currentPage > totalRecord ? totalRecord : pageSize * currentPage; + try{ + dataList = list.subList(fromIndex, toIndex); + }catch(IndexOutOfBoundsException e){ + e.printStackTrace(); + } + return dataList; + } + + /** + * @description 获取当前页数 + * @method getCurrentPage + * @param pageSize + * @param pageIndex + * @param list + * @return int + */ + public static int getCurrentPage(int pageSize, int pageIndex, List list){ + //使用list 中的sublist方法分页 + List dataList = new ArrayList<>(); + // 每页显示多少条记录 + + int currentPage; //当前第几页数据 + // 一共多少条记录 + int totalRecord = list.size(); + // 一共多少页 + int totalPage = totalRecord % pageSize; + if (totalPage > 0) { + totalPage = totalRecord / pageSize + 1; + } else { + totalPage = totalRecord / pageSize; + } + + System.out.println("总页数:" + totalPage); + + // 当前第几页数据 + currentPage = totalPage < pageIndex ? totalPage : pageIndex; + + return currentPage; + } +} diff --git a/src/main/java/com/supervision/common/utils/StringUtils.java b/src/main/java/com/supervision/common/utils/StringUtils.java new file mode 100644 index 0000000..c51c759 --- /dev/null +++ b/src/main/java/com/supervision/common/utils/StringUtils.java @@ -0,0 +1,619 @@ +package com.supervision.common.utils; + + + +import java.util.*; + +/** + * 字符串工具类 + * + * @author qmy + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final char SEPARATOR = '_'; + + /** 星号 */ + private static final String START = "*"; + + /** + * 获取参数不为空值 + * + * @param value defaultValue 要判断的value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Collection coll) + { + return !isEmpty(coll); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * * 判断一个对象数组是否非空 + * + * @param objects 要判断的对象数组 + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Object[] objects) + { + return !isEmpty(objects); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Map map) + { + return !isEmpty(map); + } + + /** + * * 判断一个字符串是否为空串 + * + * @param str String + * @return true:为空 false:非空 + */ + public static boolean isEmpty(String str) + { + return isNull(str) || NULLSTR.equals(str.trim()); + } + + /** + * * 判断一个字符串是否为非空串 + * + * @param str String + * @return true:非空串 false:空串 + */ + public static boolean isNotEmpty(String str) + { + return !isEmpty(str); + } + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) + { + return object == null; + } + + /** + * * 判断一个对象是否非空 + * + * @param object Object + * @return true:非空 false:空 + */ + public static boolean isNotNull(Object object) + { + return !isNull(object); + } + + /** + * * 判断一个对象是否是数组类型(Java基本型别的数组) + * + * @param object 对象 + * @return true:是数组 false:不是数组 + */ + public static boolean isArray(Object object) + { + return isNotNull(object) && object.getClass().isArray(); + } + + /** + * 去空格 + */ + public static String trim(String str) + { + return (str == null ? "" : str.trim()); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) + { + if (str == null) + { + return NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * 下划线转驼峰命名 + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) + { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰式命名法 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (c == SEPARATOR) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String testStr : strs) + { + if (matches(str, testStr)) + { + return true; + } + } + return false; + } + + /** + * 查找指定字符串是否匹配指定字符串数组中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, String... strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String testStr : strs) + { + if (matches(str, testStr)) + { + return true; + } + } + return false; + } + + /** + * 查找指定字符串是否匹配 + * + * @param str 指定字符串 + * @param pattern 需要检查的字符串 + * @return 是否匹配 + */ + public static boolean matches(String str, String pattern) + { + if (isEmpty(pattern) || isEmpty(str)) + { + return false; + } + + pattern = pattern.replaceAll("\\s*", ""); // 替换空格 + int beginOffset = 0; // pattern截取开始位置 + int formerStarOffset = -1; // 前星号的偏移位置 + int latterStarOffset = -1; // 后星号的偏移位置 + + String remainingURI = str; + String prefixPattern = ""; + String suffixPattern = ""; + + boolean result = false; + do + { + formerStarOffset = indexOf(pattern, START, beginOffset); + prefixPattern = substring(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length()); + + // 匹配前缀Pattern + result = remainingURI.contains(prefixPattern); + // 已经没有星号,直接返回 + if (formerStarOffset == -1) + { + return result; + } + + // 匹配失败,直接返回 + if (!result) + return false; + + if (!isEmpty(prefixPattern)) + { + remainingURI = substringAfter(str, prefixPattern); + } + + // 匹配后缀Pattern + latterStarOffset = indexOf(pattern, START, formerStarOffset + 1); + suffixPattern = substring(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length()); + + result = remainingURI.contains(suffixPattern); + // 匹配失败,直接返回 + if (!result) + return false; + + if (!isEmpty(suffixPattern)) + { + remainingURI = substringAfter(str, suffixPattern); + } + + // 移动指针 + beginOffset = latterStarOffset + 1; + + } + while (!isEmpty(suffixPattern) && !isEmpty(remainingURI)); + + return true; + } + + /** + * 生成随机六位数字字符串,用作验证码 + */ + public static String getRandomCode() { + String sources = "0123456789"; // 加上一些字母,就可以生成pc站的验证码了 + Random rand = new Random(); + StringBuffer flag = new StringBuffer(); + for (int j = 0; j < 6; j++) + { + flag.append(sources.charAt(rand.nextInt(9)) + ""); + } + return flag.toString(); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } + + /** + * strs是否包含str (包含null情况) + * @param strs + * @param str + * @return + */ + public static boolean isContains(String strs, String str) { + if (str != null && str!="") { + if (strs == null) { + return false; + } else { + return strs.contains(str); + } + } else { + return true; + } + } + + /** + * 将字符串中的 _小写 转化为 大写, 若最后一位为_, 则删除_ + * @param str + * @return + */ + public static String _toUpper(String str) { + if (str == null) { + return ""; + } + if (str.endsWith("_")) { + str = str.substring(0, str.length() - 1); + } + while (str.contains("_")) { + int i = str.indexOf("_"); + System.out.println(i); + String lower = str.substring(i + 1, i + 2); + String upper = lower.toUpperCase(); + str = str.replace("_" + lower, upper); + } + return str; + } + + /** + * 将数字转为大写 + */ + private static char[] cnArr = new char[]{'一', '二', '三', '四', '五', '六', '七', '八', '九'}; + + /** + * 将数字转换为中文数字, 这里只写到了万 + * + * @param arabicNum 阿拉伯数字 + * @return 中文数字 + */ + public static String arabicNumToChineseNum(int arabicNum) { + String si = String.valueOf(arabicNum); + String sd = ""; + if (si.length() == 1) { + if (arabicNum == 0) { + return sd; + } + sd += cnArr[arabicNum - 1]; + return sd; + } else if (si.length() == 2) { + if (si.substring(0, 1).equals("1")) { + sd += "十"; + if (arabicNum % 10 == 0) { + return sd; + } + } else { + sd += (cnArr[arabicNum / 10 - 1] + "十"); + } + sd += arabicNumToChineseNum(arabicNum % 10); + } else if (si.length() == 3) { + sd += (cnArr[arabicNum / 100 - 1] + "百"); + if (String.valueOf(arabicNum % 100).length() < 2) { + if (arabicNum % 100 == 0) { + return sd; + } + sd += "零"; + } + sd += arabicNumToChineseNum(arabicNum % 100); + } else if (si.length() == 4) { + sd += (cnArr[arabicNum / 1000 - 1] + "千"); + if (String.valueOf(arabicNum % 1000).length() < 3) { + if (arabicNum % 1000 == 0) { + return sd; + } + sd += "零"; + } + sd += arabicNumToChineseNum(arabicNum % 1000); + } else if (si.length() == 5) { + sd += (cnArr[arabicNum / 10000 - 1] + "万"); + if (String.valueOf(arabicNum % 10000).length() < 4) { + if (arabicNum % 10000 == 0) { + return sd; + } + sd += "零"; + } + sd += arabicNumToChineseNum(arabicNum % 10000); + } + return sd; + } + + public static String getUUID() { + return UUID.randomUUID().toString().replaceAll("-", ""); + } + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/config/BeanPostProcessorConfig.java b/src/main/java/com/supervision/config/BeanPostProcessorConfig.java new file mode 100644 index 0000000..391e30b --- /dev/null +++ b/src/main/java/com/supervision/config/BeanPostProcessorConfig.java @@ -0,0 +1,54 @@ +//package com.supervision.config; +// +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.BeansException; +//import org.springframework.beans.factory.config.BeanPostProcessor; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.util.ReflectionUtils; +//import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; +//import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider; +//import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; +// +//import java.lang.reflect.Field; +//import java.util.List; +//import java.util.stream.Collectors; +// +//@Slf4j +//@Configuration +//public class BeanPostProcessorConfig { +// +// @Bean +// public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { +// return new BeanPostProcessor() { +// @Override +// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { +// if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { +// customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); +// } +// return bean; +// } +// +// private void customizeSpringfoxHandlerMappings(List mappings) { +// List copy = mappings.stream() +// .filter(mapping -> mapping.getPatternParser() == null) +// .collect(Collectors.toList()); +// mappings.clear(); +// mappings.addAll(copy); +// } +// +// @SuppressWarnings("unchecked") +// private List getHandlerMappings(Object bean) { +// try { +// Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); +// field.setAccessible(true); +// return (List) field.get(bean); +// } catch (IllegalArgumentException | IllegalAccessException e) { +// throw new IllegalStateException(e); +// } +// } +// }; +// } +// +//} +// diff --git a/src/main/java/com/supervision/config/CorsConfig.java b/src/main/java/com/supervision/config/CorsConfig.java new file mode 100644 index 0000000..854db24 --- /dev/null +++ b/src/main/java/com/supervision/config/CorsConfig.java @@ -0,0 +1,33 @@ +package com.supervision.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 设置跨域 + * + * @author qmy + * @version 1.0.0 2020/10/21 15:17 + * @since JDK1.8 + */ +@Configuration +@EnableWebMvc +public class CorsConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + // 设置允许跨域的路径 + registry.addMapping("/**") + // 设置允许跨域请求的域名 + .allowedOriginPatterns("*") + // 是否允许整数 不再默认开启 + .allowCredentials(true) + // 设置允许的方法 + .allowedMethods("*") + // 跨域允许时间 + .maxAge(3600); + } + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/config/MinioConfig.java b/src/main/java/com/supervision/config/MinioConfig.java new file mode 100644 index 0000000..279676e --- /dev/null +++ b/src/main/java/com/supervision/config/MinioConfig.java @@ -0,0 +1,41 @@ +package com.supervision.config; + +import io.minio.MinioClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +/** + * Endpoint 对象存储服务的URL + * Access Key Access key就像用户ID,可以唯一标识你的账户。 + * Secret Key Secret key是你账户的密码。 + * + * @author qmy + * @since 1.0.0 + */ +@Configuration +public class MinioConfig { + + @Value("${minio.endpoint}") + private String endpoint; + + @Value("${minio.accessKey}") + private String accessKey; + + @Value("${minio.secretKey}") + private String secretKey; + + + @Bean + @Primary + public MinioClient minioClient() { + // Create a minioClient with the MinIO server playground, its access key and secret key. + return MinioClient.builder() + .endpoint(endpoint) + .credentials(accessKey, secretKey) + .build(); + } + +} + diff --git a/src/main/java/com/supervision/config/MyMetaObjectHandler.java b/src/main/java/com/supervision/config/MyMetaObjectHandler.java new file mode 100644 index 0000000..dcc04e7 --- /dev/null +++ b/src/main/java/com/supervision/config/MyMetaObjectHandler.java @@ -0,0 +1,26 @@ +package com.supervision.config; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; + +import java.util.Date; + +/** + * @author Ray + */ +public class MyMetaObjectHandler implements MetaObjectHandler { + public MyMetaObjectHandler() { + } + + @Override + public void insertFill(MetaObject metaObject) { + this.setFieldValByName("createTime", new Date(), metaObject); + this.setFieldValByName("updateTime", new Date(), metaObject); + } + + @Override + public void updateFill(MetaObject metaObject) { + this.setFieldValByName("updateTime", new Date(), metaObject); + } + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/config/MybatisPlusConfig.java b/src/main/java/com/supervision/config/MybatisPlusConfig.java new file mode 100644 index 0000000..f86cfb5 --- /dev/null +++ b/src/main/java/com/supervision/config/MybatisPlusConfig.java @@ -0,0 +1,43 @@ +package com.supervision.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MybatisPlus配置 + * + * @author qmy + * @version 1.0.0 2020/10/22 9:47 + * @since JDK1.8 + */ +@Configuration +public class MybatisPlusConfig { + + @Bean + public MyMetaObjectHandler myMetaObjectHandler() { + return new MyMetaObjectHandler(); + } + + /** + * 拦截器配置 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(this.paginationInterceptor()); + return interceptor; + } + + private PaginationInnerInterceptor paginationInterceptor() { + PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(); + paginationInterceptor.setOverflow(false); + /** + * 注意! 此处要设置数据库类型. + */ + paginationInterceptor.setDbType(DbType.MYSQL); + return paginationInterceptor; + } +} diff --git a/src/main/java/com/supervision/config/Neo4jConfig.java b/src/main/java/com/supervision/config/Neo4jConfig.java new file mode 100644 index 0000000..2c67682 --- /dev/null +++ b/src/main/java/com/supervision/config/Neo4jConfig.java @@ -0,0 +1,32 @@ +package com.supervision.config; + +import org.neo4j.driver.AuthTokens; +import org.neo4j.driver.Config; +import org.neo4j.driver.Driver; +import org.neo4j.driver.GraphDatabase; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Neo4jConfig { + + @Value("${spring.neo4j.uri}") + private String URI; + @Value("${spring.neo4j.authentication.username}") + private String USER; + @Value("${spring.neo4j.authentication.password}") + private String PASSWORD; + + @Bean + public Driver neo4jDriver() { + // 这里可以添加额外的配置,比如加密、连接池设置等 + Config config = Config.builder() + // 示例:关闭加密(注意:在生产环境中应该启用加密) + .withoutEncryption() + // 你可以在这里添加更多的配置选项 + .build(); + + return GraphDatabase.driver(URI, AuthTokens.basic(USER, PASSWORD), config); + } +} \ No newline at end of file diff --git a/src/main/java/com/supervision/minio/client/MinioTemplate.java b/src/main/java/com/supervision/minio/client/MinioTemplate.java new file mode 100644 index 0000000..6c30a48 --- /dev/null +++ b/src/main/java/com/supervision/minio/client/MinioTemplate.java @@ -0,0 +1,214 @@ +package com.supervision.minio.client; + +import cn.hutool.core.io.IoUtil; +import com.supervision.minio.exception.SysObsException; +import io.minio.*; +import io.minio.errors.MinioException; +import io.minio.http.Method; +import io.minio.messages.Bucket; +import io.minio.messages.DeleteError; +import io.minio.messages.DeleteObject; +import io.minio.messages.Item; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * minio 操作Template + * + * @author qmy + * @version 1.0.0 2021/6/22 14:42 + * @since JDK1.8 + */ +@Component +@Slf4j +public class MinioTemplate { + + @Autowired + private MinioClient minioClient; + + /** + * 上传对象 + * + * @param bucketName 存储桶名称 + * @param objectName 对象名称 + * @param userMetadata metaData + * @param stream 流 + * @param objectSize 大小 + * @param contentType contentType + * @return void + * @author qmy + * @version 1.0.0 2021/6/30 9:11 + * @since JDK1.8 + */ + public void putObject(String bucketName, String objectName, Map userMetadata, InputStream stream, long objectSize, String contentType) { + try { + minioClient.putObject(PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .userMetadata(userMetadata) + .contentType(contentType == null ? "application/octet-stream" : contentType) + .stream(stream, objectSize, -1) + .build()); + } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new SysObsException(e.getMessage()); + } + } + + /** + * 下载对象 + * + * @param bucketName 存储桶名称 + * @param objectName 对象名称 + * @param response response + * @return void + * @author qmy + * @version 1.0.0 2021/6/30 9:11 + * @since JDK1.8 + */ + public void getObject(String bucketName, String objectName, String fileType, HttpServletResponse response) { + try { + InputStream inputStream = minioClient.getObject( + GetObjectArgs.builder().bucket(bucketName).object(objectName).build()); + + StatObjectResponse statObjectResponse = minioClient.statObject( + StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); + + String fileName = objectName + "." + fileType; + response.setHeader("Content-Disposition", "inline;filename=" + fileName); + response.setCharacterEncoding("UTF-8"); + response.setContentLengthLong(statObjectResponse.size()); + response.setContentType(statObjectResponse.contentType()); + + IoUtil.copy(inputStream, response.getOutputStream()); + inputStream.close(); + } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new SysObsException(e.getMessage()); + } + } + + /** + * 下载对象 + * + * @param bucketName 存储桶名称 + * @param objectName 对象名称 + * @return void + * @author qmy + * @version 1.0.0 2021/6/30 9:11 + * @since JDK1.8 + */ + public GetObjectResponse getInputStreamObject(String bucketName, String objectName) { + GetObjectResponse inputStream; + try { + inputStream = minioClient.getObject( + GetObjectArgs.builder().bucket(bucketName).object(objectName).build()); + return inputStream; + } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new SysObsException(e.getMessage()); + } + } + + /** + * 删除对象 + * + * @param bucketName 存储桶名称 + * @param objectName 对象名称 + * @return void + * @author qmy + * @version 1.0.0 2021/6/30 9:08 + * @since JDK1.8 + */ + public void removeObject(String bucketName, String objectName) { + try { + minioClient.removeObject( + RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); + } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new SysObsException(e.getMessage()); + } + } + + /** + * 删除对象 + * + * @param bucketName 存储桶名称 + * @param objectNames 对象名称 + * @return void + * @author qmy + * @version 1.0.0 2021/6/30 9:08 + * @since JDK1.8 + */ + public List> removeObject(String bucketName, Set objectNames) { + try { + List objects = new LinkedList<>(); + for (String objectName : objectNames) { + objects.add(new DeleteObject(objectName)); + } + Iterable> results = minioClient.removeObjects( + RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build()); + List> errorInfo = new ArrayList<>(); + for (Result result : results) { + DeleteError error = result.get(); + errorInfo.add(new HashMap(2) {{ + put("objectName", error.objectName()); + put("message", error.message()); + }}); + } + return errorInfo; + } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new SysObsException(e.getMessage()); + } + } + + /** + * 获取对象信息 + * + * @param bucketName 存储桶名称 + * @param objectName 对象名称 + * @return io.minio.StatObjectResponse + * @author qmy + * @version 1.0.0 2021/6/30 9:07 + * @since JDK1.8 + */ + public StatObjectResponse statObject(String bucketName, String objectName) { + try { + return minioClient.statObject( + StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); + } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new SysObsException(e.getMessage()); + } + } + + /** + * 对象是否存在 + * + * @param bucketName 存储桶名称 + * @param objectName 对象名称 + * @return boolean + * @author qmy + * @version 1.0.0 2021/6/30 9:15 + * @since JDK1.8 + */ + public boolean objectExists(String bucketName, String objectName) { + try { + return minioClient.statObject( + StatObjectArgs.builder().bucket(bucketName).object(objectName).build()) != null; + } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { + return false; + } + } + +} diff --git a/src/main/java/com/supervision/minio/controller/MinioController.java b/src/main/java/com/supervision/minio/controller/MinioController.java new file mode 100644 index 0000000..18ec6c1 --- /dev/null +++ b/src/main/java/com/supervision/minio/controller/MinioController.java @@ -0,0 +1,34 @@ +package com.supervision.minio.controller; + +import com.supervision.common.domain.R; +import com.supervision.minio.service.MinioService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +@RestController +@RequestMapping("minio") +public class MinioController { + + @Autowired + private MinioService minioService; + + @PostMapping("/uploadFile") + public String uploadFile(@RequestPart("file") MultipartFile file) throws IOException { + return minioService.uploadFile(file); + } + + @GetMapping("/downloadFile") + public void downloadFile(@RequestParam String fileId, HttpServletResponse response) { + minioService.downloadFile(fileId, response); + } + + @PostMapping("/delFile") + public R delFile(@RequestParam String fileId) { + return minioService.delFile(fileId); + } + +} diff --git a/src/main/java/com/supervision/minio/domain/MinioFile.java b/src/main/java/com/supervision/minio/domain/MinioFile.java new file mode 100644 index 0000000..edb52f6 --- /dev/null +++ b/src/main/java/com/supervision/minio/domain/MinioFile.java @@ -0,0 +1,49 @@ +package com.supervision.minio.domain; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.io.Serializable; + +/** + * 文件表(MinioFile)表实体类 + * + * @author qmy + * @since 2024-07-08 14:45:00 + */ +@Data +@TableName("minio_file") +public class MinioFile implements Serializable { + + @TableId + private String id; + + /** + * 文件名 + */ + private String filename; + + /** + * 大小 + */ + private Integer size; + + /** + * 上传时间 + */ + private Date uploadDate; + + /** + * 文件类型 + */ + private String fileType; + + /** + * + */ + private String dataStatus; + +} + diff --git a/src/main/java/com/supervision/minio/exception/SysObsException.java b/src/main/java/com/supervision/minio/exception/SysObsException.java new file mode 100644 index 0000000..42c3fd8 --- /dev/null +++ b/src/main/java/com/supervision/minio/exception/SysObsException.java @@ -0,0 +1,21 @@ +package com.supervision.minio.exception; + +/** + * @author qmy + * @version 1.0.0 2021/6/22 15:18 + * @since JDK1.8 + */ +public class SysObsException extends RuntimeException { + + private String message; + + public SysObsException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return this.message; + } + +} diff --git a/src/main/java/com/supervision/minio/mapper/MinioFileMapper.java b/src/main/java/com/supervision/minio/mapper/MinioFileMapper.java new file mode 100644 index 0000000..55bd113 --- /dev/null +++ b/src/main/java/com/supervision/minio/mapper/MinioFileMapper.java @@ -0,0 +1,15 @@ +package com.supervision.minio.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.minio.domain.MinioFile; + +/** + * 文件表(MinioFile)表数据库访问层 + * + * @author qmy + * @since 2024-07-08 14:49:58 + */ +public interface MinioFileMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/supervision/minio/service/MinioService.java b/src/main/java/com/supervision/minio/service/MinioService.java new file mode 100644 index 0000000..d369e02 --- /dev/null +++ b/src/main/java/com/supervision/minio/service/MinioService.java @@ -0,0 +1,17 @@ +package com.supervision.minio.service; + +import com.supervision.common.domain.R; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +public interface MinioService { + + String uploadFile(MultipartFile file) throws IOException; + + void downloadFile(String fileId, HttpServletResponse response); + + R delFile(String fileId); + +} diff --git a/src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java b/src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java new file mode 100644 index 0000000..a829095 --- /dev/null +++ b/src/main/java/com/supervision/minio/service/impl/MinioServiceImpl.java @@ -0,0 +1,67 @@ +package com.supervision.minio.service.impl; + +import com.supervision.common.domain.R; +import com.supervision.common.utils.StringUtils; +import com.supervision.minio.client.MinioTemplate; +import com.supervision.minio.domain.MinioFile; +import com.supervision.minio.mapper.MinioFileMapper; +import com.supervision.minio.service.MinioService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.Date; +import java.util.Objects; +import java.util.UUID; + +@Service +public class MinioServiceImpl implements MinioService { + + @Autowired + private MinioTemplate minioTemplate; + + @Value("${minio.bucketName}") + private String bucketName; + + @Autowired + private MinioFileMapper minioFileMapper; + + @Override + public String uploadFile(MultipartFile file) throws IOException { + String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".") + 1); + InputStream in = file.getInputStream(); + MinioFile minioFile = new MinioFile(); + minioFile.setFilename(file.getOriginalFilename()); + minioFile.setUploadDate(new Date()); + minioFile.setFileType(suffix); + minioFile.setSize(in.available()); + int i = minioFileMapper.insert(minioFile); + if (i > 0) { + minioTemplate.putObject(bucketName, minioFile.getId(), null, in, in.available(), null); + return minioFile.getId(); + } else { + return null; + } + } + + @Override + public void downloadFile(String fileId, HttpServletResponse response){ + MinioFile minioFile = minioFileMapper.selectById(fileId); + String fileType = minioFile.getFileType(); + minioTemplate.getObject(bucketName, fileId, fileType, response); + } + + @Override + public R delFile(String fileId) { + MinioFile minioFile = minioFileMapper.selectById(fileId); + minioFile.setDataStatus(StringUtils.getUUID()); + minioFileMapper.updateById(minioFile); + minioTemplate.removeObject(bucketName, fileId); + return R.ok(); + } + +} diff --git a/src/main/java/com/supervision/neo4j/controller/Neo4jController.java b/src/main/java/com/supervision/neo4j/controller/Neo4jController.java new file mode 100644 index 0000000..1554864 --- /dev/null +++ b/src/main/java/com/supervision/neo4j/controller/Neo4jController.java @@ -0,0 +1,83 @@ +package com.supervision.neo4j.controller; + +import com.supervision.common.domain.R; +import com.supervision.neo4j.domain.CaseNode; +import com.supervision.neo4j.domain.Rel; +import com.supervision.neo4j.service.Neo4jService; +//import io.swagger.annotations.Api; +//import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author qmy + * @since 2023-10-26 + */ +@RestController +@RequestMapping("/neo4j") +public class Neo4jController { + + @Autowired + private Neo4jService neo4jService; + + @PostMapping("/save") + public R save(@RequestBody CaseNode caseNode) { + return neo4jService.save(caseNode); + } + + @PostMapping("/delNode") + public R delNode(Long id) { + return neo4jService.delNode(id); + } + + @PostMapping("/findById") + public R findById(@RequestParam Long id) { + CaseNode node = neo4jService.findById(id); + return R.ok(node); + } + + @PostMapping("/findByName") + public R findByName(@RequestParam String caseId, + @RequestParam(required = false, defaultValue = "") String recordsId, + @RequestParam(required = false, defaultValue = "") String nodeType, + @RequestParam String name, + @RequestParam(required = false, defaultValue = "1") String picType) { + List list = neo4jService.findByName(caseId, recordsId, nodeType, name, picType); + return R.ok(list); + } + + @PostMapping("/findOneByName") + public R findOneByName(@RequestParam String caseId, + @RequestParam(required = false, defaultValue = "") String recordsId, + @RequestParam(required = false, defaultValue = "") String nodeType, + @RequestParam String name, + @RequestParam(required = false, defaultValue = "1") String picType) { + CaseNode node = neo4jService.findOneByName(caseId, recordsId, nodeType, name, picType); + return R.ok(node); + } + + @PostMapping("/findRelation") + public Rel findRelation(@RequestBody Rel rel) { + return neo4jService.findRelation(rel); + } + + @PostMapping("/saveRelation") + public R saveRelation(@RequestBody Rel rel) { + return neo4jService.saveRelation(rel); + } + + /*************************************************************************************/ + + @GetMapping("/getNode") + public R getNode(@RequestParam String picType, @RequestParam String caseId) { + return neo4jService.getNode(picType, caseId); + } + + @GetMapping("/test") + public R test() { + return neo4jService.test(); + } + +} diff --git a/src/main/java/com/supervision/neo4j/domain/CaseNode.java b/src/main/java/com/supervision/neo4j/domain/CaseNode.java new file mode 100644 index 0000000..3dc1bd3 --- /dev/null +++ b/src/main/java/com/supervision/neo4j/domain/CaseNode.java @@ -0,0 +1,58 @@ +package com.supervision.neo4j.domain; + +import lombok.Data; +import org.springframework.data.neo4j.core.schema.*; + +/** + * @author qmy + * @since 2023-10-26 + */ +@Data +public class CaseNode { + + @Id + @GeneratedValue + private Long id; + + private String name; + + private String nodeType; + + private String recordId; + + private String recordsId; + + private String caseId; + + /** + * 0抽象图谱, 1案件图谱 + */ + private String picType; + + public CaseNode() { + } + + public CaseNode(Long id, String name) { + this.id = id; + this.name = name; + } + + public CaseNode(String name, String nodeType, String recordId, String recordsId, String caseId, String picType) { + this.name = name; + this.nodeType = nodeType; + this.recordId = recordId; + this.recordsId = recordsId; + this.caseId = caseId; + this.picType = picType; + } + + public CaseNode(Long id, String name, String nodeType, String recordId, String caseId, String picType) { + this.id = id; + this.name = name; + this.nodeType = nodeType; + this.recordId = recordId; + this.caseId = caseId; + this.picType = picType; + } + +} diff --git a/src/main/java/com/supervision/neo4j/domain/Rel.java b/src/main/java/com/supervision/neo4j/domain/Rel.java new file mode 100644 index 0000000..391fd37 --- /dev/null +++ b/src/main/java/com/supervision/neo4j/domain/Rel.java @@ -0,0 +1,36 @@ +package com.supervision.neo4j.domain; + +import lombok.Data; + +@Data +public class Rel { + + private Long id; + + private String source; + private Long sourceId; + + private String name; + + private String target; + private Long targetId; + + public Rel() { + } + + public Rel(Long sourceId, String name, Long targetId) { + this.sourceId = sourceId; + this.name = name; + this.targetId = targetId; + } + + public Rel(Long id, String source, Long sourceId, String name, String target, Long targetId) { + this.id = id; + this.source = source; + this.sourceId = sourceId; + this.name = name; + this.target = target; + this.targetId = targetId; + } + +} diff --git a/src/main/java/com/supervision/neo4j/dto/ResultDTO.java b/src/main/java/com/supervision/neo4j/dto/ResultDTO.java new file mode 100644 index 0000000..9dd9240 --- /dev/null +++ b/src/main/java/com/supervision/neo4j/dto/ResultDTO.java @@ -0,0 +1,29 @@ +package com.supervision.neo4j.dto; + +import lombok.Data; + +@Data +public class ResultDTO { + + private String startId; + + private String endId; + + private String relId; + + private String recordId; + + private String recordsId; + + public ResultDTO() { + } + + public ResultDTO(String startId, String endId, String relId, String recordId, String recordsId) { + this.startId = startId; + this.endId = endId; + this.relId = relId; + this.recordId = recordId; + this.recordsId = recordsId; + } + +} diff --git a/src/main/java/com/supervision/neo4j/repository/CaseNodeRepository.java b/src/main/java/com/supervision/neo4j/repository/CaseNodeRepository.java new file mode 100644 index 0000000..6ab90ac --- /dev/null +++ b/src/main/java/com/supervision/neo4j/repository/CaseNodeRepository.java @@ -0,0 +1,40 @@ +package com.supervision.neo4j.repository; + +import com.supervision.neo4j.domain.CaseNode; +import org.springframework.data.neo4j.core.schema.Relationship; +import org.springframework.data.neo4j.repository.Neo4jRepository; +import org.springframework.data.neo4j.repository.query.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * @author qmy + * @since 2023-10-26 + */ +//@Repository +public interface CaseNodeRepository extends Neo4jRepository { + + @Query("MATCH p=(n:CaseNode) RETURN p") + List selectAll(); + + @Query("MATCH(p:Person{name:$name}) return p") + CaseNode findByName(@Param("name") String name); + + @Query("match (a)-[r:`:#{literal(#relation)}`]-(b) where a.name = $fromNodeName and b.name = $toNodeName return r") + Relationship queryRelationShip(@Param("fromNodeName") String fromNodeName, @Param("toNodeName") String toNodeName, @Param("relation") String relation); + + /** + * 创建任意两个节点关系(fromNodeId -> relation -> toNodeId) + * @param fromNodeId 源节点id + * @param toNodeId 目标节点id + * @param relation 关系 + */ + @Query("match (a),(b) where id(a)= $fromNodeId and id(b)= $toNodeId merge (a)-[:`:#{literal(#relation)}`]->(b)") + void createRelationShip(@Param("fromNodeId") Long fromNodeId, @Param("toNodeId") Long toNodeId, @Param("relation") String relation); + + + @Query("match (a),(b) where a.name = $fromNodeName and b.name= $toNodeName merge (a)-[:`:#{literal(#relation)}`]->(b)") + void createRelationShip(@Param("fromNodeName") String fromNodeName, @Param("toNodeName") String toNodeName, @Param("relation") String relation); + +} \ No newline at end of file diff --git a/src/main/java/com/supervision/neo4j/service/Neo4jService.java b/src/main/java/com/supervision/neo4j/service/Neo4jService.java new file mode 100644 index 0000000..7306722 --- /dev/null +++ b/src/main/java/com/supervision/neo4j/service/Neo4jService.java @@ -0,0 +1,31 @@ +package com.supervision.neo4j.service; + +import com.supervision.common.domain.R; +import com.supervision.neo4j.domain.CaseNode; +import com.supervision.neo4j.domain.Rel; + +import java.util.List; + +/** + * @author qmy + * @since 2023-10-26 + */ +public interface Neo4jService { + + R save(CaseNode caseNode); + + R delNode(Long id); + + CaseNode findById(Long id); + + List findByName(String caseId, String recordId, String nodeType, String name, String picType); + CaseNode findOneByName(String caseId, String recordId, String nodeType, String name, String picType); + + Rel findRelation(Rel rel); + + R saveRelation(Rel rel); + + R getNode(String picType, String caseId); + + R test(); +} diff --git a/src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java b/src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java new file mode 100644 index 0000000..68da9d5 --- /dev/null +++ b/src/main/java/com/supervision/neo4j/service/impl/Neo4jServiceImpl.java @@ -0,0 +1,283 @@ +package com.supervision.neo4j.service.impl; + +import com.supervision.common.domain.R; +import com.supervision.common.utils.StringUtils; +import com.supervision.neo4j.domain.CaseNode; +import com.supervision.neo4j.domain.Rel; +import com.supervision.neo4j.service.Neo4jService; +import com.supervision.neo4j.utils.Neo4jUtils; +import org.neo4j.driver.*; +import org.neo4j.driver.Record; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author qmy + * @since 2023-10-26 + */ +@Service +public class Neo4jServiceImpl implements Neo4jService { + + private final Driver driver; + @Autowired + private Neo4jServiceImpl(Driver driver) { + this.driver = driver; + } + + @Override + public R save(CaseNode caseNode) { + if (StringUtils.isEmpty(caseNode.getName()) || StringUtils.isEmpty(caseNode.getNodeType())) { + return R.fail("未传节点名称或节点类型或图谱类型!"); + } + List byName = findByName(caseNode.getCaseId(), caseNode.getRecordsId(), caseNode.getNodeType(), caseNode.getName(), caseNode.getPicType()); + if (byName != null && !byName.isEmpty()) { + return R.fail("名称已存在"); + } + CaseNode res = null; + try { + Session session = driver.session(); + StringBuffer cql = new StringBuffer(); + Map params = new HashMap<>(); + cql.append("CREATE (n:").append(caseNode.getNodeType()).append("{name:$name"); + params.put("name", caseNode.getName()); + if (StringUtils.isNotEmpty(caseNode.getRecordId())) { + cql.append(", recordId:$recordId"); + params.put("recordId", caseNode.getRecordId()); + } + if (StringUtils.isNotEmpty(caseNode.getRecordsId())) { + cql.append(", recordsId:$recordsId"); + params.put("recordsId", caseNode.getRecordsId()); + } + if (StringUtils.isNotEmpty(caseNode.getCaseId())) { + cql.append(", caseId:$caseId"); + params.put("caseId", caseNode.getCaseId()); + } + if (StringUtils.isNotEmpty(caseNode.getPicType())) { + cql.append(", picType:$picType"); + params.put("picType", caseNode.getPicType()); + } + cql.append("})").append(Neo4jUtils.NODE_RETURN); + Result run = session.run(cql.toString(), params); + res = Neo4jUtils.getOneNode(run); + } catch (Exception e) { + e.printStackTrace(); + } + return R.ok(res); + } + + @Override + public R delNode(Long id) { + try { + Session session = driver.session(); + StringBuffer cql = new StringBuffer(); + cql.append("MATCH (n) where id(n) = ").append(id).append(" DELETE n"); + Result run = session.run(cql.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + return R.ok(); + } + + @Override + public CaseNode findById(Long id) { + CaseNode node = null; + try { + Session session = driver.session(); + StringBuffer cql = new StringBuffer(); + cql.append("MATCH (n) where id(n) = ").append(id).append(Neo4jUtils.NODE_RETURN); + Result run = session.run(cql.toString()); + node = Neo4jUtils.getOneNode(run); + } catch (Exception e) { + e.printStackTrace(); + } + return node; + } + + @Override + public List findByName(String caseId, String recordsId, String nodeType, String name, String picType) { + List list = new ArrayList<>(); + try { + Session session = driver.session(); + StringBuffer cql = new StringBuffer(); + cql.append("MATCH (n"); + if (StringUtils.isNotEmpty(nodeType)) { + cql.append(":"); + cql.append(nodeType); + } + cql.append(") where 1 = 1"); + if (StringUtils.isNotEmpty(caseId)) { + cql.append(" and n.caseId = "); + cql.append(caseId); + } + if (StringUtils.isNotEmpty(recordsId)) { + cql.append(" and n.recordsId = "); + cql.append(recordsId); + } + if (StringUtils.isNotEmpty(name)) { + cql.append(" and n.name = '"); + cql.append(name); + cql.append("'"); + } + if (StringUtils.isNotEmpty(picType)) { + cql.append(" and n.picType = "); + cql.append(picType); + } + cql.append(Neo4jUtils.NODE_RETURN); + Result run = session.run(cql.toString()); + list = Neo4jUtils.getNodeList(run); + } catch (Exception e) { + e.printStackTrace(); + } + return list; + } + + @Override + public CaseNode findOneByName(String caseId, String recordsId, String nodeType, String name, String picType) { + CaseNode node = null; + try { + Session session = driver.session(); + StringBuffer cql = new StringBuffer(); + Map params = new HashMap<>(); + cql.append("MATCH (n"); + if (StringUtils.isNotEmpty(nodeType)) { + cql.append(":"); + cql.append(nodeType); + } + cql.append(") where 1 = 1"); + if (StringUtils.isNotEmpty(caseId)) { + cql.append(" and n.caseId = $caseId"); + params.put("caseId", caseId); + } + if (StringUtils.isNotEmpty(recordsId)) { + cql.append(" and n.recordsId = $recordsId"); + params.put("recordsId", recordsId); + } + if (StringUtils.isNotEmpty(name)) { + cql.append(" and n.name = $name"); + params.put("name", name); + } + if (StringUtils.isNotEmpty(picType)) { + cql.append(" and n.picType = $picType"); + params.put("picType", picType); + } + cql.append(Neo4jUtils.NODE_RETURN); + Result run = session.run(cql.toString(), params); + node = Neo4jUtils.getOneNode(run); + } catch (Exception e) { + e.printStackTrace(); + } + return node; + } + + @Override + public Rel findRelation(Rel rel) { + try { + Session session = driver.session(); + StringBuffer cql = new StringBuffer(); + Map params = new HashMap<>(); + cql.append("MATCH (a)-[rel:").append(rel.getName()).append("]->(b) where id(a) = $sourceId and id(b) = $targetId") + .append(Neo4jUtils.REL_RETURN); + params.put("sourceId", rel.getSourceId()); + params.put("targetId", rel.getTargetId()); + + Result run = session.run(cql.toString(), params); + rel = Neo4jUtils.getOneRel(run); + } catch (Exception e) { + e.printStackTrace(); + } + if (rel != null && rel.getId() != null) { + return rel; + } else { + return null; + } + } + + @Override + public R saveRelation(Rel rel) { + Rel res = null; + try { + Session session = driver.session(); + StringBuffer cql = new StringBuffer(); + Map params = new HashMap<>(); + cql.append("MATCH (a), (b) where id(a) = $sourceId and id(b) = $targetId CREATE(a)-[rel:").append(rel.getName()) + .append("]->(b) ").append(Neo4jUtils.REL_RETURN); + params.put("sourceId", rel.getSourceId()); + params.put("targetId", rel.getTargetId()); + + Result run = session.run(cql.toString(), params); + rel = Neo4jUtils.getOneRel(run); + } catch (Exception e) { + e.printStackTrace(); + } + if (rel != null) { + return R.ok(rel); + } else { + return R.fail("保存失败"); + } + } + + @Override + public R getNode(String picType, String caseId) { + Map map = new HashMap<>(); + List list = new ArrayList<>(); + List> nodes = new ArrayList<>(); + try { + Session session = driver.session(); + Map params = new HashMap<>(); + params.put("picType", picType); + params.put("caseId", caseId); + Result run = session.run("MATCH (n)-[rel]->(r) where n.picType = r.picType = $picType and n.caseId = r.caseId = $caseId" + + " RETURN id(rel) as id, n.name as source, id(n) as sourceId, type(rel) as name, r.name as target, id(r) as targetId", params); + while (run.hasNext()) { + Record record = run.next(); + long id = record.get("id").asLong(); + String source = record.get("source").asString(); + long sourceId = record.get("sourceId").asLong(); + String name = record.get("name").asString(); + String target = record.get("target").asString(); + long targetId = record.get("targetId").asLong(); + list.add(new Rel(id, source, sourceId, name, target, targetId)); + } + Result node = session.run("MATCH (n) where n.picType = $picType and n.caseId = $caseId RETURN id(n) as id, n.name as name", params); + while (node.hasNext()) { + Record record = node.next(); + String name = record.get("name").asString(); + long idlong = record.get("id").asLong(); + Map nodeMap = new HashMap<>(); + nodeMap.put("name", name); + nodeMap.put("entityName", name); +// nodeMap.put("id", idlong + ""); + nodes.add(nodeMap); + } + } catch (Exception e) { + e.printStackTrace(); + } + map.put("list", list); + map.put("nodes", nodes); + return R.ok(map); + } + + @Override + public R test() { + Session session = driver.session(); + Map params = new HashMap<>(); + params.put("lawActor", "行为人"); + params.put("lawParty", "aaaaaa"); + Result run = session.run("MATCH (m:LawActor), (n:FictionalOrgan) where m.name=$lawActor OPTIONAL MATCH (m)-[r:`冒充`]->(n) RETURN id(m) as startId, id(n) as endId, id(r) as relId, m.recordId as recordId, m.recordsId as recordsId", params); + while (run.hasNext()) { + Record record = run.next(); + String id = record.get("startId").asLong() + ""; + String endId = record.get("endId").asLong() + ""; + String relId = record.get("relId").asLong() + ""; + System.out.println("************" + id); + System.out.println("************" + endId); + System.out.println("************" + relId); + } + return R.ok("222"); + } +} diff --git a/src/main/java/com/supervision/neo4j/utils/Neo4jUtils.java b/src/main/java/com/supervision/neo4j/utils/Neo4jUtils.java new file mode 100644 index 0000000..556704f --- /dev/null +++ b/src/main/java/com/supervision/neo4j/utils/Neo4jUtils.java @@ -0,0 +1,91 @@ +package com.supervision.neo4j.utils; + +import com.supervision.neo4j.domain.CaseNode; +import com.supervision.neo4j.domain.Rel; +import com.supervision.neo4j.dto.ResultDTO; +import org.neo4j.driver.Record; +import org.neo4j.driver.Result; + +import java.util.ArrayList; +import java.util.List; + +public class Neo4jUtils { + + public static final String NODE_RETURN = " RETURN id(n) as id, n.name as name, n.nodeType as nodeType, n.recordId as recordId, n.caseId as caseId, n.picType as picType"; + public static final String REL_RETURN = " RETURN id(rel) as id, a.name as source, id(a) as sourceId, type(rel) as name, b.name as target, id(b) as targetId"; + + public static CaseNode getOneNode(Result run) { + CaseNode node = null; + if (run.hasNext()) { + Record record = run.next(); + long id = record.get("id").asLong(); + String name = record.get("name").asString(); + String nodeType = record.get("nodeType").asString(); + String recordId = record.get("recordId").asString(); + String caseId = record.get("caseId").asString(); + String picType = record.get("picType").asString(); + node = new CaseNode(id, name, nodeType, recordId, caseId, picType); + } + return node; + } + + public static List getNodeList(Result run) { + List list = new ArrayList<>(); + while (run.hasNext()) { + Record record = run.next(); + long id = record.get("id").asLong(); + String name = record.get("name").asString(); + String nodeType = record.get("nodeType").asString(); + String recordId = record.get("recordId").asString(); + String caseId = record.get("caseId").asString(); + String picType = record.get("picType").asString(); + list.add(new CaseNode(id, name, nodeType, recordId, caseId, picType)); + } + return list; + } + + public static Rel getOneRel(Result run) { + Rel rel = null; + if (run.hasNext()) { + Record record = run.next(); + long id = record.get("id").asLong(); + String source = record.get("source").asString(); + Long sourceId = record.get("sourceId").asLong(); + String name = record.get("name").asString(); + String target = record.get("target").asString(); + Long targetId = record.get("targetId").asLong(); + rel = new Rel(id, source, sourceId, name, target, targetId); + } + return rel; + } + + public static List getRelList(Result run) { + List list = new ArrayList<>(); + while (run.hasNext()) { + Record record = run.next(); + long id = record.get("id").asLong(); + String source = record.get("source").asString(); + Long sourceId = record.get("sourceId").asLong(); + String name = record.get("name").asString(); + String target = record.get("target").asString(); + Long targetId = record.get("targetId").asLong(); + list.add(new Rel(id, source, sourceId, name, target, targetId)); + } + return list; + } + + public static List getResultDTOList(Result run) { + List list = new ArrayList<>(); + while (run.hasNext()) { + Record record = run.next(); + String startId = record.get("startId").asLong() + ""; + String endId = record.get("endId").asLong() + ""; + String relId = record.get("relId").asLong() + ""; + String recordId = record.get("recordId").asString(); + String recordsId = record.get("recordsId").asString(); + list.add(new ResultDTO(startId, endId, relId, recordId, recordsId)); + } + return list; + } + +} diff --git a/src/main/java/com/supervision/police/controller/ComDictionaryController.java b/src/main/java/com/supervision/police/controller/ComDictionaryController.java new file mode 100644 index 0000000..8c060b3 --- /dev/null +++ b/src/main/java/com/supervision/police/controller/ComDictionaryController.java @@ -0,0 +1,61 @@ +package com.supervision.police.controller; + +import com.supervision.common.domain.R; +import com.supervision.police.domain.ComDictionary; +import com.supervision.police.dto.DictionaryByTypeParam; +import com.supervision.police.service.ComDictionaryService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 前端控制器 + *

+ * + * @author baomidou + * @since 2022-03-16 + */ +@RestController +@RequestMapping("/comDictionary") +@Api(tags = "字典表接口") +public class ComDictionaryController { + + @Autowired + private ComDictionaryService dictionaryService; + + @GetMapping + @ApiOperation(value = "查询字典", httpMethod = "GET") + public R findDictionary(ComDictionary dictionary, + @RequestParam(required = false, defaultValue = "1") Long page, + @RequestParam(required = false, defaultValue = "10") Long size) { + return dictionaryService.findDictionaryInfo(dictionary, page, size); + } + + @PostMapping("/queryByType") + @ApiOperation(value = "通过type查询字典,可一次性查询多个", httpMethod = "POST") + public R findDictionaryListByType(@RequestBody @Validated DictionaryByTypeParam dictionaryByTypeParam) { + return dictionaryService.findDictionaryListByType(dictionaryByTypeParam); + } + + @PostMapping + @ApiOperation(value = "新增字典", httpMethod = "POST") + public R insertDictionary(@RequestBody @Validated ComDictionary dictionary) { + return dictionaryService.insertDictionary(dictionary); + } + + @PostMapping("/update") + @ApiOperation(value = "修改字典", httpMethod = "POST") + public R updateDictionary(@RequestBody ComDictionary dictionary) { + return dictionaryService.updateDictionary(dictionary); + } + + @PostMapping("/deleteByStatus/delete") + @ApiOperation(value = "逻辑删除字典", httpMethod = "POST") + public R logicDeleteDictionary(@RequestParam Long id){ + return dictionaryService.logicDeleteDictionary(id); + } + +} diff --git a/src/main/java/com/supervision/police/controller/ModelCaseController.java b/src/main/java/com/supervision/police/controller/ModelCaseController.java new file mode 100644 index 0000000..6247979 --- /dev/null +++ b/src/main/java/com/supervision/police/controller/ModelCaseController.java @@ -0,0 +1,107 @@ +package com.supervision.police.controller; + +import com.supervision.common.domain.R; +import com.supervision.police.domain.CasePerson; +import com.supervision.police.domain.ModelCase; +import com.supervision.police.service.ModelCaseService; +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@Slf4j +@RequestMapping("modelCase") +public class ModelCaseController { + + @Autowired + private ModelCaseService modelCaseService; + + /** + * 查询列表 + * @param modelCase + * @param page + * @param size + * @return + */ + @PostMapping("/queryList") + public R queryList(@RequestBody ModelCase modelCase, + @RequestParam(required = false, defaultValue = "1") Integer page, + @RequestParam(required = false, defaultValue = "20") Integer size) { + return modelCaseService.queryList(modelCase, page, size); + } + + /** + * 检查案件编号是否已存在 + * @param caseNo + * @return + */ + @GetMapping("/checkCaseNo") + public R checkCaseNo(@RequestParam String caseNo) { + return modelCaseService.checkCaseNo(caseNo); + } + + /** + * 新增或修改 + * @param modelCase + * @return + */ + @PostMapping("/addOrUpd") + public R addOrUpd(@RequestBody ModelCase modelCase) { + return modelCaseService.addOrUpd(modelCase); + } + + /** + * 删除 + * @param id + * @return + */ + @PostMapping("/del") + public R del(@RequestParam String id) { + return modelCaseService.del(id); + } + + /** + * 查询案件任务 + * @param name + * @return + */ + @GetMapping("/getPerson") + @Operation(summary = "getPersion") + public R getPerson(@RequestParam String caseId, + @RequestParam(required = false, defaultValue = "") String name) { + return modelCaseService.getPerson(caseId, name); + } + + @PostMapping("/addPerson") + public R addPerson(@RequestBody CasePerson person) { + return modelCaseService.addPersion(person); + } + + /** + * 导入案件信息 + * @param file + * @return + */ + @PostMapping("/uploadCase") + public R uploadCase(@RequestPart MultipartFile file) { + return modelCaseService.uploadCase(file); + } + + /** + * 获取指标结果 + * @param caseId + * @param indexType + * @return + */ + @PostMapping("/getIndexDetail") + public R getIndexDetail(@RequestParam String caseId, + @RequestParam String indexType, + @RequestParam(required = false, defaultValue = "1") Integer page, + @RequestParam(required = false, defaultValue = "20") Integer size) { + return modelCaseService.getIndexDetail(caseId, indexType, page, size); + } + +} diff --git a/src/main/java/com/supervision/police/controller/ModelController.java b/src/main/java/com/supervision/police/controller/ModelController.java new file mode 100644 index 0000000..38c85b8 --- /dev/null +++ b/src/main/java/com/supervision/police/controller/ModelController.java @@ -0,0 +1,26 @@ +package com.supervision.police.controller; + +import com.supervision.common.domain.R; +import com.supervision.police.dto.AnalyseCaseDTO; +import com.supervision.police.service.ModelService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("model") +public class ModelController { + + @Autowired + private ModelService modelService; + + /** + * 分析指标 + * @param analyseCaseDTO + * @return + */ + @PostMapping("/analyseCase") + public R analyseCase(@RequestBody AnalyseCaseDTO analyseCaseDTO) { + return modelService.analyseCase(analyseCaseDTO); + } + +} diff --git a/src/main/java/com/supervision/police/controller/ModelIndexController.java b/src/main/java/com/supervision/police/controller/ModelIndexController.java new file mode 100644 index 0000000..8014714 --- /dev/null +++ b/src/main/java/com/supervision/police/controller/ModelIndexController.java @@ -0,0 +1,102 @@ +package com.supervision.police.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.supervision.common.domain.R; +import com.supervision.police.domain.ModelAtomicIndex; +import com.supervision.police.domain.ModelIndex; +import com.supervision.police.service.ModelIndexService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 指标表(ModelIndex)表控制层 + * + * @author qmy + * @since 2024-07-05 09:20:10 + */ +@RestController +@RequestMapping("modelIndex") +public class ModelIndexController { + + @Autowired + private ModelIndexService modelIndexService; + + /** + * 分页查询所有数据 + * + * @param page 分页对象 + * @param modelIndex 查询实体 + * @return 所有数据 + */ + @PostMapping("/selectAll") + public R selectAll(@RequestBody ModelIndex modelIndex, + @RequestParam(required = false, defaultValue = "1") Integer page, + @RequestParam(required = false, defaultValue = "20") Integer size) { + return modelIndexService.selectAll(modelIndex, page, size); + } + + /** + * 新增/修改数据 + * + * @param modelIndex 实体对象 + * @return 新增结果 + */ + @PostMapping("/addOrUpd") + public R addOrUpd(@RequestBody ModelIndex modelIndex) { + return modelIndexService.addOrUpd(modelIndex); + } + + /** + * 删除数据 + * + * @param id 主键 + * @return 删除结果 + */ + @PostMapping("/del") + public R del(@RequestParam String id) { + return modelIndexService.del(id); + } + + /*****************************原子指标**************/ + + /** + * 分页查询所有数据 + * + * @param page 分页对象 + * @param modelAtomicIndex 查询实体 + * @return 所有数据 + */ + @PostMapping("/selectAllAtomic") + public R selectAllAtomic(@RequestBody ModelAtomicIndex modelAtomicIndex, + @RequestParam(required = false, defaultValue = "1") Integer page, + @RequestParam(required = false, defaultValue = "20") Integer size) { + return modelIndexService.selectAllAtomic(modelAtomicIndex, page, size); + } + + /** + * 新增/修改数据 + * + * @param modelAtomicIndex 实体对象 + * @return 新增结果 + */ + @PostMapping("/addOrUpdAtomic") + public R addOrUpdAtomic(@RequestBody ModelAtomicIndex modelAtomicIndex) { + return modelIndexService.addOrUpdAtomic(modelAtomicIndex); + } + + /** + * 删除数据 + * + * @param id 主键 + * @return 删除结果 + */ + @PostMapping("/delAtomic") + public R delAtomic(@RequestParam String id) { + return modelIndexService.delAtomic(id); + } + +} + diff --git a/src/main/java/com/supervision/police/controller/RecordController.java b/src/main/java/com/supervision/police/controller/RecordController.java new file mode 100644 index 0000000..2640562 --- /dev/null +++ b/src/main/java/com/supervision/police/controller/RecordController.java @@ -0,0 +1,122 @@ +package com.supervision.police.controller; + +import com.supervision.common.domain.R; +import com.supervision.police.domain.NotePrompt; +import com.supervision.police.domain.NoteRecords; +import com.supervision.police.dto.ListDTO; +import com.supervision.police.service.ModelRecordTypeService; +import com.supervision.police.service.RecordService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +@RestController +@Slf4j +@RequestMapping("record") +public class RecordController { + + @Autowired + public ModelRecordTypeService modelRecordTypeService; + + @Autowired + public RecordService recordService; + + /** + * 查询笔录类型 + * @param name + * @param page + * @param size + * @return + */ + @GetMapping("queryType") + public R queryType(@RequestParam(required = false) String name, + @RequestParam(required = false, defaultValue = "1") Integer page, + @RequestParam(required = false, defaultValue = "20") Integer size) { + return modelRecordTypeService.queryType(name, page, size); + } + +// @PostMapping("saveType") +// public R saveType(@RequestBody ModelRecordType type) { +// return modelRecordTypeService.saveType(type); +// } + + /** + * 保存提示词 + * @param prompt + * @return + */ + @PostMapping("/addOrUpdPrompt") + public R addOrUpdPrompt(@RequestBody NotePrompt prompt) { + return modelRecordTypeService.addOrUpdPrompt(prompt); + } + + /** + * 删除提示词 + * @param prompt + * @return + */ + @PostMapping("/delPrompt") + public R delPrompt(@RequestBody NotePrompt prompt) { + return modelRecordTypeService.delPrompt(prompt); + } + + /** + * 获取案件三元组信息 + * @param caseId + * @param name + * @param recordId + * @return + */ + @GetMapping("/getThreeInfo") + public R getThreeInfo(@RequestParam String caseId, + @RequestParam String name, + @RequestParam(required = false) String recordId) { + return modelRecordTypeService.getThreeInfo(caseId, name, recordId); + } + + @PostMapping("/addNeo4j") + public R addNeo4j(@RequestBody ListDTO list) { + return modelRecordTypeService.addNeo4j(list.getIds()); + } + + /** + * 上传笔录, 修改 + * @param records + * @return + */ + @PostMapping("/addOrUpdRecords") + public R uploadRecords(NoteRecords records, + @RequestPart("file") List fileList) throws IOException { + return recordService.uploadRecords(records, fileList); + } + + /** + * 查询笔录,按姓名为父目录 + * @param noteRecords + * @param page + * @param size + * @return + */ + @PostMapping("/queryRecords") + public R queryRecords(@RequestBody NoteRecords noteRecords, + @RequestParam(required = false, defaultValue = "1") Integer page, + @RequestParam(required = false, defaultValue = "20") Integer size) { + return recordService.queryRecords(noteRecords, page, size); + } + + /** + * 删除 + * @param id + * @return + */ + @PostMapping("/delRecords") + public R delRecords(@RequestParam String id) { + return recordService.delRecords(id); + } + + +} diff --git a/src/main/java/com/supervision/police/domain/CasePerson.java b/src/main/java/com/supervision/police/domain/CasePerson.java new file mode 100644 index 0000000..768d67f --- /dev/null +++ b/src/main/java/com/supervision/police/domain/CasePerson.java @@ -0,0 +1,49 @@ +package com.supervision.police.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.io.Serializable; + +/** + * 案件人物表(CasePerson)表实体类 + * + * @author qmy + * @since 2024-07-06 13:27:29 + */ +@Data +@TableName("case_person") +public class CasePerson implements Serializable { + + @TableId + private String id; + + /** + * 案件id + */ + private String caseId; + + /** + * 姓名 + */ + private String name; + + /** + * 身份证号 + */ + private String idCard; + + /** + * 角色 + */ + private String roleCode; + + /** + * 角色名称 + */ + @TableField(exist=false) + private String roleName; + +} + diff --git a/src/main/java/com/supervision/police/domain/ComDictionary.java b/src/main/java/com/supervision/police/domain/ComDictionary.java new file mode 100644 index 0000000..d639642 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/ComDictionary.java @@ -0,0 +1,90 @@ +package com.supervision.police.domain; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + *

+ * + *

+ * + * @author baomidou + * @since 2022-03-16 + */ +@TableName("com_dictionary") +@Data +public class ComDictionary implements Serializable { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * code + */ + @TableField(value = "code") + private String value; + + /** + * 名称 + */ + @TableField(value = "name") + private String label; + + /** + * 父id + */ + private Long pid; + + /** + * 类型 + */ + private String type; + + /** + * 状态0:不可用,1:可用 + */ + private String status; + + /** + * + */ + private String dataStatus; + + /** + * 备注 + */ + private String note; + + /** + * 创建人 + */ + private String creator; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateTime; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * 更新人 + */ + private String updater; + + @TableField(exist = false) + private List child; + +} diff --git a/src/main/java/com/supervision/police/domain/ModelAtomicIndex.java b/src/main/java/com/supervision/police/domain/ModelAtomicIndex.java new file mode 100644 index 0000000..5c7b193 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/ModelAtomicIndex.java @@ -0,0 +1,103 @@ +package com.supervision.police.domain; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import java.io.Serializable; + +/** + * 原子指标表(ModelAtomicIndex)表实体类 + * + * @author qmy + * @since 2024-07-05 10:23:11 + */ +@Data +@TableName("model_atomic_index") +public class ModelAtomicIndex implements Serializable { + + @TableId + private String id; + + /** + * 指标名称 + */ + private String name; + + /** + * 指标说明 + */ + private String remark; + + /** + * 案件类型 + */ + private String caseType; + @TableField(exist = false) + public String caseTypeName; + + /** + * 指标来源 + */ + private String indexSource; + @TableField(exist = false) + public String indexSourceName; + + /** + * 状态 + */ + private String connectStatus; + + /** + * 判断结果 + */ + private String judgeResult; + + /** + * 查询语句 + */ + private String queryLang; + + /** + * 笔录类型 + */ + private String recordType; + @TableField(exist = false) + public String recordTypeName; + + /** + * 提示词 + */ + private String prompt; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateTime; + @TableField(exist = false) + @JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8") + private Date updateStartTime; + @TableField(exist = false) + @JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8") + private Date updateEndTime; + + /** + * 数据状态 + */ + private String dataStatus; + +} + diff --git a/src/main/java/com/supervision/police/domain/ModelAtomicResult.java b/src/main/java/com/supervision/police/domain/ModelAtomicResult.java new file mode 100644 index 0000000..a452a0c --- /dev/null +++ b/src/main/java/com/supervision/police/domain/ModelAtomicResult.java @@ -0,0 +1,59 @@ +package com.supervision.police.domain; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import java.io.Serializable; + +/** + * 原子指标结果表(ModelAtomicResult)表实体类 + * + * @author qmy + * @since 2024-07-09 17:21:20 + */ +@Data +@TableName("model_atomic_result") +public class ModelAtomicResult implements Serializable { + + @TableId + private String id; + + /** + * 案件id + */ + private String caseId; + + /** + * 原子指标id + */ + private String atomicId; + + /** + * 原子指标结果 -1:未知, 0:不存在, 1存在 + */ + private String atomicResult; + + /** + * 笔录片段id + */ + private String recordId; + + /** + * 笔录id + */ + private String recordsId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + +} + diff --git a/src/main/java/com/supervision/police/domain/ModelCase.java b/src/main/java/com/supervision/police/domain/ModelCase.java new file mode 100644 index 0000000..b26ca3b --- /dev/null +++ b/src/main/java/com/supervision/police/domain/ModelCase.java @@ -0,0 +1,130 @@ +package com.supervision.police.domain; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import java.io.Serializable; + +/** + * 案件表(ModelCase)表实体类 + * + * @author qmy + * @since 2024-07-02 14:37:15 + */ +@Data +@TableName("model_case") +public class ModelCase implements Serializable { + + /** + * 主键 + */ + @TableId + private String id; + + /** + * 案件名称 + */ + private String caseName; + + /** + * 案件类型 + */ + private String caseType; + @TableField(exist=false) + private String caseTypeName; + + /** + * 案件状态 + */ + private String caseStatus; + @TableField(exist=false) + private String caseStatusName; + + /** + * 作案方式 + */ + private String crimeMode; + @TableField(exist=false) + private String crimeModeName; + + /** + * 案件概述 + */ + private String caseDetail; + + /** + * 立案时间 + */ + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date registerTime; + + /** + * 受理时间 + */ + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date acceptTime; + + /** + * 行为人 + */ + private String lawActor; + + /** + * 当事人 + */ + private String lawParty; + + /** + * 认定结果 + */ + private String identifyResult; + @TableField(exist=false) + private String identifyResultName; + + /** + * 综合得分 + */ + private Integer totalScore; + + /** + * 排序序号 + */ + private Integer indexNum; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateTime; + @TableField(exist=false) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateStartTime; + @TableField(exist=false) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateEndTime; + + /** + * 数据状态 + */ + private String dataStatus; + + /** + * 案件编号 + */ + private String caseNo; + +} + diff --git a/src/main/java/com/supervision/police/domain/ModelIndex.java b/src/main/java/com/supervision/police/domain/ModelIndex.java new file mode 100644 index 0000000..e800ef1 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/ModelIndex.java @@ -0,0 +1,98 @@ +package com.supervision.police.domain; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import java.io.Serializable; +import java.util.List; + +/** + * 指标表(ModelIndex)表实体类 + * + * @author qmy + * @since 2024-07-05 09:20:10 + */ +@Data +@TableName("model_index") +public class ModelIndex implements Serializable { + + @TableId + private String id; + + /** + * 指标名称 + */ + private String name; + + /** + * 指标简称 + */ + private String shortName; + + /** + * 指标说明 + */ + private String remark; + + /** + * 指标类别 + */ + private String indexType; + @TableField(exist = false) + private String indexTypeName; + + /** + * 指标分数 + */ + private Integer indexScore; + + /** + * 原子指标数量 + */ + private Integer atomicIndexNum; + @TableField(exist = false) + private List atomicIndexList; + /** + * 案件类型 + */ + private String caseType; + @TableField(exist = false) + private String caseTypeName; + + /** + * 判断逻辑 + */ + private String judgeLogic; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateTime; + @TableField(exist = false) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateStartTime; + @TableField(exist = false) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateEndTime; + + /** + * 数据状态 + */ + private String dataStatus; + +} + diff --git a/src/main/java/com/supervision/police/domain/ModelIndexResult.java b/src/main/java/com/supervision/police/domain/ModelIndexResult.java new file mode 100644 index 0000000..44639d7 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/ModelIndexResult.java @@ -0,0 +1,54 @@ +package com.supervision.police.domain; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import java.io.Serializable; + +/** + * 指标结果表(ModelIndexResult)表实体类 + * + * @author qmy + * @since 2024-07-09 18:09:24 + */ +@Data +@TableName("model_index_result") +public class ModelIndexResult implements Serializable { + + @TableId + private String id; + + /** + * 案件id + */ + private String caseId; + + /** + * 指标id + */ + private String indexId; + + /** + * 指标结果 true/false + */ + private String indexResult; + + /** + * 原子指标ids + */ + private String atomicIds; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + +} + diff --git a/src/main/java/com/supervision/police/domain/ModelRecordType.java b/src/main/java/com/supervision/police/domain/ModelRecordType.java new file mode 100644 index 0000000..c8205c5 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/ModelRecordType.java @@ -0,0 +1,39 @@ +package com.supervision.police.domain; + + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@TableName(value = "model_record_type") +@Data +public class ModelRecordType implements Serializable { + + /** + * 主键ID + */ + @TableId + private String id; + + /** + * 笔录类型(总结) + */ + private String recordType; + + /** + * 提示词 + */ + @TableField(exist = false) + private List prompts; + + /** + * 笔录示例 + */ + @TableField(exist = false) + private List records; + +} diff --git a/src/main/java/com/supervision/police/domain/NotePrompt.java b/src/main/java/com/supervision/police/domain/NotePrompt.java new file mode 100644 index 0000000..398c315 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/NotePrompt.java @@ -0,0 +1,29 @@ +package com.supervision.police.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +@TableName(value = "note_prompt") +@Data +public class NotePrompt implements Serializable { + + /** + * 主键ID + */ + @TableId + private String id; + + /** + * 笔录类型id + */ + private String typeId; + + /** + * 提示词 + */ + private String prompt; + +} diff --git a/src/main/java/com/supervision/police/domain/NoteRecord.java b/src/main/java/com/supervision/police/domain/NoteRecord.java new file mode 100644 index 0000000..979ac4e --- /dev/null +++ b/src/main/java/com/supervision/police/domain/NoteRecord.java @@ -0,0 +1,71 @@ +package com.supervision.police.domain; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@TableName(value = "note_record") +@Data +public class NoteRecord implements Serializable { + + /** + * 主键ID + */ + @TableId + private String id; + + /** + * 案件id + */ + private String caseId; + + /** + * 人员名称 + */ + private String personName; + + /** + * 笔录名称 + */ + private String noteName; + + /** + * 问题 + */ + private String question; + + /** + * 回答 + */ + private String answer; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * 笔录类型(总结) + */ + private String recordType; + + /** + * 笔录类型id + */ + @TableField(exist = false) + private String recordTypeId; + + /** + * 完整笔录id + */ + private String noteRecordsId; + +} diff --git a/src/main/java/com/supervision/police/domain/NoteRecords.java b/src/main/java/com/supervision/police/domain/NoteRecords.java new file mode 100644 index 0000000..705ae86 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/NoteRecords.java @@ -0,0 +1,104 @@ +package com.supervision.police.domain; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +import java.io.Serializable; +import java.util.List; + +/** + * 完整笔录表(NoteRecords)表实体类 + * + * @author qmy + * @since 2024-07-05 08:53:20 + */ +@Data +@TableName("note_records") +public class NoteRecords implements Serializable { + + @TableId + private String id; + + /** + * 案件id + */ + private String caseId; + + /** + * 笔录名称 + */ + private String recordName; + + /** + * 笔录文件id + */ + private String fileIds; + + /** + * 姓名 + */ + private String name; + + /** + * 角色 + */ + private String role; + + /** + * 供述材料 + */ + private Integer confessionMaterial; + + /** + * 询问人 + */ + private String lawAsker; + + /** + * 供述开始时间 + */ +// @JsonFormat(pattern="yyyy-MM-dd HH:mm",timezone = "GMT+8") + private String confessionStartTime; + + /** + * 供述结束时间 + */ +// @JsonFormat(pattern="yyyy-MM-dd HH:mm",timezone = "GMT+8") + private String confessionEndTime; + + /** + * 排序序号 + */ + private Integer indexNum; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date updateTime; + + /** + * 数据状态 + */ + private String dataStatus; + + @TableField(exist = false) + private List children; + +} + diff --git a/src/main/java/com/supervision/police/domain/TripleInfo.java b/src/main/java/com/supervision/police/domain/TripleInfo.java new file mode 100644 index 0000000..2282c93 --- /dev/null +++ b/src/main/java/com/supervision/police/domain/TripleInfo.java @@ -0,0 +1,88 @@ +package com.supervision.police.domain; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@TableName(value = "triple_info") +@Data +public class TripleInfo implements Serializable { + + /** + * 主键ID + */ + @TableId + private String id; + + /** + * 开始节点 + */ + private String startNode; + + /** + * 结束节点 + */ + private String endNode; + + /** + * 关系 + */ + private String relation; + + /** + * 笔录片段id + */ + private String noteRecordId; + + @TableField(exist = false) + private String noteRecordsId; + + /** + * 案件id + */ + @TableField(exist = false) + private String caseId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private Date createTime; + + /** + * 是否生成图谱 + */ + private String addNeo4j; + + /** + * 开始节点类型(neo4j节点类型) + */ + private String startNodeType; + + /** + * 结束节点类型(neo4j节点类型) + */ + private String endNodeType; + + public TripleInfo() { + } + + // todo + public TripleInfo(String startNode, String endNode, String relation, String noteRecordId, Date createTime, String startNodeType, String endNodeType) { + this.startNode = startNode; + this.endNode = endNode; + this.relation = relation; + this.noteRecordId = noteRecordId; + this.createTime = createTime; + this.startNodeType = startNodeType; + this.endNodeType = endNodeType; + } + +} diff --git a/src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java b/src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java new file mode 100644 index 0000000..4d10207 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java @@ -0,0 +1,19 @@ +package com.supervision.police.dto; + +import com.supervision.police.domain.ModelAtomicIndex; +import lombok.Data; + +import java.util.List; + +@Data +public class AnalyseCaseDTO { + + private String caseId; + + private String lawActor; + + private String lawParty; + + List atomicIndexList; + +} diff --git a/src/main/java/com/supervision/police/dto/AtomicData.java b/src/main/java/com/supervision/police/dto/AtomicData.java new file mode 100644 index 0000000..b48a8e5 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/AtomicData.java @@ -0,0 +1,21 @@ +package com.supervision.police.dto; + +import lombok.Data; + +/** + * 原子指标逻辑 + */ +@Data +public class AtomicData { + + /** + * 原子指标id + */ + private String atomicIndex; + + /** + * 原子指标逻辑 + */ + private String relationalSymbol; + +} diff --git a/src/main/java/com/supervision/police/dto/AtomicIndexDTO.java b/src/main/java/com/supervision/police/dto/AtomicIndexDTO.java new file mode 100644 index 0000000..afdd698 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/AtomicIndexDTO.java @@ -0,0 +1,28 @@ +package com.supervision.police.dto; + +import lombok.Data; + +@Data +public class AtomicIndexDTO { + + /** + * 指标名称 + */ + private String indexName; + + /** + * 分值 + */ + private Integer score; + + /** + * 指标结果 + */ + private String indexResult; + + /** + * 笔录问答 + */ + private String record; + +} diff --git a/src/main/java/com/supervision/police/dto/DictionaryByTypeParam.java b/src/main/java/com/supervision/police/dto/DictionaryByTypeParam.java new file mode 100644 index 0000000..f1d489d --- /dev/null +++ b/src/main/java/com/supervision/police/dto/DictionaryByTypeParam.java @@ -0,0 +1,23 @@ +package com.supervision.police.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author qmy + * @program + * @description + * @createTime 2021/11/29 + */ +@Data +public class DictionaryByTypeParam implements Serializable { + + @ApiModelProperty(value = "根据type类型查询树列表") + public List list; + + @ApiModelProperty(value = "是否返回树形结构, 1返回, 0不返回, 默认为1") + public Integer isTree = 1; +} diff --git a/src/main/java/com/supervision/police/dto/IndexDetail.java b/src/main/java/com/supervision/police/dto/IndexDetail.java new file mode 100644 index 0000000..ca939c3 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/IndexDetail.java @@ -0,0 +1,40 @@ +package com.supervision.police.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class IndexDetail { + + /** + * 指标名称 + */ + private String indexName; + + /** + * 分值 + */ + private Integer score; + + /** + * 指标结果 + */ + private String indexResult; + + /** + * 笔录问答 + */ + private String record; + + /** + * 原子指标ids + */ + private String atomicIds; + + /** + * 原子指标 + */ + private List children; + +} diff --git a/src/main/java/com/supervision/police/dto/JudgeLogic.java b/src/main/java/com/supervision/police/dto/JudgeLogic.java new file mode 100644 index 0000000..ee6b67b --- /dev/null +++ b/src/main/java/com/supervision/police/dto/JudgeLogic.java @@ -0,0 +1,28 @@ +package com.supervision.police.dto; + +import lombok.Data; + +import java.util.List; + +/** + * 指标逻辑 + */ +@Data +public class JudgeLogic { + + /** + * 与上一组之间的逻辑关系 + */ + private String groupLogic; + + /** + * 组内逻辑关系 + */ + private String rowLogic; + + /** + * 组内原子指标列表 + */ + private List atomicData; + +} diff --git a/src/main/java/com/supervision/police/dto/KeyAndNameObject.java b/src/main/java/com/supervision/police/dto/KeyAndNameObject.java new file mode 100644 index 0000000..794efc2 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/KeyAndNameObject.java @@ -0,0 +1,12 @@ +package com.supervision.police.dto; + +import lombok.Data; + +@Data +public class KeyAndNameObject { + + private String code; + + private String name; + +} diff --git a/src/main/java/com/supervision/police/dto/ListDTO.java b/src/main/java/com/supervision/police/dto/ListDTO.java new file mode 100644 index 0000000..e8d74cb --- /dev/null +++ b/src/main/java/com/supervision/police/dto/ListDTO.java @@ -0,0 +1,12 @@ +package com.supervision.police.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class ListDTO { + + public List ids; + +} diff --git a/src/main/java/com/supervision/police/dto/SignParam.java b/src/main/java/com/supervision/police/dto/SignParam.java new file mode 100644 index 0000000..4193501 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/SignParam.java @@ -0,0 +1,32 @@ +package com.supervision.police.dto; + +import lombok.Data; + +/** + * @author qmy + * @since 2023-03-30 + */ +@Data +public class SignParam { + + private String year; + + private String system; + + private String signer; + + private String approvalNumber; + + private String issuelDate; + + public SignParam() { + } + + public SignParam(String year, String system, String signer, String approvalNumber, String issuelDate) { + this.year = year; + this.system = system; + this.signer = signer; + this.approvalNumber = approvalNumber; + this.issuelDate = issuelDate; + } +} diff --git a/src/main/java/com/supervision/police/mapper/CasePersonMapper.java b/src/main/java/com/supervision/police/mapper/CasePersonMapper.java new file mode 100644 index 0000000..04d66e8 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/CasePersonMapper.java @@ -0,0 +1,15 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.CasePerson; + +/** + * 案件人物表(CasePerson)表数据库访问层 + * + * @author qmy + * @since 2024-07-06 13:27:29 + */ +public interface CasePersonMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/supervision/police/mapper/ComDictionaryMapper.java b/src/main/java/com/supervision/police/mapper/ComDictionaryMapper.java new file mode 100644 index 0000000..5d8597b --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/ComDictionaryMapper.java @@ -0,0 +1,53 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.ComDictionary; +import com.supervision.police.dto.KeyAndNameObject; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + *

+ * 字典表 Mapper 接口 + *

+ * + * @author dw + * @since 2021-11-17 + */ +@Repository +public interface ComDictionaryMapper extends BaseMapper { + + List queryAllChildrenInfoForPid(@Param("pid") Long id); + + /** + * 更新所有id, pid为 所传参数 的数据状态为0 + * 逻辑删除 + * @param id 字典id + */ + Long updateDataStatusByIdAndPid(@Param("id") Long id); + + /** + * 根据type和code唯一确定一项 + * + * @return + */ + ComDictionary queryDicByTypeAndCode(@Param("code") String code, + @Param("type") String type); + + //根据type和name唯一确定一项 + ComDictionary queryByTypeAndName(@Param("type") String type, + @Param("name") String name); + + //根据type和name唯一确定一项 + String queryDicByTypeAndName(@Param("type") String type, + @Param("name") String name); + + /** + * 查询出字典所有分类 + */ + List queryAllType(); + + List queryIndustry(@Param("type") String type); +} diff --git a/src/main/java/com/supervision/police/mapper/ModelAtomicIndexMapper.java b/src/main/java/com/supervision/police/mapper/ModelAtomicIndexMapper.java new file mode 100644 index 0000000..c61cf4d --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/ModelAtomicIndexMapper.java @@ -0,0 +1,23 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.supervision.police.domain.ModelAtomicIndex; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 原子指标表(ModelAtomicIndex)表数据库访问层 + * + * @author qmy + * @since 2024-07-05 10:23:11 + */ +public interface ModelAtomicIndexMapper extends BaseMapper { + + IPage selectAll(IPage iPage, @Param("index") ModelAtomicIndex index); + + List selectByCaseType(@Param("caseType") String caseType); + +} + diff --git a/src/main/java/com/supervision/police/mapper/ModelAtomicResultMapper.java b/src/main/java/com/supervision/police/mapper/ModelAtomicResultMapper.java new file mode 100644 index 0000000..d0280e2 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/ModelAtomicResultMapper.java @@ -0,0 +1,19 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.ModelAtomicResult; +import org.apache.ibatis.annotations.Param; + +/** + * 原子指标结果表(ModelAtomicResult)表数据库访问层 + * + * @author qmy + * @since 2024-07-09 17:21:20 + */ +public interface ModelAtomicResultMapper extends BaseMapper { + + ModelAtomicResult selectByCaseIdAndAtomicId(@Param("caseId") String caseId, + @Param("atomicId") String atomicId); + +} + diff --git a/src/main/java/com/supervision/police/mapper/ModelCaseMapper.java b/src/main/java/com/supervision/police/mapper/ModelCaseMapper.java new file mode 100644 index 0000000..e0734eb --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/ModelCaseMapper.java @@ -0,0 +1,33 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.supervision.police.domain.ModelCase; +import com.supervision.police.domain.ModelRecordType; +import com.supervision.police.dto.AtomicIndexDTO; +import com.supervision.police.dto.IndexDetail; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 案件表(ModelCase)表数据库访问层 + * + * @author qmy + * @since 2024-07-02 14:47:59 + */ +public interface ModelCaseMapper extends BaseMapper { + + IPage selectAll(IPage iPage, ModelCase modelCase); + + int selectMaxIndex(); + + IPage getIndexDetail(IPage iPage, + @Param("caseId") String caseId, + @Param("indexType") String indexType); + + List getAtomicDetail(@Param("caseId") String caseId, + @Param("atomicIds") List atomicIds); + +} + diff --git a/src/main/java/com/supervision/police/mapper/ModelIndexMapper.java b/src/main/java/com/supervision/police/mapper/ModelIndexMapper.java new file mode 100644 index 0000000..71b9e03 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/ModelIndexMapper.java @@ -0,0 +1,20 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.ModelIndex; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 指标表(ModelIndex)表数据库访问层 + * + * @author qmy + * @since 2024-07-05 09:20:10 + */ +public interface ModelIndexMapper extends BaseMapper { + + List selectByCaseType(@Param("caseType") String caseType); + +} + diff --git a/src/main/java/com/supervision/police/mapper/ModelIndexResultMapper.java b/src/main/java/com/supervision/police/mapper/ModelIndexResultMapper.java new file mode 100644 index 0000000..7746172 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/ModelIndexResultMapper.java @@ -0,0 +1,19 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.ModelIndexResult; +import org.apache.ibatis.annotations.Param; + +/** + * 指标结果表(ModelIndexResult)表数据库访问层 + * + * @author qmy + * @since 2024-07-09 18:09:24 + */ +public interface ModelIndexResultMapper extends BaseMapper { + + ModelIndexResult selectByCaseIdAndIndexId(@Param("caseId") String caseId, + @Param("indexId") String indexId); + +} + diff --git a/src/main/java/com/supervision/police/mapper/ModelRecordTypeMapper.java b/src/main/java/com/supervision/police/mapper/ModelRecordTypeMapper.java new file mode 100644 index 0000000..bb0d174 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/ModelRecordTypeMapper.java @@ -0,0 +1,19 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.supervision.police.domain.ModelRecordType; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface ModelRecordTypeMapper extends BaseMapper { + + IPage selectByName(IPage iPage, @Param("name") String name); + List selectByName(@Param("name") String name); + + ModelRecordType queryByName(@Param("name") String name); + + List getAllType(); + +} diff --git a/src/main/java/com/supervision/police/mapper/NoteCheckRecordMapper.java b/src/main/java/com/supervision/police/mapper/NoteCheckRecordMapper.java new file mode 100644 index 0000000..c663cbe --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/NoteCheckRecordMapper.java @@ -0,0 +1,18 @@ +package com.supervision.police.mapper; + +import com.supervision.springaidemo.domain.NoteCheckRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author flevance +* @description 针对表【note_check_record(案件执行验证结果)】的数据库操作Mapper +* @createDate 2024-05-11 15:47:02 +* @Entity com.supervision.springaidemo.domain.NoteCheckRecord +*/ +public interface NoteCheckRecordMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/supervision/police/mapper/NotePromptMapper.java b/src/main/java/com/supervision/police/mapper/NotePromptMapper.java new file mode 100644 index 0000000..ad857fb --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/NotePromptMapper.java @@ -0,0 +1,13 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.NotePrompt; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface NotePromptMapper extends BaseMapper { + + List queryPrompt(@Param("typeId") String typeId); + +} diff --git a/src/main/java/com/supervision/police/mapper/NoteRecordMapper.java b/src/main/java/com/supervision/police/mapper/NoteRecordMapper.java new file mode 100644 index 0000000..fefb372 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/NoteRecordMapper.java @@ -0,0 +1,17 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.NoteRecord; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface NoteRecordMapper extends BaseMapper { + + List selectByRecordType(@Param("recordType") String recordType); + + List selectRecord(@Param("caseId") String caseId, + @Param("name") String name, + @Param("recordId") String recordId); + +} diff --git a/src/main/java/com/supervision/police/mapper/NoteRecordsMapper.java b/src/main/java/com/supervision/police/mapper/NoteRecordsMapper.java new file mode 100644 index 0000000..01234d7 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/NoteRecordsMapper.java @@ -0,0 +1,15 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.NoteRecords; + +/** + * 完整笔录表(NoteRecords)表数据库访问层 + * + * @author qmy + * @since 2024-07-05 08:53:20 + */ +public interface NoteRecordsMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/supervision/police/mapper/TripleInfoMapper.java b/src/main/java/com/supervision/police/mapper/TripleInfoMapper.java new file mode 100644 index 0000000..604d297 --- /dev/null +++ b/src/main/java/com/supervision/police/mapper/TripleInfoMapper.java @@ -0,0 +1,13 @@ +package com.supervision.police.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.supervision.police.domain.TripleInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface TripleInfoMapper extends BaseMapper { + + List selectByIds(@Param("ids") List ids); + +} diff --git a/src/main/java/com/supervision/police/service/ComDictionaryService.java b/src/main/java/com/supervision/police/service/ComDictionaryService.java new file mode 100644 index 0000000..22e1ae7 --- /dev/null +++ b/src/main/java/com/supervision/police/service/ComDictionaryService.java @@ -0,0 +1,33 @@ +package com.supervision.police.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.supervision.common.domain.R; +import com.supervision.police.domain.ComDictionary; +import com.supervision.police.dto.DictionaryByTypeParam; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author baomidou + * @since 2022-03-16 + */ +public interface ComDictionaryService extends IService { + + R findDictionaryInfo(ComDictionary dictionary, Long page, Long size); + + R findDictionaryListByType(DictionaryByTypeParam dictionaryByTypeParam); + + R insertDictionary(ComDictionary dictionary); + + R updateDictionary(ComDictionary dictionary); + + R logicDeleteDictionary(Long id); + + String getName(List list, String type, String value); + String getValue(List list, String type, String name); + +} diff --git a/src/main/java/com/supervision/police/service/ModelCaseService.java b/src/main/java/com/supervision/police/service/ModelCaseService.java new file mode 100644 index 0000000..9f5c194 --- /dev/null +++ b/src/main/java/com/supervision/police/service/ModelCaseService.java @@ -0,0 +1,34 @@ +package com.supervision.police.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.supervision.common.domain.R; +import com.supervision.police.domain.CasePerson; +import com.supervision.police.domain.ModelCase; +import org.springframework.web.multipart.MultipartFile; + +/** + * 案件表(ModelCase)表服务接口 + * + * @author makejava + * @since 2024-07-02 14:14:43 + */ +public interface ModelCaseService extends IService { + + R queryList(ModelCase modelCase, Integer page, Integer size); + + R checkCaseNo(String caseNo); + + R addOrUpd(ModelCase modelCase); + + R del(String id); + + R getPerson(String caseId, String name); + + R addPersion(CasePerson person); + + R uploadCase(MultipartFile file); + + R getIndexDetail(String caseId, String indexType, Integer page, Integer size); + +} + diff --git a/src/main/java/com/supervision/police/service/ModelIndexService.java b/src/main/java/com/supervision/police/service/ModelIndexService.java new file mode 100644 index 0000000..94dce4e --- /dev/null +++ b/src/main/java/com/supervision/police/service/ModelIndexService.java @@ -0,0 +1,29 @@ +package com.supervision.police.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.supervision.common.domain.R; +import com.supervision.police.domain.ModelAtomicIndex; +import com.supervision.police.domain.ModelIndex; + +/** + * 指标表(ModelIndex)表服务接口 + * + * @author qmy + * @since 2024-07-05 09:20:10 + */ +public interface ModelIndexService extends IService { + + R selectAll(ModelIndex modelIndex, Integer page, Integer size); + + R addOrUpd(ModelIndex modelIndex); + + R del(String id); + + R selectAllAtomic(ModelAtomicIndex modelAtomicIndex, Integer page, Integer size); + + R addOrUpdAtomic(ModelAtomicIndex modelAtomicIndex); + + R delAtomic(String id); + +} + diff --git a/src/main/java/com/supervision/police/service/ModelRecordTypeService.java b/src/main/java/com/supervision/police/service/ModelRecordTypeService.java new file mode 100644 index 0000000..ce7777d --- /dev/null +++ b/src/main/java/com/supervision/police/service/ModelRecordTypeService.java @@ -0,0 +1,25 @@ +package com.supervision.police.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.supervision.common.domain.R; +import com.supervision.police.domain.ModelRecordType; +import com.supervision.police.domain.NotePrompt; + +import java.util.List; + +public interface ModelRecordTypeService extends IService { + + R queryType(String name, Integer page, Integer size); + + ModelRecordType queryByName(String content); + + R saveType(ModelRecordType type); + + R addOrUpdPrompt(NotePrompt prompt); + + R delPrompt(NotePrompt prompt); + + R getThreeInfo(String caseId, String name, String recordId); + + R addNeo4j(List ids); +} diff --git a/src/main/java/com/supervision/police/service/ModelService.java b/src/main/java/com/supervision/police/service/ModelService.java new file mode 100644 index 0000000..74d7754 --- /dev/null +++ b/src/main/java/com/supervision/police/service/ModelService.java @@ -0,0 +1,10 @@ +package com.supervision.police.service; + +import com.supervision.common.domain.R; +import com.supervision.police.dto.AnalyseCaseDTO; + +public interface ModelService { + + R analyseCase(AnalyseCaseDTO analyseCaseDTO); + +} diff --git a/src/main/java/com/supervision/police/service/NoteCheckRecordService.java b/src/main/java/com/supervision/police/service/NoteCheckRecordService.java new file mode 100644 index 0000000..afe39e2 --- /dev/null +++ b/src/main/java/com/supervision/police/service/NoteCheckRecordService.java @@ -0,0 +1,13 @@ +package com.supervision.police.service; + +import com.supervision.springaidemo.domain.NoteCheckRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author flevance +* @description 针对表【note_check_record(案件执行验证结果)】的数据库操作Service +* @createDate 2024-05-11 15:47:02 +*/ +public interface NoteCheckRecordService extends IService { + +} diff --git a/src/main/java/com/supervision/police/service/RecordService.java b/src/main/java/com/supervision/police/service/RecordService.java new file mode 100644 index 0000000..a0fe5a9 --- /dev/null +++ b/src/main/java/com/supervision/police/service/RecordService.java @@ -0,0 +1,20 @@ +package com.supervision.police.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.supervision.common.domain.R; +import com.supervision.police.domain.NoteRecord; +import com.supervision.police.domain.NoteRecords; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +public interface RecordService extends IService { + + R uploadRecords(NoteRecords records, List fileList) throws IOException; + + R queryRecords(NoteRecords noteRecords, Integer page, Integer size); + + R delRecords(String id); + +} diff --git a/src/main/java/com/supervision/police/service/impl/ComDictionaryServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ComDictionaryServiceImpl.java new file mode 100644 index 0000000..fe38919 --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/ComDictionaryServiceImpl.java @@ -0,0 +1,192 @@ +package com.supervision.police.service.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.common.domain.R; +import com.supervision.common.utils.IPages; +import com.supervision.common.utils.StringUtils; +import com.supervision.police.domain.ComDictionary; +import com.supervision.police.dto.DictionaryByTypeParam; +import com.supervision.police.mapper.ComDictionaryMapper; +import com.supervision.police.service.ComDictionaryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 服务实现类 + *

+ * + * @author baomidou + * @since 2022-03-16 + */ +@Service +public class ComDictionaryServiceImpl extends ServiceImpl implements ComDictionaryService { + + @Autowired + private ComDictionaryMapper comDictionaryMapper; + + @Override + public R findDictionaryInfo(ComDictionary dictionary, Long page, Long size) { + LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery(); + lambdaQueryWrapper + .eq(dictionary.getId() != null, ComDictionary::getId, dictionary.getId()) + .eq(StringUtils.isNotBlank(dictionary.getValue()), ComDictionary::getValue, dictionary.getValue()) + .eq(StringUtils.isNotBlank(dictionary.getType()), ComDictionary::getType, dictionary.getType()) + .eq(dictionary.getPid() != null, ComDictionary::getPid, dictionary.getPid()) + .eq(ComDictionary::getDataStatus, "1") + .isNotNull(ComDictionary::getValue); + IPage iPage = new Page<>(page, size); + iPage = comDictionaryMapper.selectPage(iPage, lambdaQueryWrapper); + return R.ok(IPages.buildDataMap(iPage.getRecords(), iPage.getRecords().size())); + } + + /** + * 通过type查询字典 + * @param dictionaryByTypeParam + * @return + */ + @Override + public R findDictionaryListByType(DictionaryByTypeParam dictionaryByTypeParam) { + Map> resultMap = queryDictionary(dictionaryByTypeParam); + return R.ok(resultMap); + } + + /** + * 根据条件查询字典表,供内部调用. + * @param dictionaryByTypeParam + * @return + */ + private Map> queryDictionary(DictionaryByTypeParam dictionaryByTypeParam) { + Map> resultMap = new HashMap<>(); + List typeList = new ArrayList<>(); + if (dictionaryByTypeParam.getList() == null || dictionaryByTypeParam.getList().size() <=0) { + typeList = comDictionaryMapper.queryAllType(); + } else { + typeList = dictionaryByTypeParam.getList(); + } + for (String dictType : typeList) { + List queryList = new ArrayList<>(); + List otherList = new ArrayList<>(); + ComDictionary comDictionary = new ComDictionary(); + comDictionary.setType(dictType); + Wrapper wrapper = Wrappers.query(comDictionary); + queryList = this.comDictionaryMapper.selectList(wrapper); + changeTree(queryList,otherList); + if (otherList.size() > 1) { + if (dictionaryByTypeParam.getIsTree() != null && dictionaryByTypeParam.getIsTree() == 0) { + resultMap.put(dictType,queryList); + }else { + resultMap.put(dictType,otherList); + } + } else { + if (dictionaryByTypeParam.getIsTree() != null && dictionaryByTypeParam.getIsTree() == 0){ + resultMap.put(dictType,otherList.get(0).getChild()); + }else { + resultMap.put(dictType,otherList); + } + } + } + return resultMap; + } + + + @Override + public R insertDictionary(ComDictionary dictionary) { + comDictionaryMapper.insert(dictionary); + return R.okMsg("新增成功"); + } + + @Override + public R updateDictionary(ComDictionary dictionary) { + try{ + comDictionaryMapper.updateById(dictionary); + return R.okMsg("更新成功"); + }catch (Exception e) { + return R.fail("更新失败"); + } + } + + @Override + public R logicDeleteDictionary(Long id) { + if (comDictionaryMapper.updateDataStatusByIdAndPid(id) > 0) { + return R.okMsg("更新成功"); + } else { + return R.fail(700,"未找到该条数据的信息."); + } + } + + private void changeTree(List queryList, List resultList) { + // 先找到所有的一级菜单 + for (ComDictionary comDictionary : queryList) { + // 一级菜单没有parentId + if (comDictionary.getPid() == null || comDictionary.getPid() == 0l) { + resultList.add(comDictionary); + } + } + // 为一级菜单设置子菜单,getChild是递归调用的 + for (ComDictionary comDictionary : resultList) { + comDictionary.setPid(0L); + comDictionary.setChild(getChild(comDictionary.getId(), queryList)); + } + } + + /** + * 递归查找子菜单 + * + * + * @param id 当前菜单id + * @param dictionaryList 要查找的列表 + * @return + */ + private List getChild(Long id, List dictionaryList) { + // 子菜单 + List childList = new ArrayList<>(); + for (ComDictionary comDictionary : dictionaryList) { + if (comDictionary.getPid() != null && comDictionary.getPid().equals(id)) { + childList.add(comDictionary); + } + } + // 把子菜单的子菜单再循环一遍 + for (ComDictionary comDictionary : childList) { + // 直接递归 + comDictionary.setChild(getChild(comDictionary.getId(), dictionaryList)); + } // 递归退出条件 + if (childList.size() == 0) { + return null; + } + return childList; + } + + @Override + public String getName(List list, String type, String value) { + for (ComDictionary comDictionary : list) { + // 父级字典项的value是null + if (comDictionary.getType().equals(type) && comDictionary.getValue() != null + && comDictionary.getValue().equals(value)) { + return comDictionary.getLabel(); + } + } + return ""; + } + + @Override + public String getValue(List list, String type, String label) { + for (ComDictionary comDictionary : list) { + if (comDictionary.getType().equals(type) && comDictionary.getLabel().equals(label)) { + return comDictionary.getValue(); + } + } + return ""; + } + +} diff --git a/src/main/java/com/supervision/police/service/impl/ModelCaseServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ModelCaseServiceImpl.java new file mode 100644 index 0000000..24545a2 --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/ModelCaseServiceImpl.java @@ -0,0 +1,222 @@ +package com.supervision.police.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.common.domain.R; +import com.supervision.common.enums.ResultStatusEnum; +import com.supervision.common.exception.CustomException; +import com.supervision.common.utils.ExcelReader; +import com.supervision.common.utils.IPages; +import com.supervision.common.utils.StringUtils; +import com.supervision.police.domain.CasePerson; +import com.supervision.police.domain.ComDictionary; +import com.supervision.police.domain.ModelAtomicIndex; +import com.supervision.police.dto.AtomicIndexDTO; +import com.supervision.police.dto.IndexDetail; +import com.supervision.police.mapper.CasePersonMapper; +import com.supervision.police.mapper.ModelCaseMapper; +import com.supervision.police.domain.ModelCase; +import com.supervision.police.service.ComDictionaryService; +import com.supervision.police.service.ModelCaseService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import java.io.IOException; +import java.util.*; + +/** + * 案件表(ModelCase)表服务实现类 + * + * @author qmy + * @since 2024-07-02 14:51:27 + */ +@Service +public class ModelCaseServiceImpl extends ServiceImpl implements ModelCaseService { + + @Autowired + private ComDictionaryService comDictionaryService; + + @Autowired + private ModelCaseMapper modelCaseMapper; + + @Autowired + private CasePersonMapper casePersonMapper; + + /** + * 查询列表 + * @param modelCase + * @param page + * @param size + * @return + */ + @Override + public R queryList(ModelCase modelCase, Integer page, Integer size) { + IPage iPage = new Page<>(page, size); + iPage = modelCaseMapper.selectAll(iPage, modelCase); + List records = iPage.getRecords(); + List dicts = comDictionaryService.list(); + for (ModelCase mc : records) { + String[] caseTypes = mc.getCaseType().split(","); + List caseType = new ArrayList<>(); + for (String type : caseTypes) { + caseType.add(comDictionaryService.getName(dicts, "case_type", type)); + } + mc.setCaseTypeName(StringUtils.join(caseType, ",")); + mc.setCaseStatusName(comDictionaryService.getName(dicts, "case_status", mc.getCaseStatus())); + mc.setCrimeModeName(comDictionaryService.getName(dicts, "crime_mode", mc.getCrimeMode())); + mc.setIdentifyResultName(comDictionaryService.getName(dicts, "identify_result", mc.getIdentifyResult())); + } + iPage.setRecords(records); + return R.ok(IPages.buildDataMap(iPage)); + } + + @Override + public R checkCaseNo(String caseNo) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(ModelCase::getCaseNo, caseNo) + .eq(ModelCase::getDataStatus, "1"); + ModelCase modelCase = modelCaseMapper.selectOne(wrapper); + if (modelCase == null) { + return R.ok(caseNo); + } else { + return R.okMsg("案件编号已存在,请勿重复添加"); + } + } + + @Override + public R addOrUpd(ModelCase modelCase) { + int i = 0; + if (modelCase.getId() != null) { + i = modelCaseMapper.updateById(modelCase); + } else { + Long num = modelCaseMapper.selectCount(null); + modelCase.setIndexNum(Integer.parseInt(num.toString()) + 1); + i = modelCaseMapper.insert(modelCase); + } + if (i > 0) { + return R.okMsg("保存成功"); + } else { + return R.fail("保存失败"); + } + } + + @Override + public R del(String id) { + ModelCase modelCase = modelCaseMapper.selectById(id); + modelCase.setDataStatus(StringUtils.getUUID()); + int i = modelCaseMapper.updateById(modelCase); + if (i > 0) { + return R.okMsg("删除成功"); + } else { + return R.fail("删除失败"); + } + } + + @Override + public R getPerson(String caseId, String name) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.like(CasePerson::getCaseId, caseId) + .like(CasePerson::getName, name); + List casePeople = casePersonMapper.selectList(wrapper); + List dicts = comDictionaryService.list(); + for (CasePerson cp : casePeople) { + cp.setRoleName(comDictionaryService.getName(dicts, "case_role", cp.getRoleCode())); + } + return R.ok(casePeople); + } + + @Override + public R addPersion(CasePerson person) { + int i = casePersonMapper.insert(person); + if (i > 0) { + return R.okMsg("新增成功"); + } else { + return R.fail("新增失败"); + } + } + + @Override + public R uploadCase(MultipartFile file) { + /** + * 检查文件格式 + */ + String fileName = file.getOriginalFilename(); + assert fileName != null; + // 截取文件的类型符 + String substring = fileName.substring(fileName.lastIndexOf(".") + 1); + if (!("xls".equals(substring) || "xlsx".equals(substring))) { + throw new CustomException(ResultStatusEnum.INCORRECT_FILE_FORMAT);// 响应“文件格式不正确”异常 + } + List putList = new ArrayList<>(); + try { + putList = ExcelReader.getCaseList(file.getInputStream(), substring, null); + } catch (IOException e) { + e.printStackTrace(); + throw new CustomException(ResultStatusEnum.UPLOAD_EXCEPTION);// 响应“文件上传异常”错误 + } + List dicts = comDictionaryService.list(); + /** + * 读取bean列表,导入到数据库中 + */ + List> errorList = new ArrayList<>(); + int index = modelCaseMapper.selectMaxIndex() + 1; + int add = 0; + for (ModelCase modelCase : putList) { + if (StringUtils.isEmpty(modelCase.getCaseNo()) || StringUtils.isEmpty(modelCase.getCaseName()) + || StringUtils.isEmpty(modelCase.getCaseTypeName()) || StringUtils.isEmpty(modelCase.getCaseStatusName()) + || StringUtils.isEmpty(modelCase.getCrimeModeName())) { + errorList.add(errorMapBuilder(modelCase, "必填项为空")); + continue; + } + //替换字典项 + String[] split = modelCase.getCaseTypeName().split(","); + List caseTypes = new ArrayList<>(); + for (String type : split) { + caseTypes.add(comDictionaryService.getValue(dicts, "case_type", type)); + } + modelCase.setCaseType(StringUtils.join(caseTypes, ",")); + modelCase.setCaseStatus(comDictionaryService.getValue(dicts, "case_status", modelCase.getCaseStatusName())); + modelCase.setCrimeMode(comDictionaryService.getValue(dicts, "crime_mode", modelCase.getCrimeModeName())); + modelCase.setIndexNum(index); + modelCaseMapper.insert(modelCase); + add++; + index++; + } + Map returnMap = new HashMap<>(); + returnMap.put("errorList", errorList); + returnMap.put("add", add); + return R.ok(returnMap); + } + + private Map errorMapBuilder(ModelCase modelCase, String errorText) { + return new HashMap(2) {{ + put("caseNo", modelCase.getCaseNo()); + put("caseName", modelCase.getCaseName()); + put("errorText", errorText); + }}; + } + + @Override + public R getIndexDetail(String caseId, String indexType, Integer page, Integer size) { + IPage iPage = new Page<>(page, size); + iPage = modelCaseMapper.getIndexDetail(iPage, caseId, indexType); + List records = iPage.getRecords(); + for (IndexDetail record : records) { + String[] array = record.getAtomicIds().split(","); + List atomicIds = Arrays.asList(array); + List atomics = modelCaseMapper.getAtomicDetail(caseId, atomicIds); + record.setChildren(atomics); + } + iPage.setRecords(records); + return R.ok(IPages.buildDataMap(iPage)); + } + +} + diff --git a/src/main/java/com/supervision/police/service/impl/ModelIndexServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ModelIndexServiceImpl.java new file mode 100644 index 0000000..bccd2e8 --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/ModelIndexServiceImpl.java @@ -0,0 +1,154 @@ +package com.supervision.police.service.impl; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.common.domain.R; +import com.supervision.common.utils.IPages; +import com.supervision.common.utils.StringUtils; +import com.supervision.police.domain.ComDictionary; +import com.supervision.police.domain.ModelAtomicIndex; +import com.supervision.police.dto.AtomicData; +import com.supervision.police.dto.JudgeLogic; +import com.supervision.police.mapper.ModelAtomicIndexMapper; +import com.supervision.police.mapper.ModelIndexMapper; +import com.supervision.police.domain.ModelIndex; +import com.supervision.police.service.ComDictionaryService; +import com.supervision.police.service.ModelIndexService; +import com.supervision.springaidemo.dto.MetricResultDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 指标表(ModelIndex)表服务实现类 + * + * @author qmy + * @since 2024-07-05 09:20:10 + */ +@Service +public class ModelIndexServiceImpl extends ServiceImpl implements ModelIndexService { + + @Autowired + private ComDictionaryService comDictionaryService; + + @Autowired + private ModelIndexMapper modelIndexMapper; + + @Autowired + private ModelAtomicIndexMapper modelAtomicIndexMapper; + + @Override + public R selectAll(ModelIndex modelIndex, Integer page, Integer size) { + IPage iPage = new Page<>(page, size); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.like(modelIndex.getName() != null, ModelIndex::getName, modelIndex.getName()) + .like(modelIndex.getShortName() != null, ModelIndex::getShortName, modelIndex.getShortName()) + .like(modelIndex.getRemark() != null, ModelIndex::getRemark, modelIndex.getRemark()) + .eq(StringUtils.isNotEmpty(modelIndex.getIndexType()), ModelIndex::getIndexType, modelIndex.getIndexType()) + .eq(StringUtils.isNotEmpty(modelIndex.getCaseType()), ModelIndex::getCaseType, modelIndex.getCaseType()) + .eq(ModelIndex::getDataStatus, "1"); + iPage = modelIndexMapper.selectPage(iPage, wrapper); + List records = iPage.getRecords(); + List dicts = comDictionaryService.list(); + for (ModelIndex index : records) { + index.setIndexTypeName(comDictionaryService.getName(dicts, "index_type", index.getIndexType())); + index.setCaseTypeName(comDictionaryService.getName(dicts, "case_type", index.getCaseType())); + //原子指标 + String judgeLogic = index.getJudgeLogic(); + List ids = new ArrayList<>(); + if (StringUtils.isNotEmpty(judgeLogic)) { + List logic = JSONUtil.toList(judgeLogic, JudgeLogic.class); + for (JudgeLogic judge : logic) { + List atomicData = judge.getAtomicData(); + for (AtomicData atomic : atomicData) { + ids.add(atomic.getAtomicIndex()); + } + } + List atomicIndexList = modelAtomicIndexMapper.selectBatchIds(ids); + index.setAtomicIndexList(atomicIndexList); + } + index.setAtomicIndexNum(ids.size()); + } + iPage.setRecords(records); + return R.ok(IPages.buildDataMap(iPage)); + } + + @Override + public R addOrUpd(ModelIndex modelIndex) { + int i = 0; + if (StringUtils.isEmpty(modelIndex.getId())) { + i = modelIndexMapper.insert(modelIndex); + } else { + i = modelIndexMapper.updateById(modelIndex); + } + if (i > 0) { + return R.okMsg("保存成功"); + } else { + return R.fail("保存失败"); + } + } + + @Override + public R del(String id) { + ModelIndex index = modelIndexMapper.selectById(id); + index.setDataStatus(StringUtils.getUUID()); + int i = modelIndexMapper.updateById(index); + if (i > 0) { + return R.okMsg("删除成功"); + } else { + return R.fail("删除失败"); + } + } + + @Override + public R selectAllAtomic(ModelAtomicIndex modelAtomicIndex, Integer page, Integer size) { + IPage iPage = new Page<>(page, size); + iPage = modelAtomicIndexMapper.selectAll(iPage, modelAtomicIndex); + List records = iPage.getRecords(); + List dicts = comDictionaryService.list(); + for (ModelAtomicIndex index : records) { + index.setCaseTypeName(comDictionaryService.getName(dicts, "case_type", index.getCaseType())); + index.setIndexSourceName(comDictionaryService.getName(dicts, "index_source", index.getIndexSource())); + index.setRecordTypeName(comDictionaryService.getName(dicts, "record_type", index.getRecordType())); + } + iPage.setRecords(records); + return R.ok(IPages.buildDataMap(iPage)); + } + + @Override + public R addOrUpdAtomic(ModelAtomicIndex modelAtomicIndex) { + int i = 0; + if (StringUtils.isEmpty(modelAtomicIndex.getId())) { + i = modelAtomicIndexMapper.insert(modelAtomicIndex); + } else { + i = modelAtomicIndexMapper.updateById(modelAtomicIndex); + } + if (i > 0) { + return R.okMsg("保存成功"); + } else { + return R.fail("保存失败"); + } + } + + @Override + public R delAtomic(String id) { + ModelAtomicIndex index = modelAtomicIndexMapper.selectById(id); + index.setDataStatus(StringUtils.getUUID()); + int i = modelAtomicIndexMapper.updateById(index); + if (i > 0) { + return R.okMsg("删除成功"); + } else { + return R.fail("删除失败"); + } + } +} + diff --git a/src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java new file mode 100644 index 0000000..1b1a7f8 --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/ModelRecordTypeServiceImpl.java @@ -0,0 +1,218 @@ +package com.supervision.police.service.impl; + +import com.alibaba.druid.util.StringUtils; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.common.domain.R; +import com.supervision.neo4j.domain.CaseNode; +import com.supervision.neo4j.domain.Rel; +import com.supervision.neo4j.service.Neo4jService; +import com.supervision.police.domain.ModelRecordType; +import com.supervision.police.domain.NoteRecord; +import com.supervision.police.domain.NotePrompt; +import com.supervision.police.domain.TripleInfo; +import com.supervision.police.mapper.ModelRecordTypeMapper; +import com.supervision.police.mapper.NoteRecordMapper; +import com.supervision.police.mapper.NotePromptMapper; +import com.supervision.police.mapper.TripleInfoMapper; +import com.supervision.police.service.ModelRecordTypeService; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONArray; +import org.json.JSONObject; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StopWatch; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Slf4j +@Service +public class ModelRecordTypeServiceImpl extends ServiceImpl implements ModelRecordTypeService { + + @Autowired + private ModelRecordTypeMapper modelRecordTypeMapper; + + @Autowired + private NoteRecordMapper noteRecordMapper; + + @Autowired + private NotePromptMapper notePromptMapper; + + private final OllamaChatClient chatClient; + @Autowired + public ModelRecordTypeServiceImpl(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + @Autowired + private TripleInfoMapper tripleInfoMapper; + + @Autowired + private Neo4jService neo4jService; + + @Override + public R queryType(String name, Integer page, Integer size) { +// IPage iPage = new Page<>(page, size); +// iPage = modelRecordTypeMapper.selectByName(iPage, name); +// return R.ok(IPages.buildDataMap(iPage)); + List list = modelRecordTypeMapper.selectByName(name); + + for (ModelRecordType modelRecordType : list) { + //笔录内容 + List noteRecords = noteRecordMapper.selectByRecordType(modelRecordType.getRecordType()); + modelRecordType.setRecords(noteRecords); + //提示词 + List prompts = notePromptMapper.queryPrompt(modelRecordType.getId()); + modelRecordType.setPrompts(prompts); + } + return R.ok(list); +// return R.ok(IPages.buildDataMap(iPage)); + } + + @Override + public ModelRecordType queryByName(String content) { + Wrapper wrapper = new QueryWrapper().eq("record_type", content); + return modelRecordTypeMapper.selectOne(wrapper); + } + + @Override + public R saveType(ModelRecordType type) { + String id = type.getId(); + int i = 0; + if (StringUtils.isEmpty(id)) { + //新增 + i = modelRecordTypeMapper.insert(type); + } else { + i = modelRecordTypeMapper.updateById(type); + } + if (i > 0) { + return R.ok("保存成功"); + } else { + return R.fail("保存失败"); + } + } + + @Override + public R addOrUpdPrompt(NotePrompt prompt) { + int i = 0; + if (StringUtils.isEmpty(prompt.getId())) { + i = notePromptMapper.insert(prompt); + } else { + i = notePromptMapper.updateById(prompt); + } + if (i > 0) { + return R.ok("保存成功"); + } else { + return R.fail("保存失败"); + } + } + + @Override + public R delPrompt(NotePrompt prompt) { + String id = prompt.getId(); + int i = notePromptMapper.deleteById(id); + if (i > 0) { + return R.ok("删除成功"); + } else { + return R.fail("删除失败"); + } + } + + @Override + public R getThreeInfo(String caseId, String name, String recordId) { + List records = noteRecordMapper.selectRecord(caseId, name, recordId); + List tripleInfos = new ArrayList<>(); + for (NoteRecord record : records) { + List prompts = notePromptMapper.queryPrompt(record.getRecordTypeId()); + for (NotePrompt prompt : prompts) { + if (StringUtils.isEmpty(prompt.getPrompt())) { + continue; + } + try { + // 分析三元组 + List messages = new ArrayList<>(List.of(new SystemMessage(prompt.getPrompt() + record.getQuestion() + record.getAnswer()))); + Prompt ask = new Prompt(messages); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + log.info("开始分析:"); + ChatResponse call = chatClient.call(ask); + stopWatch.stop(); + log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); + log.info("分析的结果是:{}", content); + JSONObject jsonObject = new JSONObject(content); + JSONArray threeInfo = jsonObject.getJSONArray("result"); + for (int i = 0; i < threeInfo.length(); i++) { + JSONObject object = threeInfo.getJSONObject(i); + String startNodeType = object.getString("startNodeType"); + String entity = object.getString("entity"); + String endNodeType = object.getString("endNodeType"); + String property = object.getString("property"); + String value = object.getString("value"); + //去空 + if (StringUtils.isEmpty(startNodeType) || StringUtils.isEmpty(entity) || StringUtils.isEmpty(endNodeType) + || StringUtils.isEmpty(property) || StringUtils.isEmpty(value)) { + continue; + } + TripleInfo tripleInfo = new TripleInfo(entity, property, value, record.getId(), new Date(), startNodeType, endNodeType); + tripleInfoMapper.insert(tripleInfo); + tripleInfos.add(tripleInfo); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return R.ok(tripleInfos); + } + + @Override + public R addNeo4j(List ids) { + List tripleInfos = tripleInfoMapper.selectByIds(ids); + int i = 0; + for (TripleInfo tripleInfo : tripleInfos) { + try { + //开始节点 + String start = tripleInfo.getStartNode(); + CaseNode startNode = neo4jService.findOneByName(tripleInfo.getCaseId(), tripleInfo.getNoteRecordsId(), tripleInfo.getStartNodeType(), start, "1"); + if (startNode == null) { + startNode = new CaseNode(start, tripleInfo.getStartNodeType(), tripleInfo.getNoteRecordId(), tripleInfo.getNoteRecordsId(), tripleInfo.getCaseId(), "1"); + CaseNode save = (CaseNode) neo4jService.save(startNode).getData(); + startNode.setId(save.getId()); + } + //结束节点 + String end = tripleInfo.getEndNode(); + CaseNode endNode = neo4jService.findOneByName(tripleInfo.getCaseId(), tripleInfo.getNoteRecordsId(), tripleInfo.getEndNodeType(), end, "1"); + if (endNode == null) { + endNode = new CaseNode(end, tripleInfo.getEndNodeType(), tripleInfo.getNoteRecordId(), tripleInfo.getNoteRecordsId(), tripleInfo.getCaseId(), "1"); + CaseNode save = (CaseNode) neo4jService.save(endNode).getData(); + endNode.setId(save.getId()); + } + //关系 + Rel rel = new Rel(startNode.getId(), tripleInfo.getRelation(), endNode.getId()); + Rel relation = neo4jService.findRelation(rel); + if (relation == null) { + R r = neo4jService.saveRelation(rel); + } + tripleInfo.setAddNeo4j("1"); + int j = tripleInfoMapper.updateById(tripleInfo); + if (j > 0) { + i++; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return R.ok("成功插入" + i + "条信息"); + } +} diff --git a/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java new file mode 100644 index 0000000..68b431f --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java @@ -0,0 +1,185 @@ +package com.supervision.police.service.impl; + +import cn.hutool.json.JSONUtil; +import com.supervision.common.domain.R; +import com.supervision.common.utils.StringUtils; +import com.supervision.neo4j.dto.ResultDTO; +import com.supervision.neo4j.utils.Neo4jUtils; +import com.supervision.police.domain.*; +import com.supervision.police.dto.AnalyseCaseDTO; +import com.supervision.police.dto.AtomicData; +import com.supervision.police.dto.JudgeLogic; +import com.supervision.police.mapper.*; +import com.supervision.police.service.ModelService; +import org.neo4j.driver.Driver; +import org.neo4j.driver.Result; +import org.neo4j.driver.Session; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Service +public class ModelServiceImpl implements ModelService { + + @Autowired + private ModelCaseMapper modelCaseMapper; + + @Autowired + private ModelAtomicIndexMapper modelAtomicIndexMapper; + + private final Driver driver; + @Autowired + private ModelServiceImpl(Driver driver) { + this.driver = driver; + } + + @Autowired + private ModelAtomicResultMapper modelAtomicResultMapper; + + @Autowired + private ModelIndexMapper modelIndexMapper; + + @Autowired + private ModelIndexResultMapper modelIndexResultMapper; + + @Override + public R analyseCase(AnalyseCaseDTO analyseCaseDTO) { + ModelCase modelCase = modelCaseMapper.selectById(analyseCaseDTO.getCaseId()); + //原子指标 + List atomicIndices = modelAtomicIndexMapper.selectByCaseType(modelCase.getCaseType()); + Map atomic = new HashMap<>(); + for (ModelAtomicIndex atomicIndex : atomicIndices) { + //原子指标结果 + ModelAtomicResult result = new ModelAtomicResult(); + result.setCaseId(analyseCaseDTO.getCaseId()); + result.setAtomicId(atomicIndex.getId()); + //查询语句 + String ql = atomicIndex.getQueryLang(); + Map params = new HashMap<>(); + params.put("lawActor", analyseCaseDTO.getLawActor()); + params.put("caseId", analyseCaseDTO.getCaseId()); + //原子指标结果表 + try { + // index_source==1 + List list = analyseCaseDTO.getAtomicIndexList(); + //index_source==3 + Session session = driver.session(); + //查询图谱 index_source: 1人工定义 2数据库查询 3图谱生成 4大模型 + if ("1".endsWith(atomicIndex.getIndexSource())) { + // list + } else if ("2".endsWith(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) { + // + } else if ("3".endsWith(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) { + //图谱 + int i = 1; + String lawPartys = analyseCaseDTO.getLawParty(); + String[] split = StringUtils.isEmpty(lawPartys) ? new String[0] : lawPartys.split(","); + if (ql.contains("$lawParty") && split.length > 1) { + i = split.length; + } + for (int j = 0; j < i; j++) { + if (split.length > 0) { + params.put("lawParty", split[j]); + } + Result run = session.run(ql, params); + List res = Neo4jUtils.getResultDTOList(run); + if (res.isEmpty()) { + result.setAtomicResult("-1"); + } else { + ResultDTO resultDTO = res.get(0); + if (StringUtils.isNotEmpty(resultDTO.getRelId())) { + //存在关系 + result.setAtomicResult("1"); + result.setRecordId(resultDTO.getRecordId()); + result.setRecordsId(resultDTO.getRecordsId()); + break; + } else { + result.setAtomicResult("0"); + } + } + } + } else if ("4".endsWith(atomicIndex.getIndexSource())) { + // + } + } catch (Exception e) { + e.printStackTrace(); + } + //保存原子指标结果表 + ModelAtomicResult exist = modelAtomicResultMapper.selectByCaseIdAndAtomicId(analyseCaseDTO.getCaseId(), atomicIndex.getId()); + if (exist == null) { + modelAtomicResultMapper.insert(result); + } else { + result.setId(exist.getId()); + modelAtomicResultMapper.updateById(result); + } + // 所有原子指标id + atomic.put(result.getAtomicId(), "1".equals(result.getAtomicResult())); + } + + // 计算指标结果 + int score = 0; + List modelIndices = modelIndexMapper.selectByCaseType(modelCase.getCaseType()); + for (ModelIndex modelIndex : modelIndices) { + ModelIndexResult result = new ModelIndexResult(); + result.setCaseId(analyseCaseDTO.getCaseId()); + result.setIndexId(modelIndex.getId()); + Set atomicIds = new HashSet<>(); + if (StringUtils.isNotEmpty(modelIndex.getJudgeLogic())) { + List judgeLogics = JSONUtil.toList(modelIndex.getJudgeLogic(), JudgeLogic.class); + boolean res = false; + for (int i = 0; i < judgeLogics.size(); i++) { + boolean group = false; + JudgeLogic logic = judgeLogics.get(i); + String rowLogic = logic.getRowLogic(); + List atomicData = logic.getAtomicData(); + for (int j = 0; j < atomicData.size(); j++) { + AtomicData data = atomicData.get(j); + atomicIds.add(data.getAtomicIndex()); + Boolean ato = atomic.get(data.getAtomicIndex()); + String relationalSymbol = data.getRelationalSymbol(); + if ("2".equals(relationalSymbol) || "4".equals(relationalSymbol) || "5".equals(relationalSymbol)) { + ato = !ato; + } + if (j == 0) { + group = ato; + } else { + if ("1".equals(rowLogic)) { + group = group && ato; + } else if ("2".equals(rowLogic)) { + group = group || ato; + } + } + } + String groupLogic = logic.getGroupLogic(); + if (i == 0) { + res = group; + } else { + if ("1".equals(groupLogic)) { + res = res && group; + } else if ("2".equals(groupLogic)) { + res = res || group; + } + } + } + result.setIndexResult(res? "true" : "false"); + result.setAtomicIds(StringUtils.join(atomicIds, ",")); + } + ModelIndexResult exist = modelIndexResultMapper.selectByCaseIdAndIndexId(analyseCaseDTO.getCaseId(), modelIndex.getId()); + if (exist == null) { + modelIndexResultMapper.insert(result); + } else { + result.setId(exist.getId()); + modelIndexResultMapper.updateById(result); + } + + if ("true".equals(result.getIndexResult())) { + score = score + modelIndex.getIndexScore(); + } + } + modelCase.setTotalScore(score); + modelCaseMapper.updateById(modelCase); + return R.ok(); + } + +} diff --git a/src/main/java/com/supervision/police/service/impl/NoteCheckRecordServiceImpl.java b/src/main/java/com/supervision/police/service/impl/NoteCheckRecordServiceImpl.java new file mode 100644 index 0000000..03c254c --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/NoteCheckRecordServiceImpl.java @@ -0,0 +1,22 @@ +package com.supervision.police.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.springaidemo.domain.NoteCheckRecord; +import com.supervision.police.service.NoteCheckRecordService; +import com.supervision.police.mapper.NoteCheckRecordMapper; +import org.springframework.stereotype.Service; + +/** +* @author flevance +* @description 针对表【note_check_record(案件执行验证结果)】的数据库操作Service实现 +* @createDate 2024-05-11 15:47:02 +*/ +@Service +public class NoteCheckRecordServiceImpl extends ServiceImpl + implements NoteCheckRecordService{ + +} + + + + diff --git a/src/main/java/com/supervision/police/service/impl/RecordServiceImpl.java b/src/main/java/com/supervision/police/service/impl/RecordServiceImpl.java new file mode 100644 index 0000000..770bda0 --- /dev/null +++ b/src/main/java/com/supervision/police/service/impl/RecordServiceImpl.java @@ -0,0 +1,228 @@ +package com.supervision.police.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.common.domain.R; +import com.supervision.common.utils.IPages; +import com.supervision.common.utils.ListUtils; +import com.supervision.common.utils.StringUtils; +import com.supervision.minio.domain.MinioFile; +import com.supervision.minio.mapper.MinioFileMapper; +import com.supervision.minio.service.MinioService; +import com.supervision.police.domain.ModelCase; +import com.supervision.police.domain.ModelRecordType; +import com.supervision.police.domain.NoteRecord; +import com.supervision.police.domain.NoteRecords; +import com.supervision.police.mapper.ModelCaseMapper; +import com.supervision.police.mapper.ModelRecordTypeMapper; +import com.supervision.police.mapper.NoteRecordMapper; +import com.supervision.police.mapper.NoteRecordsMapper; +import com.supervision.police.service.RecordService; +import com.supervision.springaidemo.dto.QARecordNodeDTO; +import com.supervision.springaidemo.util.RecordRegexUtil; +import com.supervision.springaidemo.util.WordReadUtil; +import lombok.extern.slf4j.Slf4j; +import org.json.JSONObject; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StopWatch; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Service +public class RecordServiceImpl extends ServiceImpl implements RecordService { + + @Autowired + private NoteRecordMapper noteRecordMapper; + + @Autowired + private NoteRecordsMapper noteRecordsMapper; + + @Autowired + private MinioService minioService; + + @Autowired + private ModelCaseMapper modelCaseMapper; + + @Autowired + private MinioFileMapper minioFileMapper; + + private final OllamaChatClient chatClient; + @Autowired + public RecordServiceImpl(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + @Autowired + private ModelRecordTypeMapper modelRecordTypeMapper; + + @Override +// @Transactional(rollbackFor = Exception.class) + public R uploadRecords(NoteRecords records, List fileList) throws IOException { + //上传文件,获取文件ids + List fileIds = new ArrayList<>(); + for (MultipartFile file : fileList) { + String fileId = minioService.uploadFile(file); + fileIds.add(fileId); + } + if (StringUtils.isNotEmpty(records.getFileIds())) { + records.setFileIds(records.getFileIds() + "," + StringUtils.join(fileIds, ",")); + } else { + records.setFileIds(StringUtils.join(fileIds, ",")); + } + //修改案件的行为人、当事人 + if (StringUtils.isNotEmpty(records.getRole()) && !"嫌疑人".equals(records.getRole())) { + ModelCase modelCase = modelCaseMapper.selectById(records.getCaseId()); + //行为人 + if ("行为人".equals(records.getRole()) && StringUtils.isEmpty(modelCase.getLawActor())) { + modelCase.setLawActor(records.getName()); + modelCaseMapper.updateById(modelCase); + } else if ("受害人".equals(records.getRole()) || "证人".equals(records.getRole())) { + if (StringUtils.isEmpty(modelCase.getLawParty())) { + modelCase.setLawParty(records.getName()); + } else { + String[] split = modelCase.getLawParty().split(","); + if (!Arrays.asList(split).contains(records.getName())) { + modelCase.setLawParty(modelCase.getLawParty() + "," + records.getName()); + } + } + modelCaseMapper.updateById(modelCase); + } + } + int i = 0; + if (StringUtils.isEmpty(records.getId())) { + i = noteRecordsMapper.insert(records); + } else { + i = noteRecordsMapper.updateById(records); + } + //所有对话类型 + List allTypes = modelRecordTypeMapper.getAllType(); + + if (i > 0) { + //拆分笔录 + for (MultipartFile file : fileList) { + String context = WordReadUtil.readWord(file); + List qaList = RecordRegexUtil.recordRegex(context, records.getName()); + for (QARecordNodeDTO qa : qaList) { + try { + NoteRecord noteRecord = new NoteRecord(); + noteRecord.setCaseId(records.getCaseId()); + noteRecord.setNoteRecordsId(records.getId()); + noteRecord.setNoteName(file.getName()); + noteRecord.setPersonName(records.getName()); + noteRecord.setQuestion(qa.getQuestion()); + noteRecord.setAnswer(qa.getAnswer()); + noteRecord.setCreateTime(new Date()); + String test = "分类任务: 对话笔记录文本分类。目标: 将给定的对话笔记录分配到预定义的类别中,这些类别包括但不限于: " + allTypes.toString() + "。"; + String example = "说明: 提供一段对话笔记录文本,分类器应该识别出对话的主题,并将其归类到上述类别中的一个。" + + "示例输入: 文本: \"办案警官问:你为了骗取更多的钱都做了哪些准备?。裴金禄回答:我刚开始我就是自己想了一些关于骗钱的点子,后面为了更不容易让别人识破我为了更佳逼真,我就从网上随便搜了一家租赁公司,我就搜到了兰州胜利机械租赁有限公司,我又想到了我管理的中铁北京局和中铁电气化局施工公司。我先是通过百度搜索了“办证”之后就在网页上面弹出了一个页面上面有一个QQ号,我就加上了。加上之后我就将我的要求给他说了,要求他给我刻两个假的公章,一个是兰州胜利机械租赁有限公司合同专用章,另一个是中铁北京局集团有限公司合同专用章。我还要求他给我伪造了一张兰州胜利机械租赁有限公司的营业执照\"" + + "预期输出: { type: '诈骗准备' }" + + "任务要求: " + + "1. 分类器应当准确地识别对话的主题。 " + + "2. 如果一段对话笔记录包含多个主题,请选择最相关的类别。" + + "3. 必须考虑上下文语境和专业术语来确定正确的分类。"; + String end = "对话内容为:"; + List messages = new ArrayList<>(List.of(new SystemMessage(test + example + end + qa.getQuestion() + qa.getAnswer()))); + Prompt prompt = new Prompt(messages); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + log.info("开始分析:"); + ChatResponse call = chatClient.call(prompt); + stopWatch.stop(); + log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); + log.info("问:{}, 答:{}", qa.getQuestion(), qa.getAnswer()); + log.info("分析的结果是:{}", content); + JSONObject jsonObject = new JSONObject(content); + String type = jsonObject.getString("type").trim(); + System.out.println("问:" + qa.getQuestion() + "答:" + qa.getAnswer()); + System.out.println("分析的结果是:" + type); +/* // todo 写死测试 + String type = ""; + if (qa.getQuestion().contains("你为了骗取更多的钱都做了哪些准备")) { + type = "诈骗准备"; + } else { + continue; + }*/ + //保存笔录 + noteRecord.setRecordType(type); + noteRecordMapper.insert(noteRecord); + } catch (Exception e) { + e.printStackTrace(); + } +// ModelRecordType exist = modelRecordTypeMapper.queryByName(type); +// if (exist == null) { +// ModelRecordType modelRecordType = new ModelRecordType(); +// modelRecordType.setRecordType(type); +// modelRecordTypeMapper.insert(modelRecordType); +// } + } + } + return R.okMsg("保存成功"); + } else { + return R.fail("保存笔录失败"); + } + } + + @Override + public R queryRecords(NoteRecords noteRecords, Integer page, Integer size) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.like(StringUtils.isNotEmpty(noteRecords.getName()), NoteRecords::getName, noteRecords.getName()) + .eq(NoteRecords::getCaseId, noteRecords.getCaseId()) + .eq(NoteRecords::getDataStatus, "1"); + List list = noteRecordsMapper.selectList(wrapper); + // LinkedHashMap 保障顺序 + Map> nameMap = list.stream().filter(item -> StringUtils.isNotBlank(item.getName())) + .collect(Collectors.groupingBy(NoteRecords::getName, LinkedHashMap::new, Collectors.toList())); + List res = new ArrayList<>(); + for (String name : nameMap.keySet()) { + NoteRecords noteRecord = new NoteRecords(); + noteRecord.setName(name); + noteRecord.setChildren(nameMap.get(name)); + res.add(noteRecord); + } + List pager = ListUtils.Pager(size, page, res); + for (NoteRecords person : pager) { + for (NoteRecords noteRecord : person.getChildren()) { + String fileIds = noteRecord.getFileIds(); + if (StringUtils.isNotEmpty(fileIds)) { + noteRecord.setConfessionMaterial(fileIds.split(",").length); + } + } + } + return R.ok(IPages.buildDataMap(pager, res.size())); + } + + @Override + public R delRecords(String id) { + NoteRecords noteRecords = noteRecordsMapper.selectById(id); + noteRecords.setDataStatus(StringUtils.getUUID()); + noteRecordsMapper.updateById(noteRecords); + String fileIds = noteRecords.getFileIds(); + if (StringUtils.isNotEmpty(fileIds)) { + //删除文件 + for (String fileId : fileIds.split(",")) { + MinioFile minioFile = minioFileMapper.selectById(fileId); + minioFile.setDataStatus(StringUtils.getUUID()); + minioFileMapper.updateById(minioFile); + minioService.delFile(fileId); + } + } + return R.ok(); + } + +} diff --git a/src/main/java/com/supervision/springaidemo/controller/ChatController.java b/src/main/java/com/supervision/springaidemo/controller/ChatController.java new file mode 100644 index 0000000..68c151c --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/ChatController.java @@ -0,0 +1,336 @@ +package com.supervision.springaidemo.controller; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.supervision.springaidemo.domain.ModelMetric; +import com.supervision.springaidemo.domain.NoteCheckRecord; +import com.supervision.springaidemo.dto.MetricResultDTO; +import com.supervision.springaidemo.service.ModelMetricService; +import com.supervision.police.service.NoteCheckRecordService; +import com.supervision.springaidemo.thread.RunCheckThread; +import com.supervision.springaidemo.thread.RunCheckThreadPool; +import com.supervision.springaidemo.util.WordReadUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.BufferedReader; +import java.io.File; +import java.util.*; + +@RestController +@Slf4j +public class ChatController { + + private final OllamaChatClient chatClient; + + @Autowired + private ModelMetricService modelMetricService; + + @Autowired + private NoteCheckRecordService noteCheckRecordService; + + // 使用多线程进行提交 + + + @Autowired + public ChatController(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + @GetMapping("/ai/chat") + public void generate() { + String template = """ + 一般嫌疑人或者受害者在笔录中说什么话能对应到下面指标呢 + + 例子:指标:是否有金钱往来。回复:["XXX给我转来的钱。","我收到过XXX给我转来的钱","我通过银行给XXX转了钱"] + 现在请对下面这个指标进行举例,例子要尽可能覆盖更多的情况;既要有行为人可能承认的话10条,还要有受害者可能指认的话10条! + 指标:行为人在合同签订后支付了部分货款,并骗取全部货物后,在规定的期限内无正当理由不支付其余货款 + 回复json格式:{"behavior":[""],"victim":[""]} + """; + Prompt prompt = new Prompt(List.of(new UserMessage(template))); + ChatResponse call = chatClient.call(prompt); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); + log.info(content); + } + + private Message buildMessage(Map param) { + String messageTemplate = """ + 以下是案件的身份信息 + --- + 行为人:金(李),吴 + 受害人:刘,尚,张 + --- + 以下是笔录的内容: + --- + 问:我们是经侦大队的民警(出示工作证件),现依法向你询问有关问题。根据刑事诉讼法的有关规定,你应当如实提供证据、证言,如果有意作伪证或者隐匿罪证的,要负法律责任。你明白吗?答:明白。 + 问:现向你宣读《证人诉讼权利义务告知书》(向当事人宣读《证人诉讼权利义务告知书》,并将《证人诉讼权利义务告知书》送交当事人),你对你的权利义务是否清楚?答:清楚了。 + 问:你有什么要求吗?答:没有。 + 问:你的个人情况?答:我叫张,曾用名无,男,1980年出生,汉族,高中文化程度,户籍所在地宁夏固原市,现住宁夏固原市,现在无工作,居民身份证号码642226,联系电话13519。 + 问:你是否是中国共产党党员或国家机关工作人员?答:都不是。 + 问:你认识刘吗?答:认识,我们是朋友。 + 问:刘于2022年03月23日在我局报称:他和你、尚3人想合作经营一家汽车公司,被一名男子金骗了,该金自称是汽车有限公司的工作人员,负责西北地区推销,与刘签订了《汽车租赁合同》,租赁8辆新能源汽车,并协商每辆汽车缴纳5万元的押金使用3年,3年后由汽车公司收回车辆,退还押金,后刘分2次给该公司公户内转账20万元前期押金,剩余20万元押金等车辆到固原后将车辆上牌,再进行支付。支付押金后,金与该公司以各种借口推诿,至今未将租赁车辆交给你们3人,是否属实?答:属实。 + 问:你是如何得知汽车公司的?答:是金给我介绍的。 + 问:金是如何认识的?答:金是我通过平台认识,之后我们成为微信好友。 + 问:金是如何给你介绍汽车的?答:我之前与金在平台认识,之后我们成为微信好友,金平常就在微信内给我推送关于汽车的模式和链接。我当时看这个生意可以盈利,就与金了解汽车。 + 问:你是如何给刘和尚介绍的?答:当时我与金了解了汽车,前期需要投入40万元,我能力有限,就将此事与刘和尚商议,我当时给他们说合作在固原开一家汽车运营公司(包括卖车业务、租车业务、还有新能源汽车销售业务),我们3人商议后达成了合作协议。 + 问:你与刘、尚是如何出资的?答:前期需要缴纳20万元的押金,我出资了3万元,尚出资了5万元,刘出资了12万元,我和尚的钱全部交给刘,是刘分2次给汽车公司转账的。 + 问:你们具体是谁与金联系对接业务的?答:具体尚与金联系对接业务的。 + 问:你们将押金转给该公司后,该公司是否将你们预定的车辆发给你们?答:我们将20万元的押金转给该公司后,该公司与金以各种借口推诿,一直未将我们预定的车辆发给我们。之后我们到你们公安局报案,经你们民警联系后,该公司与金于2022年给我们发了一辆电动车,我当时察看后,该车是一辆旧车,也不能正常从板车上开下,我就没有要。 + 问:是谁给你通知让你去接车的?答:当时是一个山东省电话号码给我打电话,让我去固原市高速公路南出口接车,我去看见是一辆旧车,我就询问车辆司机,该车是从什么地方拉来的,司机称是从西安市拉来的。 + 问:你们当时是谁与金签订的《汽车租赁合同》?答:是刘与金签订的。 + 问:你们除了签订《汽车租赁合同》,还签订什么协议了吗?答:我们还签订了一份《授权及扶持补充协议》。 + 问:签订的《汽车租赁合同》、《授权及扶持补充协议》是谁制作的?答:是金带来的。 + 问:签订合同时,你是否在场?现场还有谁?答:我在场,现场还有尚,还有与金一起的女子。 + 问:你们当时签订合同预定的都是什么牌子的车辆?答:总共8辆全新的(刚出厂未挂牌)汽车,分别是创维4辆,奔腾2辆,尼桑1辆,大众朗逸1辆。 + 问:你讲一下金的基本情况?答:该男子真名不叫金,我们报案后,才知道该男子叫李,是山东人,身份证号码是:37078,联系电话是18,微信号是J,其他什么情况我不清楚。 + 问:你讲一下与金一起来的女子的基本情况?答:我只知道该女子姓吴,金称是他们公司的行政经理,联系电话是178,其他什么情况我不知道。 + 问:该姓吴女子来固原具体都做了什么工作?答:她只是来固原给我们办理注册公司。 + 问:你还有什么需要补充说明的吗?答:2022年01月刘将剩余的16万元转给该公司账户内,01月金(李)在微信内建了个微信群,群内有我、刘、尚、金(李)、刘、吴6人,称刘是汽车公司负责给各地发车,吴现在已经不在该群内了。 + 问:你以上所讲的是否属实?答:属实。 + 问:以上笔录请你仔细阅看。如果记录有误请指出来,我们即给予更正。请你确认记录无误后再在笔录上逐页签名。答:好的。 + --- + + 现在需要你根据以上内容,进行判断并以简体中文输出下面的各项,注意:如果笔录里面有提到了存在相关证据,则你可以认为这些证据文件是真实存在的 + 1.指标名称:{metricName}。 + 2.结论:true({metricTrueDesc})/false({metricFalseDesc}),直接给我true/false。 + 3.笔录对应原话:从笔录的对话中,得到该结论的原文(一定是摘抄的原文)。 + 4.原因:分析得出该结论的原因,需明确说明为什么得到该结论,需要逻辑清晰完整。 + + 判断结果以json格式回复, JSON的value内容我给你的提示,在实际输出的时候不需要带上: + --- + {"metricName":"指标名称", "result":"结论", "originalContext":"笔录对应原话","reason":"原因"} + --- + """; + String format = StrUtil.format(messageTemplate, param); + return new UserMessage(format); + } + + + @GetMapping("/ai/run") + public void run() { + var list = modelMetricService.list(); + for (ModelMetric modelMetric : list) { + Map param = new HashMap<>(); + param.put("metricTrueDesc", modelMetric.getMetricTrueDesc()); + param.put("metricFalseDesc", modelMetric.getMetricFalseDesc()); + param.put("metricName", modelMetric.getMetricName()); + Message message = buildMessage(param); + Prompt prompt = new Prompt(List.of(new SystemMessage("所有的回复以简体中文回答。请以step by step的方式进行。step1:理解笔录设计人员的身份信息;step2:根据笔录的内容分析案件之间的逻辑关系和关联;step3:判断给定的指标是否满足。step4:根据要求的给定格式进行回复"), message)); + log.info("prompt:{}", prompt.toString()); + ChatResponse call = chatClient.call(prompt); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); + log.info(content); + } + } + + private static final String template = """ + 我们现在需要以step by step的方式进行笔录的指标分析工作,得到最终的结果并返回。 + step1:理解下面人员身份信息; + --- + 行为人:{actionUserNameList} + 犯罪嫌疑人:{suspectUserNameList} + 受害人:{victimUserNameList} + 证人:{witnessNameList} + --- + + step2:分析笔录的内容; + 以下是笔录的内容,笔录中"问"是办案警官问,"答"是{noteUserName}回答: + --- + {context} + --- + + step3:现在给你指标以及指标的释义或例子: + 指标:{metricName} + 指标释义或例子及判断标准: + 如({metricTrueDesc}),则为true; + 如({metricFalseDesc}),则为false; + 如果笔录中,没有任何笔录内容涉及到该项指标,则为empty。 + + step4:现在需要你根据上面提供的所有信息,尽可能实事求是完成判断: + 1.判断结论:true/false/empty + 2.得到结论的笔录原话:从笔录的对话中,得到该结论的原文(一定是摘抄的原文且为中文)。如果结论为true,则必须要有原文佐证! + 3.得到结论的原因:分析得出该结论的原因,需明确说明为什么得到该结论,需要实事求是且为中文回复。如果结论为true/false,则必须有原因! + + + step5:必须以json格式回复, JSON的value内容我给你的提示,在实际输出的时候不需要带上: + --- + {"result":"结论", "originalContext":"笔录对应原话","reason":"原因"} + --- + 好了,现在可以回复了! + """; + + @GetMapping("runNoteCheck") + public void runNoteCheck() { + HashMap map = new HashMap<>(); + map.put("杨学明", "/Users/flevance/Desktop/宁夏审讯大模型/陈恩明合同诈骗/受害人杨学明询问笔录.docx"); + map.put("朱文泽", "/Users/flevance/Desktop/宁夏审讯大模型/陈恩明合同诈骗/受害人朱文泽询问笔录.docx"); + map.put("陈恩明", "/Users/flevance/Desktop/宁夏审讯大模型/陈恩明合同诈骗/嫌疑人陈恩明讯问笔录.docx"); + map.put("武桂清1", "/Users/flevance/Desktop/宁夏审讯大模型/陈恩明合同诈骗/嫌疑人武桂清讯问笔录1.docx"); + map.put("武桂清2", "/Users/flevance/Desktop/宁夏审讯大模型/陈恩明合同诈骗/嫌疑人武桂清讯问笔录2.docx"); + for (Map.Entry entry : map.entrySet()) { + String context = WordReadUtil.readWord(entry.getValue()); + List actionUserNameList = new ArrayList<>(); + actionUserNameList.add("陈恩明"); + actionUserNameList.add("武桂清"); + List victimUserNameList = new ArrayList<>(); + victimUserNameList.add("漫旭昌"); + victimUserNameList.add("杨学明"); + victimUserNameList.add("朱文泽"); + var list = modelMetricService.list(); + for (ModelMetric modelMetric : list) { + // 没有跑过的,才继续跑 + Long count = noteCheckRecordService.lambdaQuery().eq(NoteCheckRecord::getPersonName, entry.getKey()).eq(NoteCheckRecord::getMetricCode, modelMetric.getMetricCode()).count(); + if (count < 1) { + Map param = new HashMap<>(); + param.put("actionUserNameList", CollUtil.join(actionUserNameList, ";")); + param.put("victimUserNameList", CollUtil.join(victimUserNameList, ";")); + param.put("witnessNameList", "无"); + param.put("noteUserName", entry.getKey()); + param.put("context", context); + param.put("metricName", modelMetric.getMetricName()); + param.put("metricTrueDesc", modelMetric.getMetricTrueDesc()); + param.put("metricFalseDesc", modelMetric.getMetricFalseDesc()); + String format = StrUtil.format(template, param); + Message message = new UserMessage(format); + Prompt prompt = new Prompt(List.of(new SystemMessage("所有的回复以简体中文回答。请以step by step的方式进行。step1:理解笔录设计人员的身份信息;step2:根据笔录的内容分析案件之间的逻辑关系和关联;step3:根据给定的指标,提取出来可能涉及的笔录内容文本;step4:根据该笔录内容判断给定的指标是否满足。step5:根据要求的给定格式进行回复"), message)); + log.info("prompt:{}", prompt); + ChatResponse call = chatClient.call(prompt); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); + log.info(content); + MetricResultDTO metricResultDTO = JSONUtil.toBean(content, MetricResultDTO.class); + NoteCheckRecord noteCheckRecord = new NoteCheckRecord(); + noteCheckRecord.setPersonName(entry.getKey()); + noteCheckRecord.setNoteName(FileUtil.getName(entry.getValue())); + noteCheckRecord.setType(entry.getKey().contains("询问") ? "询问" : "讯问"); + noteCheckRecord.setMetricCode(modelMetric.getMetricCode()); + noteCheckRecord.setMetricName(modelMetric.getMetricName()); + noteCheckRecord.setResult(metricResultDTO.getResult()); + noteCheckRecord.setOriginalContext(metricResultDTO.getOriginalContext()); + noteCheckRecord.setReason(metricResultDTO.getReason()); + noteCheckRecordService.save(noteCheckRecord); + } + + } + } + + } + + /** + * 从word中读取笔录 + */ + + @GetMapping("runCheck") + public void runCheck() { + + +// List metricCodeList = ListUtil.list(false, "RZ010", "RZ019", "RZ020", "RZ022"); + // 行为人 + List actionUserNameList = ListUtil.list(false, "裴金禄"); + // 犯罪嫌疑人 + List suspectUserNameList = ListUtil.list(false, "裴金禄", "景涛", "李世怀", "万学宝"); + // 受害人 + List victimUserNameList = ListUtil.list(false, "董金才", "吕加国", "吕志仓"); + // 证人 + List witnessNameList = ListUtil.list(false, "白鹏", "丁建华", "雷建贵", "雷建明", "李泽懿", "王存良", "王开阔", "吴尚军", "杨正福", "叶魁伍", "赵景宝"); + // 获取目录下的所有笔录信息 + List files = FileUtil.loopFiles("/Users/flevance/Desktop/宁夏审讯大模型/裴金禄/行为人和受害人/"); + for (File file : files) { + // 只跑裴金禄的笔录 + log.info("开始分析:{}的笔录", file.getName()); + String context = WordReadUtil.readWord(file.getPath()); +// List list = modelMetricService.lambdaQuery().in(ModelMetric::getMetricCode, metricCodeList).list(); + List list = modelMetricService.list(); + for (ModelMetric modelMetric : list) { + + Map param = new HashMap<>(); + param.put("actionUserNameList", CollUtil.join(actionUserNameList, ";")); + param.put("suspectUserNameList", CollUtil.join(suspectUserNameList, ";")); + param.put("victimUserNameList", CollUtil.join(victimUserNameList, ";")); + param.put("witnessNameList", CollUtil.join(witnessNameList, ";")); + param.put("context", context); + param.put("metricName", modelMetric.getMetricName()); + param.put("metricTrueDesc", modelMetric.getMetricTrueDesc()); + param.put("metricFalseDesc", modelMetric.getMetricFalseDesc()); + String format = StrUtil.format(template, param); + List userMessageList = new ArrayList<>(); + log.info("开始提交分析,prompt长度为:{}", format.length()); + // 如果超过8000字,就进行截断,每次以6000字进行提交 + if (format.length() > 8000) { + log.info("分段提交"); + for (String s : StrUtil.split(format, 6000)) { + userMessageList.add(new UserMessage(s)); + userMessageList.add(new AssistantMessage("继续")); + } + userMessageList.remove(userMessageList.size() - 1); + } else { + userMessageList.add(new UserMessage(format)); + } + String systemPrompt = """ + 你是一个善于分析办案笔录的模型,能够根据办案笔录中的当事人的回答内容,实事求是的判断给定指标是否满足。注意,仅根据笔录进行分析,不要做笔录之外的推断。笔录内容可能比较长,可能分多次提交给你。 + """; + List messages = new ArrayList<>(List.of(new SystemMessage(systemPrompt))); + messages.addAll(userMessageList); + Prompt prompt = new Prompt(messages); + RunCheckThread runCheck = new RunCheckThread("裴金禄第五次",chatClient, noteCheckRecordService, prompt, file.getName(), format, systemPrompt, modelMetric, 0); + RunCheckThreadPool.chatExecutor.submit(runCheck); + } + } + } + + + @GetMapping("testLongText") + public void testLongText() { + StringBuilder stringBuilder = new StringBuilder(); + + BufferedReader utf8Reader = FileUtil.getUtf8Reader("/Users/flevance/Desktop/宁夏审讯大模型/了不起的盖茨比 .txt"); + utf8Reader.lines().forEach(stringBuilder::append); + String template = """ + 我现在给你一个小说,请你解析小说的内容: + --- + {context} + --- + 现在请你分析小说内容,讲讲第8章讲了什么内容,清晰的描述出来.请以中文进行回答.并以json的形式进行输出 + """; + String systemPrompt = """ + 你是一个善于归纳分析的大模型,我现在需要你来做小说内容提取。小说内容可能比较长,可能分多次提交给你。所有的回答都以中文的形式进行回答. + """; + Map param = new HashMap<>(); + log.info("大小是:{}", stringBuilder.length()); + param.put("context", stringBuilder.toString()); + String format = StrUtil.format(template, param); + List userMessageList = new ArrayList<>(); + for (String s : StrUtil.split(format, 6000)) { + userMessageList.add(new UserMessage(s)); + userMessageList.add(new AssistantMessage("继续")); + } + userMessageList.remove(userMessageList.size() - 1); + List messages = new ArrayList<>(List.of(new SystemMessage(systemPrompt))); + messages.addAll(userMessageList); + Prompt prompt = new Prompt(messages); + + ChatResponse call = chatClient.call(prompt); + Generation result = call.getResult(); + + String content = result.getOutput().getContent(); + log.info("分析的结果是:{}", content); + + } +} + + diff --git a/src/main/java/com/supervision/springaidemo/controller/ExampleChatController.java b/src/main/java/com/supervision/springaidemo/controller/ExampleChatController.java new file mode 100644 index 0000000..72b4ddd --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/ExampleChatController.java @@ -0,0 +1,256 @@ +package com.supervision.springaidemo.controller; + +import cn.hutool.core.io.FileUtil; +import com.supervision.police.domain.ModelRecordType; +import com.supervision.police.domain.NoteRecord; +import com.supervision.springaidemo.dto.QARecordNodeDTO; +import com.supervision.police.mapper.ModelRecordTypeMapper; +import com.supervision.police.mapper.NoteRecordMapper; +import com.supervision.police.service.ModelRecordTypeService; +import com.supervision.springaidemo.service.ModelMetricService; +import com.supervision.police.service.RecordService; +import com.supervision.police.service.NoteCheckRecordService; +import com.supervision.springaidemo.util.RecordRegexUtil; +import com.supervision.springaidemo.util.WordReadUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.annotations.Param; +import org.json.JSONObject; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StopWatch; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.File; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 目前这是效果最好的方案,暂时先用这个 + */ +@RestController +@Slf4j +@RequestMapping("exampleChat") +public class ExampleChatController { + + private final OllamaChatClient chatClient; + + @Autowired + private ModelMetricService modelMetricService; + + @Autowired + private NoteCheckRecordService noteCheckRecordService; + @Autowired + private ModelRecordTypeMapper modelRecordTypeMapper; + @Autowired + private NoteRecordMapper noteRecordMapper; + + @Autowired + public ExampleChatController(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + @Autowired + private RecordService recordService; + + @Autowired + private ModelRecordTypeService modelRecordTypeService; + + private static final String exampleTemplate = """ + 我们现在需要以step by step的方式进行笔录的指标分析工作,得到最终的结果并返回。 + + step1:分析笔录的内容; + 以下是笔录的内容: + --- + {context} + --- + + step2:现在给你指标以及指标的释义或例子可协助你参考: + 指标释义或例子及判断标准: + 指标名称:{metricName} + 我现在给你为true的例子可供参考:{example}; + 如果和例子这种情况相反或偏差较大则为false; + 如果笔录中,没有任何笔录内容涉及到该项指标,无法进行判断,则为empty。 + + step3:现在需要你根据上面提供的所有信息,尽可能实事求是完成判断: + 1.判断结论:true/false/empty + 2.得到结论的笔录原话:从笔录的对话中,得到该结论的原文(一定是摘抄的原文且为中文)。如果结论为true,则必须要有原文佐证! + 3.得到结论的原因:分析得出该结论的原因,需明确说明为什么得到该结论,需要参考例子的格式且为中文回复。如果结论为true/false,则必须有原因! + + step4:必须以json格式回复, JSON的value内容我给你的提示,在实际输出的时候不需要带上: + --- + {"result":"结论", "originalContext":"笔录对应原话","reason":"原因"} + --- + 好了,现在可以回复了! + """; + + @GetMapping("exampleChat") + public void exampleChat() { + File file = FileUtil.file("E:\\jc\\宁夏\\Fw_裴金禄\\裴金禄第一次.docx"); + String context = WordReadUtil.readWord(file.getPath()); + List qaList = RecordRegexUtil.recordRegex(context, "裴金禄"); + for (QARecordNodeDTO qa : qaList) { + NoteRecord noteRecord = new NoteRecord(); + noteRecord.setNoteName(file.getName()); + noteRecord.setPersonName("裴金禄"); + noteRecord.setQuestion(qa.getQuestion()); + noteRecord.setAnswer(qa.getAnswer()); + noteRecord.setCreateTime(new Date()); + +// if (qa.getAnswer().length() > 500) { +// continue; +// } + //根据提示词分析类型 并保存 +// String test = "你现在是一个笔录分析人员,请用四个字描述一下下述内容属于哪种类型的对话?"; + String test = "你是一个善于归纳分析问讯笔录的大模型,请用四个字描述下述内容属于哪种类型的对话?对话内容为:"; + String tip = "你的回答必须严格控制为四个字。"; + String example = "示例1:办案警官问:我们是中卫市公安局沙坡头区分局经侦大队的民警(出示工作证件),现依法对你进行讯问,你应当如实回答我们的提问,对与案件无关的问题,你有拒绝回答的权利。你听明白了吗? 张某答:听明白了。回复:{\"type\":\"权利义务\"}。" + + "示例2:办案警官问:你的个人情况?张某答:我叫裴金禄,男,1984年01月10日出生,藏族,大学文化,户籍所在地陕西省西安市雁塔区丈八四路6号7号楼1单元 2304室,现住陕西省西安市雁塔区丈八四路6号7号楼1单元 2304室,无业,居民身份证号码622326198401100090,联系电话15829319393。回复:{\"type\":\"个人情况\"}。" + + "示例3:办案警官问:你的家庭情况?张某答:我父亲叫:裴国智,今年:67岁,退休,电话:13519353723; 母亲:李金芬,今年:61岁,无业;我弟弟裴金生,今年: 34岁,在中石油运输公司上班。回复:{\"type\":\"家庭情况\"}。"; + List messages = new ArrayList<>(List.of(new SystemMessage(test + qa.getQuestion() + qa.getAnswer() + tip + example))); + Prompt prompt = new Prompt(messages); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); +// log.info("开始分析:"); + ChatResponse call = chatClient.call(prompt); + stopWatch.stop(); +// log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); +// log.info("问:{}, 答:{}", qa.getQuestion(), qa.getAnswer()); +// log.info("分析的结果是:{}", content); + JSONObject jsonObject = new JSONObject(content); + String type = jsonObject.getString("type").trim(); + System.out.println("问:"+qa.getQuestion()+"答:"+qa.getAnswer()); + System.out.println("分析的结果是:"+ type); + + //保存笔录 + noteRecord.setRecordType(type); + recordService.save(noteRecord); + + ModelRecordType exist = modelRecordTypeService.queryByName(type); + if (exist == null) { + ModelRecordType modelRecordType = new ModelRecordType(); + modelRecordType.setRecordType(type); + modelRecordTypeService.save(modelRecordType); + } + } + +// for (QARecordNodeDTO qaRecordNodeDTO : qaList) { +// // 只查入罪指标 +// List list = modelMetricService.lambdaQuery().likeRight(ModelMetric::getMetricCode, "RZ").list(); +// for (ModelMetric modelMetric : list) { +// String systemPrompt = """ +// 你是一个善于分析办案笔录的模型,能够根据办案笔录的回答内容,结合给定的例子,实事求是的判断给定指标是否满足。注意,仅根据笔录进行分析,不要做笔录之外的推断。笔录内容可能比较长,可能分多次提交给你。Think step by step +// """; +// List messages = new ArrayList<>(List.of(new SystemMessage(systemPrompt))); +// Map param = new HashMap<>(); +// param.put("context", qaRecordNodeDTO.toString()); +// param.put("metricName", modelMetric.getMetricName()); +// param.put("example", StrUtil.format(modelMetric.getExample(), MapUtil.of("action", "裴金禄"))); +// String format = StrUtil.format(exampleTemplate, param); +// List userMessageList = new ArrayList<>(); +// if (format.length() > 8000) { +// log.info("分段提交"); +// for (String s : StrUtil.split(format, 6000)) { +// userMessageList.add(new UserMessage(s)); +// userMessageList.add(new AssistantMessage("继续")); +// } +// userMessageList.remove(userMessageList.size() - 1); +// } else { +// userMessageList.add(new UserMessage(format)); +// } +// messages.addAll(userMessageList); +// +// RunCheckThread runCheck = new RunCheckThread("裴金禄尝试正则来做", chatClient, noteCheckRecordService, new Prompt(messages), FileUtil.getName(file), format, systemPrompt, modelMetric, 0); +// RunCheckThreadPool.chatExecutor.submit(runCheck); +// } +// } + + + + } + + @GetMapping("test") + public List test(@Param("test") String test) { + List list = new ArrayList<>(); + List messages = new ArrayList<>(List.of(new SystemMessage(test))); + Prompt prompt = new Prompt(messages); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + log.info("开始分析:"); + ChatResponse call = chatClient.call(prompt); + stopWatch.stop(); + log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + + String content = result.getOutput().getContent(); + log.info("分析的结果是:{}", content); + Map resultMap = new HashMap<>(); + resultMap.put("result", content); + list.add(resultMap); + return list; + } + + @GetMapping("queryRecordType") + public List queryRecordType() { + List types = modelRecordTypeMapper.selectList(null); + String allType = types.stream().map(ModelRecordType::getRecordType).collect(Collectors.joining(".")); + List list = noteRecordMapper.selectList(null); + for (NoteRecord record : list) { + record.setRecordType(""); + + String test = "你是一个善于总结问讯内容的大模型,请判断以下对话属于【" + allType + "】哪个分类?对话内容为:"; + String tip = "你的回答必须在所给范围内。"; + String example = "示例:办案警官问:你的家庭情况?答:裴金禄回答:我父亲叫:裴国智,今年:67岁,退休,电话:13519353723;母亲:李金芬,今年:61岁,无业;我弟弟裴金生,今年:34岁,在中石油运输公司上班。回复:{\"type\":\"家庭情况\"}。"; + List messages = new ArrayList<>(List.of(new SystemMessage(test + record.getQuestion() + record.getAnswer() + tip + example))); + Prompt prompt = new Prompt(messages); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); +// log.info("开始分析:"); + ChatResponse call = chatClient.call(prompt); + stopWatch.stop(); +// log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); +// log.info("问:{}, 答:{}", qa.getQuestion(), qa.getAnswer()); +// log.info("分析的结果是:{}", content); + System.out.println("问:"+record.getQuestion()+"答:"+record.getAnswer()); + System.out.println("分析的结果是:"+ content); + record.setRecordType(content); + } + return list; + } + + @GetMapping("test1") + public void test2(@Param("id") String id) { + NoteRecord noteRecord = recordService.getById(id); + String question = noteRecord.getQuestion(); + String answer = noteRecord.getAnswer(); + String test = "请从以下对话中提取所有关于" + noteRecord.getRecordType() + "的所有三元组"; +// String test = "请从以下对话中提取所有三元组,对话内容为:"; + String example = "。示例:办案警官问:你的家庭情况?答:裴金禄回答:我父亲叫:裴国智,今年:67岁,电话:13519353723;母亲:李金芬,今年:61岁;我弟弟裴金生,今年:34岁。" + + "回复:{\"result\":[{\"主体\":\"裴金禄\",\"关系\":\"父子\",\"客体\":\"裴国智\"},{\"主体\":\"裴金禄\",\"关系\":\"母子\",\"客体\":\"李金芬\"},{\"主体\":\"裴金禄\",\"关系\":\"兄弟\",\"客体\":\"裴金生\"},{\"主体\":\"裴国智\",\"关系\":\"年龄\",\"客体\":67},{\"主体\":\"李金芬\",\"关系\":\"年龄\",\"客体\":61},{\"主体\":\"裴金生\",\"关系\":\"年龄\",\"客体\":34}]}。"; + String a = "你是一个问讯笔录分析师,请分析以下内容中所有规定的三元组信息并补充完整,规定的三元组信息如下:[{startNodeType:'Person',entity:'',endNodeType:'Person',property:'',value:'' },{startNodeType:'Person',entity:'',endNodeType:'Organ',property:'',value:''}],要求返回格式{result:[三元组信息]}。"; + List messages = new ArrayList<>(List.of(new SystemMessage(a + question+answer))); +// List messages = new ArrayList<>(List.of(new SystemMessage(test + question+answer+example))); + Prompt prompt = new Prompt(messages); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + log.info("开始分析:"); + ChatResponse call = chatClient.call(prompt); + stopWatch.stop(); + log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + + String content = result.getOutput().getContent(); + log.info("分析的结果是:{}", content); + } + +} diff --git a/src/main/java/com/supervision/springaidemo/controller/NewTestController.java b/src/main/java/com/supervision/springaidemo/controller/NewTestController.java new file mode 100644 index 0000000..0c9bf62 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/NewTestController.java @@ -0,0 +1,106 @@ +package com.supervision.springaidemo.controller; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import com.supervision.springaidemo.domain.ModelMetric; +import com.supervision.springaidemo.dto.QARecordNodeDTO; +import com.supervision.springaidemo.service.ModelMetricService; +import com.supervision.police.service.NoteCheckRecordService; +import com.supervision.springaidemo.thread.RunCheckThread; +import com.supervision.springaidemo.thread.RunCheckThreadPool; +import com.supervision.springaidemo.util.RecordRegexUtil; +import com.supervision.springaidemo.util.WordReadUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 自己测试的方案,计划改成2阶段的形式 + * 第一阶段,首先根据提示词,从原文中获取笔录的内容(首先让大模型从原文中提取出来可能涉及的内容) + * 然后再尝试跑结果 + */ +@RestController +@Slf4j +@RequestMapping("newTestChat") +public class NewTestController { + + private final OllamaChatClient chatClient; + + @Autowired + private ModelMetricService modelMetricService; + + @Autowired + private NoteCheckRecordService noteCheckRecordService; + + @Autowired + public NewTestController(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + private static final String template = """ + 请根据以下关键词,从笔录中找到相关的原文段落: + --- + 关键词1:财物去向 + --- + 笔录内容如下: + --- + {context} + --- + 请判断笔录和关键词是否可能有关联,如有关联,则对这段话进行总结 + 必须以json数组格式回复 + --- + {"match":"true/false(相关回复true,不相关回复false)","summary":"如果有关联,则对该笔录进行总结"} + --- + 好了,现在可以回复了。不要胡编乱造!无中生有! + """; + + + @GetMapping("newTestChat") + public void newTestChat() { + // 只查入罪指标 + ModelMetric modelMetric = modelMetricService.lambdaQuery().eq(ModelMetric::getMetricCode, "RZ007").one(); + File file = FileUtil.file("/Users/flevance/Desktop/宁夏审讯大模型/裴金禄/行为人和受害人/裴金禄第一次.docx"); + String context = WordReadUtil.readWord(file.getPath()); + List qaList = RecordRegexUtil.recordRegex(context, "裴金禄"); + for (QARecordNodeDTO qaRecordNodeDTO : qaList) { + String systemPrompt = """ + 你是一个善于内容提取的模型,能够根据给定关键字从原文中找到可能匹配的原文段落。 + """; + List messages = new ArrayList<>(List.of(new SystemMessage(systemPrompt))); + Map param = new HashMap<>(); + param.put("context", qaRecordNodeDTO.toString()); + String format = StrUtil.format(template, param); + List userMessageList = new ArrayList<>(); + if (format.length() > 8000) { + log.info("分段提交"); + for (String s : StrUtil.split(format, 6000)) { + userMessageList.add(new UserMessage(s)); + userMessageList.add(new AssistantMessage("继续")); + } + userMessageList.remove(userMessageList.size() - 1); + } else { + userMessageList.add(new UserMessage(format)); + } + messages.addAll(userMessageList); + + RunCheckThread runCheck = new RunCheckThread("尝试分段提取-第一段找相似", chatClient, noteCheckRecordService, new Prompt(messages), FileUtil.getName(file), format, systemPrompt, modelMetric, 5); + RunCheckThreadPool.chatExecutor.submit(runCheck); + } + } + + +} diff --git a/src/main/java/com/supervision/springaidemo/controller/RzChatController.java b/src/main/java/com/supervision/springaidemo/controller/RzChatController.java new file mode 100644 index 0000000..f16ebdc --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/RzChatController.java @@ -0,0 +1,118 @@ +package com.supervision.springaidemo.controller; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import com.supervision.springaidemo.domain.ModelMetric; +import com.supervision.springaidemo.service.ModelMetricService; +import com.supervision.police.service.NoteCheckRecordService; +import com.supervision.springaidemo.thread.RunCheckThread; +import com.supervision.springaidemo.thread.RunCheckThreadPool; +import com.supervision.springaidemo.util.WordReadUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 入罪指标controller + */ +@RestController +@Slf4j +@RequestMapping("rzChat") +public class RzChatController { + + private static final String step1Template = """ + 我们现在需要以step by step的方式进行笔录的指标分析工作,得到最终的结果并返回。 + + step1:分析笔录的内容; + 以下是笔录的内容,笔录中"问"是办案警官问,"答"是{noteUserName}回答: + --- + {context} + --- + + step2:现在给你指标以及指标的释义或例子: + 指标释义或例子及判断标准: + 如满足:{metricDetailTemplate},则为true; + 如果不满足::{metricDetailTemplate},则为false; + 如果笔录中,没有任何笔录内容涉及到该项指标,无法进行判断,则为empty。 + + step3:现在需要你根据上面提供的所有信息,尽可能实事求是完成判断: + 1.判断结论:true/false/empty + 2.得到结论的笔录原话:从笔录的对话中,得到该结论的原文(一定是摘抄的原文且为中文)。如果结论为true,则必须要有原文佐证! + 3.得到结论的原因:分析得出该结论的原因,需明确说明为什么得到该结论,需要实事求是且为中文回复。如果结论为true/false,则必须有原因! + + step4:必须以json格式回复, JSON的value内容我给你的提示,在实际输出的时候不需要带上: + --- + {"result":"结论", "originalContext":"笔录对应原话","reason":"原因"} + --- + 好了,现在可以回复了! + """; + + private final OllamaChatClient chatClient; + + @Autowired + private ModelMetricService modelMetricService; + + @Autowired + private NoteCheckRecordService noteCheckRecordService; + + @Autowired + public RzChatController(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + @GetMapping("extract") + public void extract() throws InterruptedException { + List files = FileUtil.loopFiles("/Users/flevance/Desktop/宁夏审讯大模型/裴金禄/行为人和受害人/"); + for (File file : files) { + String context = WordReadUtil.readWord(file.getPath()); + // 只查入罪指标 + List list = modelMetricService.lambdaQuery().likeRight(ModelMetric::getMetricCode, "RZ").list(); + for (ModelMetric modelMetric : list) { + String systemPrompt = """ + 你是一个善于分析办案笔录的模型,能够根据办案笔录的回答内容,实事求是的判断给定指标是否满足。注意,仅根据笔录进行分析,不要做笔录之外的推断。笔录内容可能比较长,可能分多次提交给你。 + """; + List messages = new ArrayList<>(List.of(new SystemMessage(systemPrompt))); + Map param = new HashMap<>(); + param.put("metricDetailTemplate", StrUtil.format(modelMetric.getMetricDetailTemplate(), MapUtil.of("action", "裴金禄"))); + param.put("noteUserName", "裴金禄"); + param.put("context", context); + String format = StrUtil.format(step1Template, param); + List userMessageList = new ArrayList<>(); + if (format.length() > 8000) { + log.info("分段提交"); + for (String s : StrUtil.split(format, 6000)) { + userMessageList.add(new UserMessage(s)); + userMessageList.add(new AssistantMessage("继续")); + } + userMessageList.remove(userMessageList.size() - 1); + } else { + userMessageList.add(new UserMessage(format)); + } + messages.addAll(userMessageList); + + RunCheckThread runCheck = new RunCheckThread("裴金禄尝试通过直接定义模板", chatClient, noteCheckRecordService, new Prompt(messages), FileUtil.getName(file), format, systemPrompt, modelMetric, 0); + RunCheckThreadPool.chatExecutor.submit(runCheck); + + + } + } + + + } + +} diff --git a/src/main/java/com/supervision/springaidemo/controller/SimilarityController.java b/src/main/java/com/supervision/springaidemo/controller/SimilarityController.java new file mode 100644 index 0000000..bceaece --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/SimilarityController.java @@ -0,0 +1,146 @@ +package com.supervision.springaidemo.controller; + +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.json.JSONUtil; +import cn.hutool.poi.excel.ExcelReader; +import cn.hutool.poi.excel.ExcelUtil; +import cn.hutool.poi.excel.ExcelWriter; +import com.supervision.springaidemo.domain.VpAskTemplateQuestionLibrary; +import com.supervision.springaidemo.domain.VpCommonDic; +import com.supervision.springaidemo.service.VpAskTemplateQuestionLibraryService; +import com.supervision.springaidemo.service.VpCommonDicService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.document.Document; +import org.springframework.ai.embedding.EmbeddingClient; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.ollama.OllamaEmbeddingClient; +import org.springframework.ai.ollama.api.OllamaOptions; +import org.springframework.ai.vectorstore.SimpleVectorStore; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.File; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +@RequestMapping("similarity") +@RestController +public class SimilarityController { + + private final SimpleVectorStore store; + + + private final OllamaChatClient chatClient; + + @Autowired + private VpCommonDicService vpCommonDicService; + + @Autowired + private VpAskTemplateQuestionLibraryService libraryService; + + @Autowired + public SimilarityController(OllamaEmbeddingClient ollamaEmbeddingClient, OllamaChatClient chatClient) { + store = new SimpleVectorStore(ollamaEmbeddingClient.withDefaultOptions(OllamaOptions.create().withModel("llama3-chinese:8b"))); + this.chatClient = chatClient; +// File file = FileUtil.file("/Users/flevance/Java/spring-ai-demo/spring-ai-demo/data/storeData.json"); +// if (FileUtil.isNotEmpty(file)) { +// store.load(file); +// } + } + + @GetMapping("init") + public void init() { + // 从数据库中加载向量数据 + List list = libraryService.lambdaQuery().list(); + for (VpAskTemplateQuestionLibrary vpAskTemplateQuestionLibrary : list) { + String questionJsonStr = vpAskTemplateQuestionLibrary.getQuestion(); + List questionList = JSONUtil.toList(questionJsonStr, String.class); + questionList.add(vpAskTemplateQuestionLibrary.getDescription()); + for (String question : questionList) { + Map meta = MapUtil.of("dictId", vpAskTemplateQuestionLibrary.getDictId()); + meta.put("id", vpAskTemplateQuestionLibrary.getId()); + Document document = new Document(question, meta); + store.add(ListUtil.of(document)); + log.info("{}已添加到向量数据库", question); + } + } + log.info("向量化完成"); + // 加载完成之后,保存到本地 + store.save(FileUtil.newFile("/Users/flevance/Java/spring-ai-demo/spring-ai-demo/data/storeData.json")); + log.info("保存完成"); + } + + @GetMapping("similarity") + public void similarity(String userQuestion) { + List documents = store.similaritySearch(userQuestion); + for (Document document : documents) { + log.info("{}", document.getContent()); + } + } + + @GetMapping("itemCheck") + public void itemCheck() { + File file = FileUtil.file("/Users/flevance/Desktop/虚拟病人/副本副本医生临床问诊问题收集v1.xlsx"); + ExcelReader reader = ExcelUtil.getReader(file, 1); + ExcelWriter writer = ExcelUtil.getWriter(file, "match"); + List list = vpCommonDicService.lambdaQuery().like(VpCommonDic::getNameZhPath, "/").eq(VpCommonDic::getGroupCode, "AQT").list(); + Set databaseExistSet = new HashSet<>(); + for (VpCommonDic vpCommonDic : list) { + databaseExistSet.add(vpCommonDic.getNameZhPath()); + } + List> objects = reader.read(1); + for (int i = 0; i < objects.size(); i++) { + List list1 = objects.get(i); + String s = (String) list1.get(0); + String s1 = (String) list1.get(1); + // 如果不存在,则记录 + if (!databaseExistSet.contains(s + "/" + s1)) { + writer.writeCellValue(1, i + 1, "不存在"); + } else { + writer.writeCellValue(1, i + 1, "存在"); + } + } + writer.flush(); + + } + + @GetMapping("similarityBatch") + public void similarityBatch() { + init(); + Map dicMap = vpCommonDicService.list().stream().collect(Collectors.toMap(VpCommonDic::getId, Function.identity())); + // 从Excel中获取数据 + File file = FileUtil.file("/Users/flevance/Desktop/虚拟病人/副本副本医生临床问诊问题收集v1.xlsx"); + ExcelReader reader = ExcelUtil.getReader(file, 2); + ExcelWriter writer = ExcelUtil.getWriter(file, "result"); + + List objects = reader.readColumn(2, 1); + for (int i = 0; i < objects.size(); i++) { + int rowIndex = i + 1; + String question = objects.get(i).toString(); + try { + List documents = store.similaritySearch(question); + Optional first = documents.stream().findFirst(); + if (first.isPresent()) { + Map meta = first.get().getMetadata(); + String dictId = meta.get("dictId").toString(); + VpCommonDic vpCommonDic = dicMap.get(Long.parseLong(dictId)); + writer.writeCellValue(8, rowIndex, question); + writer.writeCellValue(9, rowIndex, ""); + writer.writeCellValue(10, rowIndex, vpCommonDic.getNameZhPath()); + writer.writeCellValue(11, rowIndex, dictId); + } + } catch (Exception e) { + log.error("出现错误", e); + } + log.info("{}匹配完成.", question); + } + writer.flush(); + + } +} diff --git a/src/main/java/com/supervision/springaidemo/controller/SimilarityQuestionController.java b/src/main/java/com/supervision/springaidemo/controller/SimilarityQuestionController.java new file mode 100644 index 0000000..c176a14 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/SimilarityQuestionController.java @@ -0,0 +1,44 @@ +package com.supervision.springaidemo.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@Slf4j +@RequestMapping("question") +public class SimilarityQuestionController { + + private static final String template = """ + 假设你现在是一个医生,现在假设你在问诊,如果你想问用户:你什么时候发现问题的? + 请你给出这种问句10种相似的问法以扩充语料,要求扩充语料和源问题相似度很高以满足向量匹配的需求,且符合真实场景医生的询问方式 + """; + + + private final OllamaChatClient chatClient; + + @Autowired + public SimilarityQuestionController(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + @GetMapping("test") + public void test() { + Prompt prompt = new Prompt(List.of(new UserMessage(template))); + ChatResponse call = chatClient.call(prompt); + Generation result = call.getResult(); + + String content = result.getOutput().getContent(); + log.info("结果是:{}", content); + } + +} diff --git a/src/main/java/com/supervision/springaidemo/controller/VPTestController.java b/src/main/java/com/supervision/springaidemo/controller/VPTestController.java new file mode 100644 index 0000000..2ec2e04 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/VPTestController.java @@ -0,0 +1,83 @@ +package com.supervision.springaidemo.controller; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.supervision.springaidemo.dto.AnswerDTO; +import com.supervision.springaidemo.dto.GlobalResult; +import com.supervision.springaidemo.util.TtsUtil; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * 测试如何避免出现答非所问 + */ +@RequestMapping("vp-test") +@RestController +public class VPTestController { + + private final OllamaChatClient chatClient; + + + // 使用多线程进行提交 + + + @Autowired + public VPTestController(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + public static final String userPromptTemplate = """ + 现在希望你从预设的问题中,找到与给定问题的意图最匹配的项,以避免出现答非所问 + --- + 给定问题:{userQuestion} + --- + 预设问题1:{dataBaseQuestion1},问题ID:1761963909201268731 + 预设问题2:{dataBaseQuestion2},问题ID:1761963909201268732 + 预设问题3:{dataBaseQuestion3},问题ID:1761963909201268733 + 预设问题4:{dataBaseQuestion4},问题ID:1761963909201268734 + 预设问题5:{dataBaseQuestion5},问题ID:1761963909201268735 + --- + 回复格式为json:{"id":"对应的问题ID","question":"匹配到的预设问题"} + """; + + + +// private static final String systemPrompt = """ +// 你现在扮演一个医生,以医生的角度从预设问题列表中找到与给定问题最匹配的一项 +// """; + + @GetMapping("test") + public String test(String userQuestion) { + List messageHistoryList = new ArrayList<>(); +// messageHistoryList.add(new SystemMessage(systemPrompt)); + HashMap map = new HashMap<>(); + map.put("userQuestion", userQuestion); + map.put("dataBaseQuestion1", "您有什么症状?"); + map.put("dataBaseQuestion2", "您有什么不舒服的?"); + map.put("dataBaseQuestion3", "您是否有腹痛?"); + map.put("dataBaseQuestion4", "您还有什么不舒服的?"); + map.put("dataBaseQuestion5", "您还有其他什么症状吗?"); + StrUtil.format(userPromptTemplate, map); + messageHistoryList.add(new UserMessage(StrUtil.format(userPromptTemplate, map))); + Prompt prompt = new Prompt(messageHistoryList); + ChatResponse call = chatClient.call(prompt); + Generation result = call.getResult(); + return result.getOutput().getContent(); + } + +} diff --git a/src/main/java/com/supervision/springaidemo/controller/VirtualPatientTestController.java b/src/main/java/com/supervision/springaidemo/controller/VirtualPatientTestController.java new file mode 100644 index 0000000..0538042 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/controller/VirtualPatientTestController.java @@ -0,0 +1,90 @@ +package com.supervision.springaidemo.controller; + +import cn.hutool.json.JSONUtil; +import com.supervision.springaidemo.dto.AnswerDTO; +import com.supervision.springaidemo.dto.GlobalResult; +import com.supervision.springaidemo.util.TtsUtil; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +@RequestMapping("virtual-patient") +@RestController +public class VirtualPatientTestController { + + private final OllamaChatClient chatClient; + + + // 使用多线程进行提交 + + + @Autowired + public VirtualPatientTestController(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + public static final String userPromptTemplate = """ + 预设病例的基本情况如下: + --- + 名字:xxx + 年龄:xxx + 性别:女 + 主诉:头疼,发烧。 + 居住地:山东。 + 职业:学生 + 饮食:情况良好,胃口很大,总是感到饥饿,其他方面正常。 + 大小便:小便正常,但每天有大约3次稀便。 + 伴随症状:包括手抖、怕热、容易出汗,虽然胃口很好,吃很多却总是觉得饿,同时感到紧张、容易发脾气,经常拉肚子,体重有所下降。 + --- + 回复格式为json:{"answer":"根据病例情况回复的内容"} + """; + + private static final String systemPrompt = """ + 我们现在来进行一个角色扮演连续对话场景。 + 你现在扮演一个病人的角色(小樊),我来扮演医生,我们进行模拟问诊。 + 我会给你设定病人的基本情况,你根据给定病人的基本信息进行回复我。 + 如果参考信息中不能回答医生的问题,则回复'我不知道/没注意/不清楚'",所有问话都必须给回复! + 如果医生说'你好'等礼貌用语,你就回复'你好,医生'!!! + """; + + private static final List messageHistoryList = new ArrayList<>(); + + static { + messageHistoryList.add(new SystemMessage(systemPrompt)); + messageHistoryList.add(new UserMessage(userPromptTemplate)); + messageHistoryList.add(new AssistantMessage("好的,已了解我要扮演病人的基本情况。已准备好对话了。")); + } + + @GetMapping("talk") + public String talk(String question) { + messageHistoryList.add(new UserMessage(question)); + Prompt prompt = new Prompt(messageHistoryList); + ChatResponse call = chatClient.call(prompt); + Generation result = call.getResult(); + String content = result.getOutput().getContent(); + messageHistoryList.add(new AssistantMessage(content)); + return content; + } + + @GetMapping("chatVoice") + public GlobalResult chatVoice(String question){ + String talk = talk(question); + AnswerDTO answer = JSONUtil.toBean(talk, AnswerDTO.class); + String answerBase64 = TtsUtil.ttsTransform(answer.getAnswer()); + answer.setAnswerBase64(answerBase64); + return GlobalResult.ok(answer); + } + +} diff --git a/src/main/java/com/supervision/springaidemo/domain/ModelMetric.java b/src/main/java/com/supervision/springaidemo/domain/ModelMetric.java new file mode 100644 index 0000000..e3e8de8 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/domain/ModelMetric.java @@ -0,0 +1,76 @@ +package com.supervision.springaidemo.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +import lombok.Data; + +/** + * @TableName model_metric + */ +@TableName(value = "model_metric") +@Data +public class ModelMetric implements Serializable { + /** + * 主键 + */ + @TableId + private String id; + + /** + * 指标编码 + */ + private String metricCode; + + /** + * 指标ID + */ + private Integer metricId; + + /** + * 指标名称 + */ + private String metricName; + + /** + * 模型详情模板,一个新的尝试 + */ + private String metricDetailTemplate; + + /** + * 通过例子来做,钱院长的建议,可以尝试一下 + */ + private String example; + + /** + * 判定符合的描述 + */ + private String metricTrueDesc; + + /** + * 判定为不符合的原因 + */ + private String metricFalseDesc; + + /** + * 指标详细描述 + */ + private String metricDesc; + + /** + * 指标类型 0共性指标 1入罪指标 2出罪指标 + */ + private Integer metricType; + + /** + * 提示词模板 + */ + private String promptTemplate; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/supervision/springaidemo/domain/ModelMetricExample.java b/src/main/java/com/supervision/springaidemo/domain/ModelMetricExample.java new file mode 100644 index 0000000..0e0442b --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/domain/ModelMetricExample.java @@ -0,0 +1,35 @@ +package com.supervision.springaidemo.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; + +/** + * 指标例子 + * @TableName model_metric_example + */ +@TableName(value ="model_metric_example") +@Data +public class ModelMetricExample implements Serializable { + /** + * 主键 + */ + @TableId + private String id; + + /** + * 编码 + */ + private String metricCode; + + /** + * 例子内容 + */ + private String example; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/supervision/springaidemo/domain/NoteCheckRecord.java b/src/main/java/com/supervision/springaidemo/domain/NoteCheckRecord.java new file mode 100644 index 0000000..b8fce5b --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/domain/NoteCheckRecord.java @@ -0,0 +1,83 @@ +package com.supervision.springaidemo.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +import lombok.Data; + +/** + * 案件执行验证结果 + * + * @TableName note_check_record + */ +@TableName(value = "note_check_record") +@Data +public class NoteCheckRecord implements Serializable { + /** + * 主键ID + */ + @TableId + private String id; + + /** + * 案件名称 + */ + private String caseName; + + /** + * 人员名称 + */ + private String personName; + + /** + * 笔录名称 + */ + private String noteName; + + /** + * 询问/讯问 + */ + private String type; + + /** + * 指标编码 + */ + private String metricCode; + + /** + * 指标名称 + */ + private String metricName; + + /** + * 系统提示词 + */ + private String systemPrompt; + + /** + * 提示词内容 + */ + private String prompt; + + /** + * 结论 + */ + private String result; + + /** + * 笔录原话 + */ + private String originalContext; + + /** + * 分析的原因 + */ + private String reason; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/supervision/springaidemo/domain/VpAskTemplateQuestionLibrary.java b/src/main/java/com/supervision/springaidemo/domain/VpAskTemplateQuestionLibrary.java new file mode 100644 index 0000000..62562cc --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/domain/VpAskTemplateQuestionLibrary.java @@ -0,0 +1,81 @@ +package com.supervision.springaidemo.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 诊断问询意图问题库 + * @TableName vp_ask_template_question_library + */ +@TableName(value ="vp_ask_template_question_library") +@Data +public class VpAskTemplateQuestionLibrary implements Serializable { + /** + * 主键 + */ + @TableId + private String id; + + /** + * 字典值ID(关联common_dict表ID) + */ + private Long dictId; + + /** + * 编码 + */ + private String code; + + /** + * 中文注释 用户设置的问题 + */ + private String description; + + /** + * 问题列表 由用户传入的问题生成的问题列表 + */ + private String question; + + /** + * 默认回答编码 + */ + private String defaultAnswerCode; + + /** + * 默认问题的回答 + */ + private String defaultAnswer; + + /** + * 默认回答资源id + */ + private String defaultAnswerResourceId; + + /** + * 创建人ID + */ + private String createUserId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新人 + */ + private String updateUserId; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/supervision/springaidemo/domain/VpCommonDic.java b/src/main/java/com/supervision/springaidemo/domain/VpCommonDic.java new file mode 100644 index 0000000..f11b6ec --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/domain/VpCommonDic.java @@ -0,0 +1,86 @@ +package com.supervision.springaidemo.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 通用字典表 + * @TableName vp_common_dic + */ +@TableName(value ="vp_common_dic") +@Data +public class VpCommonDic implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 字段码值 + */ + private String code; + + /** + * 中文名 + */ + private String nameZh; + + /** + * 英文名 + */ + private String nameEn; + + /** + * 分组code + */ + private String groupCode; + + /** + * 父级id + */ + private Long parentId; + + /** + * 优先级,用来做排序等操作 + */ + private Integer priority; + + /** + * 中文路径 + */ + private String nameZhPath; + + /** + * 说明 + */ + private String description; + + /** + * + */ + private String createUserId; + + /** + * + */ + private Date createTime; + + /** + * + */ + private String updateUserId; + + /** + * + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/supervision/springaidemo/dto/AnswerDTO.java b/src/main/java/com/supervision/springaidemo/dto/AnswerDTO.java new file mode 100644 index 0000000..9e45c9a --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/AnswerDTO.java @@ -0,0 +1,11 @@ +package com.supervision.springaidemo.dto; + +import lombok.Data; + +@Data +public class AnswerDTO { + + private String answer; + + private String answerBase64; +} diff --git a/src/main/java/com/supervision/springaidemo/dto/GlobalResult.java b/src/main/java/com/supervision/springaidemo/dto/GlobalResult.java new file mode 100644 index 0000000..643fe6a --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/GlobalResult.java @@ -0,0 +1,45 @@ +package com.supervision.springaidemo.dto; + +import lombok.Data; +import org.springframework.http.HttpStatus; + +@Data +public class GlobalResult { + + private int code = 200; + + private String msg = "success"; + + private T data; + + + public static GlobalResult ok() { + return ok(null); + } + + public static GlobalResult ok(T data) { + GlobalResult globalResult = new GlobalResult<>(); + globalResult.setData(data); + return globalResult; + } + + public static GlobalResult ok(T data, String message) { + GlobalResult globalResult = new GlobalResult<>(); + globalResult.setMsg(message); + globalResult.setData(data); + return globalResult; + } + + public static GlobalResult error(String msg) { + return error(HttpStatus.INTERNAL_SERVER_ERROR.value(), null, msg); + } + + + public static GlobalResult error(int code, T data, String msg) { + GlobalResult globalResult = new GlobalResult<>(); + globalResult.setCode(code); + globalResult.setData(data); + globalResult.setMsg(msg); + return globalResult; + } +} diff --git a/src/main/java/com/supervision/springaidemo/dto/MetricResultDTO.java b/src/main/java/com/supervision/springaidemo/dto/MetricResultDTO.java new file mode 100644 index 0000000..11f6644 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/MetricResultDTO.java @@ -0,0 +1,13 @@ +package com.supervision.springaidemo.dto; + +import lombok.Data; + +@Data +public class MetricResultDTO { + + private String result; + + private String originalContext; + + private String reason; +} diff --git a/src/main/java/com/supervision/springaidemo/dto/QARecordNodeDTO.java b/src/main/java/com/supervision/springaidemo/dto/QARecordNodeDTO.java new file mode 100644 index 0000000..f35175b --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/QARecordNodeDTO.java @@ -0,0 +1,28 @@ +package com.supervision.springaidemo.dto; + +import lombok.Data; + +/** + * 问答对对象 + */ +@Data +public class QARecordNodeDTO { + + private String question; + + private String answer; + + public QARecordNodeDTO() { + } + + public QARecordNodeDTO(String question, String answer) { + this.question = question; + this.answer = answer; + } + + @Override + public String toString() { + return question + "\r\n" + answer; + } + +} diff --git a/src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/AsrReqDTO.java b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/AsrReqDTO.java new file mode 100644 index 0000000..eceff42 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/AsrReqDTO.java @@ -0,0 +1,21 @@ +package com.supervision.springaidemo.dto.paddlespeech.req; + +import lombok.Data; + +@Data +public class AsrReqDTO { + + private final String audio; + + private final String audio_format = "wav"; + + private final Integer sample_rate = 16000; + + private final String lang = "zh_cn"; + + private final Integer punc = 0; + + public AsrReqDTO(String audio) { + this.audio = audio; + } +} diff --git a/src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/TtsReqDTO.java b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/TtsReqDTO.java new file mode 100644 index 0000000..834b1e5 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/req/TtsReqDTO.java @@ -0,0 +1,23 @@ +package com.supervision.springaidemo.dto.paddlespeech.req; + +import lombok.Data; + +@Data +public class TtsReqDTO { + + private final String text; + + private final Integer spk_id = 0; + + private final Double speed = 1.0; + + private final Double volume = 1.0; + + private final Integer sample_rate = 16000; + + private final String save_path = "./tts.wav"; + + public TtsReqDTO(String text) { + this.text = text; + } +} diff --git a/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/AsrResultDTO.java b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/AsrResultDTO.java new file mode 100644 index 0000000..317f917 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/AsrResultDTO.java @@ -0,0 +1,10 @@ +package com.supervision.springaidemo.dto.paddlespeech.res; + +import lombok.Data; + +@Data +public class AsrResultDTO { + + private String transcription; + +} diff --git a/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/PaddleSpeechResDTO.java b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/PaddleSpeechResDTO.java new file mode 100644 index 0000000..a242ec0 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/PaddleSpeechResDTO.java @@ -0,0 +1,15 @@ +package com.supervision.springaidemo.dto.paddlespeech.res; + +import lombok.Data; + +@Data +public class PaddleSpeechResDTO { + + private Boolean success; + + private Integer code; + + private Object message; + + private T result; +} diff --git a/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/TtsResultDTO.java b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/TtsResultDTO.java new file mode 100644 index 0000000..8012d25 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/dto/paddlespeech/res/TtsResultDTO.java @@ -0,0 +1,23 @@ +package com.supervision.springaidemo.dto.paddlespeech.res; + +import lombok.Data; + +@Data +public class TtsResultDTO { + + private String lang; + + private String spk_id; + + private String speed; + + private String volume; + + private String sample_rate; + + private String duration; + + private String save_path; + + private String audio; +} diff --git a/src/main/java/com/supervision/springaidemo/mapper/ModelMetricExampleMapper.java b/src/main/java/com/supervision/springaidemo/mapper/ModelMetricExampleMapper.java new file mode 100644 index 0000000..21fec21 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/mapper/ModelMetricExampleMapper.java @@ -0,0 +1,18 @@ +package com.supervision.springaidemo.mapper; + +import com.supervision.springaidemo.domain.ModelMetricExample; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author flevance +* @description 针对表【model_metric_example(指标例子)】的数据库操作Mapper +* @createDate 2024-05-17 11:49:41 +* @Entity com.supervision.springaidemo.domain.ModelMetricExample +*/ +public interface ModelMetricExampleMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/mapper/ModelMetricMapper.java b/src/main/java/com/supervision/springaidemo/mapper/ModelMetricMapper.java new file mode 100644 index 0000000..8efa7a7 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/mapper/ModelMetricMapper.java @@ -0,0 +1,18 @@ +package com.supervision.springaidemo.mapper; + +import com.supervision.springaidemo.domain.ModelMetric; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author flevance +* @description 针对表【model_metric】的数据库操作Mapper +* @createDate 2024-05-10 16:40:18 +* @Entity com.supervision.domain.ModelMetric +*/ +public interface ModelMetricMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/mapper/VpAskTemplateQuestionLibraryMapper.java b/src/main/java/com/supervision/springaidemo/mapper/VpAskTemplateQuestionLibraryMapper.java new file mode 100644 index 0000000..ca65ddc --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/mapper/VpAskTemplateQuestionLibraryMapper.java @@ -0,0 +1,18 @@ +package com.supervision.springaidemo.mapper; + +import com.supervision.springaidemo.domain.VpAskTemplateQuestionLibrary; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author flevance +* @description 针对表【vp_ask_template_question_library(诊断问询意图问题库)】的数据库操作Mapper +* @createDate 2024-05-22 17:40:02 +* @Entity com.supervision.springaidemo.domain.VpAskTemplateQuestionLibrary +*/ +public interface VpAskTemplateQuestionLibraryMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/mapper/VpCommonDicMapper.java b/src/main/java/com/supervision/springaidemo/mapper/VpCommonDicMapper.java new file mode 100644 index 0000000..265b40c --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/mapper/VpCommonDicMapper.java @@ -0,0 +1,18 @@ +package com.supervision.springaidemo.mapper; + +import com.supervision.springaidemo.domain.VpCommonDic; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author flevance +* @description 针对表【vp_common_dic(通用字典表)】的数据库操作Mapper +* @createDate 2024-05-23 10:24:49 +* @Entity com.supervision.springaidemo.domain.VpCommonDic +*/ +public interface VpCommonDicMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/service/ModelMetricExampleService.java b/src/main/java/com/supervision/springaidemo/service/ModelMetricExampleService.java new file mode 100644 index 0000000..25287bc --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/ModelMetricExampleService.java @@ -0,0 +1,13 @@ +package com.supervision.springaidemo.service; + +import com.supervision.springaidemo.domain.ModelMetricExample; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author flevance +* @description 针对表【model_metric_example(指标例子)】的数据库操作Service +* @createDate 2024-05-17 11:49:41 +*/ +public interface ModelMetricExampleService extends IService { + +} diff --git a/src/main/java/com/supervision/springaidemo/service/ModelMetricService.java b/src/main/java/com/supervision/springaidemo/service/ModelMetricService.java new file mode 100644 index 0000000..7ea6ea2 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/ModelMetricService.java @@ -0,0 +1,13 @@ +package com.supervision.springaidemo.service; + +import com.supervision.springaidemo.domain.ModelMetric; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author flevance +* @description 针对表【model_metric】的数据库操作Service +* @createDate 2024-05-10 16:40:18 +*/ +public interface ModelMetricService extends IService { + +} diff --git a/src/main/java/com/supervision/springaidemo/service/VpAskTemplateQuestionLibraryService.java b/src/main/java/com/supervision/springaidemo/service/VpAskTemplateQuestionLibraryService.java new file mode 100644 index 0000000..5d4062e --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/VpAskTemplateQuestionLibraryService.java @@ -0,0 +1,13 @@ +package com.supervision.springaidemo.service; + +import com.supervision.springaidemo.domain.VpAskTemplateQuestionLibrary; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author flevance +* @description 针对表【vp_ask_template_question_library(诊断问询意图问题库)】的数据库操作Service +* @createDate 2024-05-22 17:40:02 +*/ +public interface VpAskTemplateQuestionLibraryService extends IService { + +} diff --git a/src/main/java/com/supervision/springaidemo/service/VpCommonDicService.java b/src/main/java/com/supervision/springaidemo/service/VpCommonDicService.java new file mode 100644 index 0000000..e07acf9 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/VpCommonDicService.java @@ -0,0 +1,13 @@ +package com.supervision.springaidemo.service; + +import com.supervision.springaidemo.domain.VpCommonDic; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author flevance +* @description 针对表【vp_common_dic(通用字典表)】的数据库操作Service +* @createDate 2024-05-23 10:24:49 +*/ +public interface VpCommonDicService extends IService { + +} diff --git a/src/main/java/com/supervision/springaidemo/service/impl/ModelMetricExampleServiceImpl.java b/src/main/java/com/supervision/springaidemo/service/impl/ModelMetricExampleServiceImpl.java new file mode 100644 index 0000000..2dfa87f --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/impl/ModelMetricExampleServiceImpl.java @@ -0,0 +1,22 @@ +package com.supervision.springaidemo.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.springaidemo.domain.ModelMetricExample; +import com.supervision.springaidemo.service.ModelMetricExampleService; +import com.supervision.springaidemo.mapper.ModelMetricExampleMapper; +import org.springframework.stereotype.Service; + +/** +* @author flevance +* @description 针对表【model_metric_example(指标例子)】的数据库操作Service实现 +* @createDate 2024-05-17 11:49:41 +*/ +@Service +public class ModelMetricExampleServiceImpl extends ServiceImpl + implements ModelMetricExampleService{ + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/service/impl/ModelMetricServiceImpl.java b/src/main/java/com/supervision/springaidemo/service/impl/ModelMetricServiceImpl.java new file mode 100644 index 0000000..106a624 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/impl/ModelMetricServiceImpl.java @@ -0,0 +1,22 @@ +package com.supervision.springaidemo.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.springaidemo.domain.ModelMetric; +import com.supervision.springaidemo.service.ModelMetricService; +import com.supervision.springaidemo.mapper.ModelMetricMapper; +import org.springframework.stereotype.Service; + +/** +* @author flevance +* @description 针对表【model_metric】的数据库操作Service实现 +* @createDate 2024-05-10 16:40:18 +*/ +@Service +public class ModelMetricServiceImpl extends ServiceImpl + implements ModelMetricService{ + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/service/impl/VpAskTemplateQuestionLibraryServiceImpl.java b/src/main/java/com/supervision/springaidemo/service/impl/VpAskTemplateQuestionLibraryServiceImpl.java new file mode 100644 index 0000000..17f54f1 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/impl/VpAskTemplateQuestionLibraryServiceImpl.java @@ -0,0 +1,22 @@ +package com.supervision.springaidemo.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.springaidemo.domain.VpAskTemplateQuestionLibrary; +import com.supervision.springaidemo.service.VpAskTemplateQuestionLibraryService; +import com.supervision.springaidemo.mapper.VpAskTemplateQuestionLibraryMapper; +import org.springframework.stereotype.Service; + +/** +* @author flevance +* @description 针对表【vp_ask_template_question_library(诊断问询意图问题库)】的数据库操作Service实现 +* @createDate 2024-05-22 17:40:02 +*/ +@Service +public class VpAskTemplateQuestionLibraryServiceImpl extends ServiceImpl + implements VpAskTemplateQuestionLibraryService{ + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/service/impl/VpCommonDicServiceImpl.java b/src/main/java/com/supervision/springaidemo/service/impl/VpCommonDicServiceImpl.java new file mode 100644 index 0000000..38e90fc --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/service/impl/VpCommonDicServiceImpl.java @@ -0,0 +1,22 @@ +package com.supervision.springaidemo.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.supervision.springaidemo.domain.VpCommonDic; +import com.supervision.springaidemo.service.VpCommonDicService; +import com.supervision.springaidemo.mapper.VpCommonDicMapper; +import org.springframework.stereotype.Service; + +/** +* @author flevance +* @description 针对表【vp_common_dic(通用字典表)】的数据库操作Service实现 +* @createDate 2024-05-23 10:24:49 +*/ +@Service +public class VpCommonDicServiceImpl extends ServiceImpl + implements VpCommonDicService{ + +} + + + + diff --git a/src/main/java/com/supervision/springaidemo/thread/RunCheckThread.java b/src/main/java/com/supervision/springaidemo/thread/RunCheckThread.java new file mode 100644 index 0000000..a59f800 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/thread/RunCheckThread.java @@ -0,0 +1,91 @@ +package com.supervision.springaidemo.thread; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.supervision.springaidemo.domain.ModelMetric; +import com.supervision.springaidemo.domain.NoteCheckRecord; +import com.supervision.springaidemo.dto.MetricResultDTO; +import com.supervision.police.service.NoteCheckRecordService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.util.StopWatch; + +@Slf4j +public class RunCheckThread implements Runnable { + + private final String caseName; + + private final OllamaChatClient chatClient; + + private final NoteCheckRecordService noteCheckRecordService; + + private final Prompt prompt; + + private final String fileName; + + private final String format; + + private final String systemPrompt; + + private final ModelMetric modelMetric; + + + private Integer count; + + public RunCheckThread(String caseName, OllamaChatClient chatClient, NoteCheckRecordService noteCheckRecordService, Prompt prompt, String fileName, String format, String systemPrompt, ModelMetric modelMetric, Integer count) { + this.caseName = caseName; + this.chatClient = chatClient; + this.noteCheckRecordService = noteCheckRecordService; + this.prompt = prompt; + this.fileName = fileName; + this.format = format; + this.systemPrompt = systemPrompt; + this.modelMetric = modelMetric; + this.count = count; + } + + @Override + public void run() { + try { + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + log.info("开始分析:{}",fileName); + ChatResponse call = chatClient.call(prompt); + stopWatch.stop(); + log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + + String content = result.getOutput().getContent(); + log.info("分析的结果是:{}", content); + MetricResultDTO metricResultDTO = JSONUtil.toBean(content, MetricResultDTO.class); + // 如果为空,则再跑一次,最多跑5次 + if (StrUtil.isBlank(metricResultDTO.getResult())) { + if (count > 5) { + log.info("{}的{}结果超过5次,不再继续跑了", fileName, modelMetric); + } else { + log.info("{}的{}结果为空,当前跑了{}次,重新提交,再跑一次", fileName, modelMetric, count); + Integer newCount = count++; + RunCheckThread runCheck = new RunCheckThread(caseName, chatClient, noteCheckRecordService, prompt, fileName, format, systemPrompt, modelMetric, newCount); + RunCheckThreadPool.chatExecutor.submit(runCheck); + } + } else { + NoteCheckRecord noteCheckRecord = new NoteCheckRecord(); + noteCheckRecord.setCaseName(caseName); + noteCheckRecord.setNoteName(fileName); + noteCheckRecord.setMetricCode(modelMetric.getMetricCode()); + noteCheckRecord.setMetricName(modelMetric.getMetricName()); + noteCheckRecord.setSystemPrompt(systemPrompt); + noteCheckRecord.setPrompt(format); + noteCheckRecord.setResult(metricResultDTO.getResult()); + noteCheckRecord.setOriginalContext(metricResultDTO.getOriginalContext()); + noteCheckRecord.setReason(metricResultDTO.getReason()); + noteCheckRecordService.save(noteCheckRecord); + } + } catch (Exception e) { + log.error("出现错误", e); + } + } +} diff --git a/src/main/java/com/supervision/springaidemo/thread/RunCheckThreadPool.java b/src/main/java/com/supervision/springaidemo/thread/RunCheckThreadPool.java new file mode 100644 index 0000000..e7231b9 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/thread/RunCheckThreadPool.java @@ -0,0 +1,10 @@ +package com.supervision.springaidemo.thread; + +import cn.hutool.core.thread.ThreadUtil; + +import java.util.concurrent.ExecutorService; + +public class RunCheckThreadPool { + + public static final ExecutorService chatExecutor = ThreadUtil.newFixedExecutor(20, Integer.MAX_VALUE, "chat", false); +} diff --git a/src/main/java/com/supervision/springaidemo/util/RecordRegexUtil.java b/src/main/java/com/supervision/springaidemo/util/RecordRegexUtil.java new file mode 100644 index 0000000..10cd374 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/util/RecordRegexUtil.java @@ -0,0 +1,38 @@ +package com.supervision.springaidemo.util; + +import cn.hutool.core.util.CharUtil; +import cn.hutool.core.util.StrUtil; +import com.supervision.springaidemo.dto.QARecordNodeDTO; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 正则提取问答 + */ +public class RecordRegexUtil { + + // 创建正则表达式Pattern对象,允许问题和答案之间有任意数量的换行符 + private static final Pattern pattern = Pattern.compile("(问:)(.*?)(答:)(.*?)(?=问:|\n$)", Pattern.DOTALL); + + + public static List recordRegex(String content, String answerName) { + List qaList = new ArrayList<>(); + // 创建Matcher对象 + Matcher matcher = pattern.matcher(content); + // 循环找到所有匹配项 + while (matcher.find()) { + // 提取问题和答案 + String question = matcher.group(2).trim(); + String answer = matcher.group(4).trim(); + QARecordNodeDTO qaRecordNodeDTO = new QARecordNodeDTO(); + qaRecordNodeDTO.setQuestion("办案警官问:" + StrUtil.removeAll(question, CharUtil.SPACE, CharUtil.CR, CharUtil.LF)); + qaRecordNodeDTO.setAnswer(answerName + "回答:" + StrUtil.removeAll(answer, CharUtil.SPACE, CharUtil.CR, CharUtil.LF)); + qaList.add(qaRecordNodeDTO); + } + return qaList; + } + +} diff --git a/src/main/java/com/supervision/springaidemo/util/TtsUtil.java b/src/main/java/com/supervision/springaidemo/util/TtsUtil.java new file mode 100644 index 0000000..3015755 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/util/TtsUtil.java @@ -0,0 +1,33 @@ +package com.supervision.springaidemo.util; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.supervision.springaidemo.dto.paddlespeech.req.TtsReqDTO; +import com.supervision.springaidemo.dto.paddlespeech.res.PaddleSpeechResDTO; +import com.supervision.springaidemo.dto.paddlespeech.res.TtsResultDTO; + +public class TtsUtil { + + private static final String TTS_URL = "http://192.168.10.137:8090/paddlespeech/tts"; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static String ttsTransform(String str) { + // 构建 + String post = HttpUtil.post(TTS_URL, JSONUtil.toJsonStr(new TtsReqDTO(str))); + try { + PaddleSpeechResDTO response = objectMapper.readValue(post, new TypeReference>() { + }); + if (!response.getSuccess() || ObjectUtil.isEmpty(response.getResult())) { + throw new RuntimeException("文字转换语音失败"); + } + return response.getResult().getAudio(); + } catch (Exception e) { + throw new RuntimeException("语音转换文字失败", e); + } + + } +} diff --git a/src/main/java/com/supervision/springaidemo/util/WordReadUtil.java b/src/main/java/com/supervision/springaidemo/util/WordReadUtil.java new file mode 100644 index 0000000..0914a35 --- /dev/null +++ b/src/main/java/com/supervision/springaidemo/util/WordReadUtil.java @@ -0,0 +1,57 @@ +package com.supervision.springaidemo.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFParagraph; +import org.springframework.web.multipart.MultipartFile; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.List; + +@Slf4j +public class WordReadUtil { + + public static String readWord(String filePath) { + + StringBuilder stringBuilder = new StringBuilder(); + // 使用 FileInputStream 打开文件 + try (FileInputStream fis = new FileInputStream(filePath)) { + // 创建 XWPFDocument 对象 + XWPFDocument document = new XWPFDocument(fis); + + // 获取所有段落 + List paragraphs = document.getParagraphs(); + + // 遍历所有段落并打印文本 + for (XWPFParagraph paragraph : paragraphs) { + stringBuilder.append(paragraph.getText()); + } + } catch (Exception e) { + log.error("获取笔录内容失败,{}", filePath, e); + } + return stringBuilder.toString(); + + } + + public static String readWord(MultipartFile file) { + StringBuilder stringBuilder = new StringBuilder(); + // 使用 InputStream 打开文件 + try (InputStream in = file.getInputStream()) { + // 创建 XWPFDocument 对象 + XWPFDocument document = new XWPFDocument(in); + + // 获取所有段落 + List paragraphs = document.getParagraphs(); + + // 遍历所有段落并打印文本 + for (XWPFParagraph paragraph : paragraphs) { + stringBuilder.append(paragraph.getText()); + } + } catch (Exception e) { + log.error("获取笔录内容失败,{}", file.getOriginalFilename(), e); + } + return stringBuilder.toString(); + } + +} diff --git a/src/main/java/com/supervision/swagger/OpenAPIConfig.java b/src/main/java/com/supervision/swagger/OpenAPIConfig.java new file mode 100644 index 0000000..d1c0932 --- /dev/null +++ b/src/main/java/com/supervision/swagger/OpenAPIConfig.java @@ -0,0 +1,34 @@ +package com.supervision.swagger; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class OpenAPIConfig { + + @Value("${sys-common-swagger.enabled:true}") + private boolean enabled; + + @Value("${sys-common-swagger.base-package:com.sys}") + private String basePackage; + + @Value("${sys-common-swagger.title:${spring.application.name:}}") + private String title; + + @Value("${sys-common-swagger.description:${spring.application.name:}}") + private String description = "接口文档"; + + private String version = "1.0.0"; + + @Bean + public OpenAPI OpenAPI() { + return new OpenAPI().info(new Info() + .title(title) + .description(description) + .version(version)); + } + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..c854d76 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,85 @@ +spring: + application: + name: spring-ai-demo + ai: + # 文档地址 https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/api/chat/ollama-chat.html + ollama: + base-url: http://113.128.242.110:11434 +# base-url: http://124.220.94.55:8060 + chat: + enabled: true + options: + model: llama3-chinese:8b +# model: qwen2:72b + # 控制模型在请求后加载到内存中的时间(稍微长一点的时间,避免重复加载浪费性能,加快处理速度) + keep_alive: 30m + # 例如0.3 + temperature: 0.8 + format: json + # 减少产生废话的可能性。较高的值(例如,100)将给出更多样化的答案,而较低的值(例如,10)将更加保守。 + top-k: 90 + # 与top-k一起工作。较高的值(例如,0.95)将导致更加多样化的文本,而较低的值(例如,0.5)将生成更加集中和保守的文本。 + top-p: 0.95 + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + # url: jdbc:mysql://192.168.10.137:3306/nx_llm?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8 +# url: jdbc:mysql://192.168.10.138:3306/virtual_patient?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8 + url: jdbc:mysql://113.128.242.110:3306/nx_llm?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8 + username: root + password: 'root@2024' + initial-size: 5 # 初始化大小 + min-idle: 10 # 最小连接数 + max-active: 20 # 最大连接数 + max-wait: 60000 # 获取连接时的最大等待时间 + min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒 + time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒 + filters: stat,wall # 配置扩展插件:stat-监控统计,log4j-日志,wall-防火墙(防止SQL注入),去掉后,监控界面的sql无法统计 + validation-query: SELECT 1 # 检测连接是否有效的 SQL语句,为空时以下三个配置均无效 + test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能 + test-on-return: true # 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能 + test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认false,建议开启,不影响性能 + stat-view-servlet: + enabled: false # 是否开启 StatViewServlet + filter: + stat: + enabled: true # 是否开启 FilterStat,默认true + log-slow-sql: true # 是否开启 慢SQL 记录,默认false + slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000,单位:毫秒 + merge-sql: false # 合并多个连接池的监控数据,默认false + data: + neo4j: + database: neo4j + + neo4j: + uri: bolt://113.128.242.110:7687 + authentication: + username: neo4j + password: Sushengtian@sdjn2023 +sys: + common: + swagger: + enabled: true + description: XXX系统 + base-package: com.supervision.*.controller + title: XXX系统 + version: 1.0.0 + +springdoc: + api-docs: + # 是否开启接口文档 + enabled: true + swagger-ui: + # 持久化认证数据,如果设置为 true,它会保留授权数据并且不会在浏览器关闭/刷新时丢失 + persistAuthorization: true + +minio: + endpoint: http:113.128.242.110:9002 + accessKey: minioadmin + secretKey: minioadmin + bucketName: nxfuhsi + +logging: + level: + org.springframework.ai: TRACE \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..b369131 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,15 @@ +spring: + profiles: + active: dev + main: + allow-bean-definition-overriding: true + mvc: + path match: + matching-strategy: ANT_PATH_MATCHER + +mybatis-plus: + mapper-locations: classpath*:mapper/*.xml + configuration: + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + call-setters-on-nulls: true diff --git a/src/main/resources/mapper/CasePersonMapper.xml b/src/main/resources/mapper/CasePersonMapper.xml new file mode 100644 index 0000000..455aa78 --- /dev/null +++ b/src/main/resources/mapper/CasePersonMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ComDictionaryMapper.xml b/src/main/resources/mapper/ComDictionaryMapper.xml new file mode 100644 index 0000000..fd008f7 --- /dev/null +++ b/src/main/resources/mapper/ComDictionaryMapper.xml @@ -0,0 +1,47 @@ + + + + + update com_dictionary + set data_status = 0 + where id = #{id} or pid = #{id} + + + + + + + + + + + + diff --git a/src/main/resources/mapper/MinioFileMapper.xml b/src/main/resources/mapper/MinioFileMapper.xml new file mode 100644 index 0000000..b3d8bec --- /dev/null +++ b/src/main/resources/mapper/MinioFileMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ModelAtomicIndexMapper.xml b/src/main/resources/mapper/ModelAtomicIndexMapper.xml new file mode 100644 index 0000000..eb96b7b --- /dev/null +++ b/src/main/resources/mapper/ModelAtomicIndexMapper.xml @@ -0,0 +1,32 @@ + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ModelAtomicResultMapper.xml b/src/main/resources/mapper/ModelAtomicResultMapper.xml new file mode 100644 index 0000000..28f2641 --- /dev/null +++ b/src/main/resources/mapper/ModelAtomicResultMapper.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ModelCaseMapper.xml b/src/main/resources/mapper/ModelCaseMapper.xml new file mode 100644 index 0000000..4d8c7c7 --- /dev/null +++ b/src/main/resources/mapper/ModelCaseMapper.xml @@ -0,0 +1,56 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ModelIndexMapper.xml b/src/main/resources/mapper/ModelIndexMapper.xml new file mode 100644 index 0000000..a7aa550 --- /dev/null +++ b/src/main/resources/mapper/ModelIndexMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ModelIndexResultMapper.xml b/src/main/resources/mapper/ModelIndexResultMapper.xml new file mode 100644 index 0000000..7393456 --- /dev/null +++ b/src/main/resources/mapper/ModelIndexResultMapper.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ModelMetricExampleMapper.xml b/src/main/resources/mapper/ModelMetricExampleMapper.xml new file mode 100644 index 0000000..fe7c87d --- /dev/null +++ b/src/main/resources/mapper/ModelMetricExampleMapper.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + id,metric_code,example + + diff --git a/src/main/resources/mapper/ModelMetricMapper.xml b/src/main/resources/mapper/ModelMetricMapper.xml new file mode 100644 index 0000000..614bdae --- /dev/null +++ b/src/main/resources/mapper/ModelMetricMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + id,metric_code,metric_name, + metric_true_desc,metric_false_desc, + metric_desc,metric_type,prompt_template + + diff --git a/src/main/resources/mapper/ModelRecordTypeMapper.xml b/src/main/resources/mapper/ModelRecordTypeMapper.xml new file mode 100644 index 0000000..2b9f5b1 --- /dev/null +++ b/src/main/resources/mapper/ModelRecordTypeMapper.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/src/main/resources/mapper/NoteCheckRecordMapper.xml b/src/main/resources/mapper/NoteCheckRecordMapper.xml new file mode 100644 index 0000000..c8ffdd9 --- /dev/null +++ b/src/main/resources/mapper/NoteCheckRecordMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + id + ,person_name,note_name, + type,metric_code,metric_name,system_prompt,prompt + result,original_context,reason + + diff --git a/src/main/resources/mapper/NotePromptMapper.xml b/src/main/resources/mapper/NotePromptMapper.xml new file mode 100644 index 0000000..0d722f1 --- /dev/null +++ b/src/main/resources/mapper/NotePromptMapper.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/NoteRecordMapper.xml b/src/main/resources/mapper/NoteRecordMapper.xml new file mode 100644 index 0000000..d208796 --- /dev/null +++ b/src/main/resources/mapper/NoteRecordMapper.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/src/main/resources/mapper/NoteRecordsMapper.xml b/src/main/resources/mapper/NoteRecordsMapper.xml new file mode 100644 index 0000000..c5c7d19 --- /dev/null +++ b/src/main/resources/mapper/NoteRecordsMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/TripleInfoMapper.xml b/src/main/resources/mapper/TripleInfoMapper.xml new file mode 100644 index 0000000..05c191c --- /dev/null +++ b/src/main/resources/mapper/TripleInfoMapper.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/VpCommonDicMapper.xml b/src/main/resources/mapper/VpCommonDicMapper.xml new file mode 100644 index 0000000..3b7cf8d --- /dev/null +++ b/src/main/resources/mapper/VpCommonDicMapper.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + id,code,name_zh, + name_en,group_code,parent_id, + priority,name_zh_path,description, + create_user_id,create_time,update_user_id, + update_time + + diff --git a/src/test/java/com/supervision/springaidemo/SpringAiDemoApplicationTests.java b/src/test/java/com/supervision/springaidemo/SpringAiDemoApplicationTests.java new file mode 100644 index 0000000..fb08ead --- /dev/null +++ b/src/test/java/com/supervision/springaidemo/SpringAiDemoApplicationTests.java @@ -0,0 +1,74 @@ +package com.supervision.springaidemo; + +import com.supervision.common.domain.R; +import com.supervision.neo4j.controller.Neo4jController; +import com.supervision.neo4j.domain.CaseNode; +import com.supervision.springaidemo.controller.ExampleChatController; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.util.StopWatch; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class SpringAiDemoApplicationTests { + + @Autowired + private OllamaChatClient ollamaChatClient; + + @Autowired + private ExampleChatController exampleChatController; + + @Autowired + private Neo4jController neo4jController; + + @Test + public void contextLoads() { + + } + + @Test + public void test() { +// exampleChatController.test("1803663875373694977", "你现在是一个笔录分析人员,请用四个字描述一下下述内容属于哪种类型的对话?"); + } + + @Test + public void savePersion() { + CaseNode caseNode = new CaseNode(); + caseNode.setName("自然人"); + R save = neo4jController.save(caseNode); + System.out.printf(save.toString()); + } + + private final OllamaChatClient chatClient; + @Autowired + public SpringAiDemoApplicationTests(OllamaChatClient chatClient) { + this.chatClient = chatClient; + } + + @Test + public void aaaaa() { + List messages = new ArrayList<>(List.of(new SystemMessage("你是谁"))); + Prompt prompt = new Prompt(messages); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + log.info("开始分析:"); + ChatResponse call = chatClient.call(prompt); + stopWatch.stop(); + log.info("耗时:{}", stopWatch.getTotalTimeSeconds()); + Generation result = call.getResult(); + + String content = result.getOutput().getContent(); + log.info("分析的结果是:{}", content); + } +}