瀏覽代碼

Merge remote-tracking branch 'origin/master'

1811872455@163.com 2 周之前
父節點
當前提交
d5021f3b97
共有 57 個文件被更改,包括 1878 次插入0 次删除
  1. 4 0
      java/storlead-api/src/main/resources/application-prod.yml
  2. 100 0
      java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/ChunkController.java
  3. 139 0
      java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/DocumentController.java
  4. 93 0
      java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/KnowledgeController.java
  5. 92 0
      java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/TagController.java
  6. 4 0
      java/storlead-knowledge/storlead-knowledge-core/pom.xml
  7. 9 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/config/DifyConfig.java
  8. 28 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/config/DifyProperties.java
  9. 21 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/ChunkEntity.java
  10. 38 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/DocumentEntity.java
  11. 62 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/KnowledgeEntity.java
  12. 14 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/RerankingModelEntity.java
  13. 27 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/RetrievalModelDictEntity.java
  14. 18 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/SummaryIndexSettingEntity.java
  15. 16 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/TagEntity.java
  16. 35 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/DocFormEnum.java
  17. 30 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/DocLanguageEnum.java
  18. 29 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/IndexingTechniqueEnum.java
  19. 47 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/ModelEnum.java
  20. 11 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/ChunkDTO.java
  21. 7 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/DocumentDTO.java
  22. 14 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/KnowledgeDTO.java
  23. 16 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/QueryPageDTO.java
  24. 23 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/TagDTO.java
  25. 299 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/HttpService.java
  26. 9 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/JacksonHolder.java
  27. 42 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/JsonUtils.java
  28. 26 0
      java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/UrlBuilder.java
  29. 13 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/controller/MarketingController.java
  30. 25 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/CustomerBaseEntity.java
  31. 195 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/MarketingCampaignEntity.java
  32. 43 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/SopDetailEntity.java
  33. 35 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/SopEntity.java
  34. 22 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/TagEntity.java
  35. 55 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/TemplateEntity.java
  36. 26 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/TemplateTagEntity.java
  37. 9 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/CustomerBaseEntityMapper.java
  38. 9 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/MarketingCampaignEntityMapper.java
  39. 9 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/SopDetailEntityMapper.java
  40. 9 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/SopEntityMapper.java
  41. 9 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/TagEntityMapper.java
  42. 9 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/TemplateEntityMapper.java
  43. 9 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/TemplateTagEntityMapper.java
  44. 7 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/CustomerBaseEntityService.java
  45. 8 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/MarketingCampaignEntityService.java
  46. 7 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/SopDetailEntityService.java
  47. 7 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/SopEntityService.java
  48. 7 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/TagEntityService.java
  49. 7 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/TemplateEntityService.java
  50. 7 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/TemplateTagEntityService.java
  51. 14 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/CustomerBaseEntityServiceImpl.java
  52. 14 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/MarketingCampaignEntityServiceImpl.java
  53. 14 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/SopDetailEntityServiceImpl.java
  54. 14 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/SopEntityServiceImpl.java
  55. 14 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/TagEntityServiceImpl.java
  56. 14 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/TempalteEntityServiceImpl.java
  57. 14 0
      java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/TempalteTagEntityServiceImpl.java

+ 4 - 0
java/storlead-api/src/main/resources/application-prod.yml

@@ -218,3 +218,7 @@ file:
   # 文件大小 /M
   maxSize: 100
   avatarMaxSize: 5
+
+  dify:
+    base-url: http://192.168.1.77/v1/
+    dataset-api-key: dataset-qfhXMNcjsRSwN5CK6aoWx3hl

+ 100 - 0
java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/ChunkController.java

@@ -0,0 +1,100 @@
+package com.storlead.knowledge.api;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.storlead.framework.common.result.Result;
+import com.storlead.knowledge.config.DifyProperties;
+import com.storlead.knowledge.pojo.dto.ChunkDTO;
+import com.storlead.knowledge.pojo.dto.QueryPageDTO;
+import com.storlead.knowledge.utils.HttpService;
+import com.storlead.knowledge.utils.JacksonHolder;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+
+@RestController
+@RequestMapping("/knowledge/chunk/")
+@Api(tags = "知识库--文档--文本块")
+public class ChunkController {
+    @Resource
+    private HttpService httpService;
+    @Resource
+    private DifyProperties difyProperties;
+
+
+    @GetMapping("{dataset_id}/{document_id}")
+    @ApiOperation("获取指定知识库指定文档文本块")
+    public Result<Object> list(@PathVariable String dataset_id , @PathVariable String document_id , QueryPageDTO page) {
+        String url = difyProperties.getBaseUrl()  + "datasets/"+ dataset_id +"/documents/"+document_id +"/segments";
+        return httpService.get(
+                url,
+                Map.of("page", page.getPageIndex(), "size", page.getPageSize(), "keyword", page.getKeyword()),
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+    @GetMapping("{dataset_id}/{document_id}/{segment_id}")
+    @ApiOperation("获取指定知识库指定文档文本块")
+    public Result<Object> getOne(@PathVariable String dataset_id , @PathVariable String document_id , @PathVariable String segment_id ) {
+        String url = difyProperties.getBaseUrl()  + "datasets/"+ dataset_id +"/documents/"+document_id +"/segments/"+segment_id;
+        return httpService.get(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+
+    @DeleteMapping("{dataset_id}/{document_id}/{segment_id}")
+    @ApiOperation("删除文本块")
+    public Result<Object> deleteDataset(@PathVariable String dataset_id , @PathVariable String document_id , @PathVariable String segment_id ) {
+        String url = difyProperties.getBaseUrl()  + "datasets/"+ dataset_id +"/documents/"+document_id +"/segments/"+segment_id;
+        return httpService.delete(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}) ;
+    }
+
+    @PostMapping("/{dataset_id}/{document_id}")
+    @ApiOperation("创建文本块")
+    public Result<?> createSegments(
+            @PathVariable String dataset_id,
+            @PathVariable String document_id,
+            @RequestBody ChunkDTO request
+    ) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl()  + "datasets/"+ dataset_id +"/documents/"+document_id +"/segments/";
+        return  httpService.post(
+                url,
+                Map.of(),
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                JacksonHolder.OBJECT_MAPPER.writeValueAsString(request),
+                new TypeReference<>() {}
+        );
+
+    }
+    @PostMapping("/{dataset_id}/{document_id}/{segment_id}")
+    @ApiOperation("更新指定ID的文本块")
+    public Result<Object> updateChunk(  @PathVariable String dataset_id,
+                                        @PathVariable String document_id,
+                                        @PathVariable String segment_id,
+                                        @RequestBody ChunkDTO request) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl()  + "datasets/"+ dataset_id +"/documents/"+document_id +"/segments/"+segment_id;
+        return   httpService.post(
+                url,
+                Map.of(),
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                JacksonHolder.OBJECT_MAPPER.writeValueAsString(request),
+                new TypeReference<>() {}
+        );
+
+
+    }
+
+}

+ 139 - 0
java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/DocumentController.java

@@ -0,0 +1,139 @@
+package com.storlead.knowledge.api;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.storlead.framework.common.result.Result;
+import com.storlead.knowledge.config.DifyProperties;
+import com.storlead.knowledge.pojo.dto.DocumentDTO;
+import com.storlead.knowledge.pojo.dto.KnowledgeDTO;
+import com.storlead.knowledge.utils.HttpService;
+import com.storlead.knowledge.utils.JacksonHolder;
+import com.storlead.knowledge.pojo.dto.QueryPageDTO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+
+@RestController
+@RequestMapping("/knowledge/document/")
+@Api(tags = "知识库")
+public class DocumentController {
+    @Resource
+    private HttpService httpService;
+
+    @Resource
+    private DifyProperties difyProperties;
+
+
+    @GetMapping("{dataset_id}/documents")
+    @ApiOperation("获取知识库文档")
+    public Result<Object> listDocuments(@PathVariable String dataset_id , QueryPageDTO page) {
+        String url = difyProperties.getBaseUrl() +"datasets/"+ dataset_id + "/documents";
+        return httpService.get(
+                url,
+                Map.of("page", page.getPageIndex(), "size", page.getPageSize(), "keyword", page.getKeyword()),
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+    @GetMapping("{dataset_id}/documents/{document_id}")
+    @ApiOperation("获取指定ID的知识库的指定文档")
+    public Result<Object> getDocument(@PathVariable String dataset_id , @PathVariable String document_id) {
+        String url = difyProperties.getBaseUrl() +"datasets/"+ dataset_id + "/documents/"+document_id;
+        return httpService.get(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {});
+    }
+
+    @DeleteMapping("{dataset_id}/documents/{document_id}")
+    @ApiOperation("删除指定ID的文档")
+    public Result<Object> deleteDocument(@PathVariable String dataset_id , @PathVariable String document_id) {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id + "/documents/"+document_id;
+        return httpService.delete(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}) ;
+    }
+
+    @PostMapping("{dataset_id}/document/create_by_text")
+    @ApiOperation("以文本创建文档")
+    public Result<Object> createDocumentByText(@RequestBody DocumentDTO documentDTO, @PathVariable String dataset_id) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id + "/document/create-by-text";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(documentDTO);
+        return httpService.post(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @PostMapping("{dataset_id}/document/create_by_file")
+    @ApiOperation("以文件创建文档")
+    public Result<Object> createDocumentByFile(
+            @RequestParam("file") MultipartFile file,
+            @RequestParam("data") String data,
+            @PathVariable String dataset_id
+    ) {
+        String url = difyProperties.getBaseUrl() +"datasets/"+ dataset_id + "/document/create-by-file";
+        return httpService.uploadWithJson(
+                url,
+                file,
+                data,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+    @PostMapping("{dataset_id}/documents/{document_id}/update-by-text")
+    @ApiOperation("以文本更新文档")
+    public Result<Object> updateDocumentByText(
+            @RequestBody KnowledgeDTO knowledgeDTO,
+            @PathVariable String dataset_id,
+            @PathVariable String document_id
+    ) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() +"datasets/"+dataset_id + "/documents/"+document_id+"/update-by-text";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(knowledgeDTO);
+        return httpService.patch(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @PostMapping("{dataset_id}/documents/{document_id}/update-by-file")
+    @ApiOperation("以文件创建文档")
+    public Result<Object> updateDocumentByFile(
+            @RequestParam("file") MultipartFile file,
+            @RequestParam("data") String data,
+            @PathVariable String dataset_id,
+            @PathVariable String document_id
+    ) {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id + "/documents/"+ document_id+"/create-by-file";
+        return httpService.uploadWithJson(
+                url,
+                file,
+                data,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+    @GetMapping("{dataset_id}/documents/{batch}/indexing-status")
+    @ApiOperation("查看刚上传文件的索引状态")
+    public Result<Object> getIndexingStstus(
+            @RequestParam("file") MultipartFile file,
+            @RequestParam("data") String data,
+            @PathVariable String dataset_id,
+            @PathVariable String batch
+    ) {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id + "/documents/"+ batch+"/indexing-status";
+        return httpService.uploadWithJson(
+                url,
+                file,
+                data,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+}

+ 93 - 0
java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/KnowledgeController.java

@@ -0,0 +1,93 @@
+package com.storlead.knowledge.api;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.storlead.framework.common.result.Result;
+import com.storlead.knowledge.config.DifyProperties;
+import com.storlead.knowledge.pojo.dto.KnowledgeDTO;
+import com.storlead.knowledge.utils.HttpService;
+import com.storlead.knowledge.utils.JacksonHolder;
+import com.storlead.knowledge.pojo.dto.QueryPageDTO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+
+@RestController
+@RequestMapping("/knowledge/base/")
+@Api(tags = "知识库")
+public class KnowledgeController {
+    @Resource
+    private HttpService httpService;
+    @Resource
+    private DifyProperties difyProperties;
+
+    @GetMapping("datasets")
+    @ApiOperation("获取所有知识库数据集")
+    public Result<Object> listDatasets(QueryPageDTO page) {
+        String url = difyProperties.getBaseUrl() + "datasets";
+        return httpService.get(
+                url,
+                Map.of("page", page.getPageIndex(), "size", page.getPageSize(), "keyword", page.getKeyword()),
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+    @GetMapping("datasets/{dataset_id}")
+    @ApiOperation("获取指定ID的知识库")
+    public Result<Object> getDataset(@PathVariable String dataset_id ) {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id;
+        return httpService.get(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {});
+    }
+
+    @DeleteMapping("datasets/{dataset_id}")
+    @ApiOperation("删除指定ID的知识库")
+    public Result<Object> deleteDataset(@PathVariable String  dataset_id) {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id;
+        return httpService.delete(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}) ;
+    }
+
+    @PostMapping("datasets")
+    @ApiOperation("创建知识库")
+    public Result<Object> createDataset(@RequestBody KnowledgeDTO knowledgeDTO) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(knowledgeDTO);
+        return httpService.post(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @PatchMapping("datasets/{dataset_id}")
+    @ApiOperation("更新指定ID的知识库")
+    public Result<Object> updateDataset(@RequestBody KnowledgeDTO knowledgeDTO, @PathVariable String  dataset_id) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id;
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(knowledgeDTO);
+        return httpService.patch(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @PostMapping("datasets/{dataset_id}/retrieve")
+    @ApiOperation("知识库测试")
+    public Result<Object> retrieve( @PathVariable String  dataset_id,@RequestBody  QueryPageDTO queryPageDTO) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets/"+dataset_id+"/retrieve";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(queryPageDTO);
+        return httpService.post(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @GetMapping("workspaces/current/models/model-types/{model_type}")
+    @ApiOperation("获取可用模型")
+    public Result<Object> retrieve( @PathVariable String  model_type) {
+        String url = difyProperties.getBaseUrl() + "workspaces/current/models/model-types/"+model_type;
+        return httpService.get(url, null, "Bearer "+difyProperties.getDatasetApiKey(), new TypeReference<>() {});
+    }
+}

+ 92 - 0
java/storlead-knowledge/storlead-knowledge-api/src/main/java/com/storlead/knowledge/api/TagController.java

@@ -0,0 +1,92 @@
+package com.storlead.knowledge.api;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.storlead.framework.common.result.Result;
+import com.storlead.knowledge.config.DifyProperties;
+import com.storlead.knowledge.pojo.dto.TagDTO;
+import com.storlead.knowledge.utils.HttpService;
+import com.storlead.knowledge.utils.JacksonHolder;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+
+@RestController
+@RequestMapping("/knowledge/tag/")
+@Api(tags = "知识库")
+public class TagController {
+    @Resource
+    private HttpService httpService;
+
+    @Resource
+    private DifyProperties difyProperties;
+
+    @GetMapping("list")
+    @ApiOperation("获取所有知识库标签")
+    public Result<Object> listTags() {
+        String url = difyProperties.getBaseUrl() + "datasets/tags";
+        return httpService.get(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}
+        );
+    }
+
+    @GetMapping("{dataset_id}/tags")
+    @ApiOperation("获取指定ID知识库的标签")
+    public Result<Object> getDataset(@PathVariable String dataset_id ) {
+        String url = difyProperties.getBaseUrl() +"datasets/" +dataset_id +"/tags";
+        return httpService.get(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {});
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除标签")
+    public Result<Object> deleteDataset() {
+        String url = difyProperties.getBaseUrl() + "datasets/tags";
+        return httpService.delete(
+                url,
+                null,
+                "Bearer "+difyProperties.getDatasetApiKey(),
+                new TypeReference<>() {}) ;
+    }
+
+    @PostMapping("/create")
+    @ApiOperation("创建标签")
+    public Result<Object> createTag(@RequestBody TagDTO tagDTO) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets/tags";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(tagDTO);
+        return httpService.post(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @PatchMapping("update")
+    @ApiOperation("更新指定ID的标签")
+    public Result<Object> updateTag(@RequestBody TagDTO tagDTO) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets/tags";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(tagDTO);
+        return httpService.patch(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @PostMapping("/binding")
+    @ApiOperation("将标签绑定到知识库")
+    public Result<Object> binding( @RequestBody  TagDTO tagDTO) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets/tags/binding";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(tagDTO);
+        return httpService.post(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+
+    @PostMapping("/unbinding")
+    @ApiOperation("将标签绑定到知识库")
+    public Result<Object> unbinding(@RequestBody  TagDTO tagDTO) throws JsonProcessingException {
+        String url = difyProperties.getBaseUrl() + "datasets/tags/unbinding";
+        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(tagDTO);
+        return httpService.post(url, null, "Bearer "+difyProperties.getDatasetApiKey(), body, new TypeReference<>() {});
+    }
+}

+ 4 - 0
java/storlead-knowledge/storlead-knowledge-core/pom.xml

@@ -25,5 +25,9 @@
             <groupId>com.storlead.boot</groupId>
             <artifactId>storlead-common</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-web</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 9 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/config/DifyConfig.java

@@ -0,0 +1,9 @@
+package com.storlead.knowledge.config;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties(DifyProperties.class)
+public class DifyConfig {
+}

+ 28 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/config/DifyProperties.java

@@ -0,0 +1,28 @@
+package com.storlead.knowledge.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "dify")
+public class DifyProperties {
+
+    private String baseUrl;
+    private String datasetApiKey;
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    public String getDatasetApiKey() {
+        return datasetApiKey;
+    }
+
+    public void setDatasetApiKey(String apiKey) {
+        this.datasetApiKey = apiKey;
+    }
+}

+ 21 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/ChunkEntity.java

@@ -0,0 +1,21 @@
+package com.storlead.knowledge.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "ChunkEntity", description = "标签")
+public class ChunkEntity {
+    @ApiModelProperty(value = "分块ID")
+    private String id;
+    @ApiModelProperty(value = "分块内容")
+    private String content;
+    @ApiModelProperty(value = "分块答案")
+    private String answer;
+    @ApiModelProperty(value = "分块关键词")
+    private String[] keywords;
+    @ApiModelProperty(value = "分块附件ID")
+    private String[] attachment_ids;
+
+}

+ 38 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/DocumentEntity.java

@@ -0,0 +1,38 @@
+package com.storlead.knowledge.entity;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel(value = "DocumnetEntity", description = "知识库文档")
+public class DocumentEntity {
+    @ApiModelProperty(value = "文档ID")
+    private String id;
+    @ApiModelProperty(value = "文档名称")
+    private String name;
+    @ApiModelProperty(value = "文档内容")
+    private String text;
+    @ApiModelProperty(value = "索引模式")
+    private String indexingTechnique;
+    @ApiModelProperty(value = "文档格式")
+    private String docForm;
+    @ApiModelProperty(value = "文档语言")
+    private String docLanguage;
+    @ApiModelProperty(value = "嵌入模型")
+    private String embeddingModel;
+    @ApiModelProperty(value = "模型提供商")
+    private String embeddingModelProvider;
+    @ApiModelProperty(value = "原始id")
+    private String originalDocumentId;
+    @ApiModelProperty(value = "索引状态")
+    private String indexingStatus;
+    @ApiModelProperty(value = "标签")
+    private List<TagEntity> tags;
+
+
+
+}

+ 62 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/KnowledgeEntity.java

@@ -0,0 +1,62 @@
+package com.storlead.knowledge.entity;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+import java.util.Date;
+
+@Data
+@ApiModel(value = "KnowledgeEntity", description = "知识库基本信息")
+public class KnowledgeEntity {
+    @ApiModelProperty(value = "知识库ID")
+    private String id;
+    @ApiModelProperty(value = "知识库名称")
+    private String name;
+    @ApiModelProperty(value = "知识库描述")
+    private String description;
+    @ApiModelProperty(value = "知识库数据源类型")
+    private String dataSourceType;
+    @ApiModelProperty(value = "知识库索引技术")
+    private String indexingTechnique;
+    @ApiModelProperty(value = "知识库应用数量")
+    private Integer appCount;
+    @ApiModelProperty(value = "知识库文档数量")
+    private Integer documentCount;
+    @ApiModelProperty(value = "知识库字数")
+    private Integer wordCount;
+    @ApiModelProperty(value = "知识库创建人")
+    private String createdById;
+    @ApiModelProperty(value = "知识库创建时间")
+    private Date createdAt;
+    @ApiModelProperty(value = "知识库更新时间")
+    private Date updatedAt;
+    @ApiModelProperty(value = "知识库嵌入模型")
+    private String embeddingModel;
+    @ApiModelProperty(value = "知识库嵌入模型提供者")
+    private String embeddingModelProvider;
+    @ApiModelProperty(value = "知识库嵌入模型是否可用")
+    private Boolean embeddingAvailable;
+    @ApiModelProperty(value = "知识库检索模型字典")
+    private RetrievalModelDictEntity retrievalModelDict;
+    @ApiModelProperty(value = "知识库摘要索引设置")
+    private SummaryIndexSettingEntity summaryIndexSetting;
+    @ApiModelProperty(value = "知识库标签")
+    private String tags;
+    @ApiModelProperty(value = "知识库文档形式")
+    private String docForm;
+    @ApiModelProperty(value = "知识库分片结构")
+    private String chunkStructure;
+    @ApiModelProperty(value = "知识库是否发布")
+    private Boolean isPublished;
+    @ApiModelProperty(value = "知识库总文档数")
+    private Integer totalDocuments;
+    @ApiModelProperty(value = "知识库可用文档数")
+    private Integer totalAvailableDocuments;
+    @ApiModelProperty(value = "知识库是否启用API")
+    private Boolean enableApi;
+    @ApiModelProperty(value = "知识库是否为多模态")
+    private Boolean isMultimodal;
+}

+ 14 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/RerankingModelEntity.java

@@ -0,0 +1,14 @@
+package com.storlead.knowledge.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "RerankingModelEntity", description = "重排模型")
+public class RerankingModelEntity {
+    @ApiModelProperty(value = "重排提供者名称")
+    String rerankingProviderName;
+    @ApiModelProperty(value = "重排模型名称")
+        String rerankingModelName;
+}

+ 27 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/RetrievalModelDictEntity.java

@@ -0,0 +1,27 @@
+package com.storlead.knowledge.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "RetrievalModelEntity", description = "知识库检索模型字典")
+public class RetrievalModelDictEntity {
+    @ApiModelProperty(value = "搜索方法")
+    private String searchMethod;
+    @ApiModelProperty(value = "是否启用重排")
+    private boolean rerankingEnable;
+    @ApiModelProperty(value = "重排模式")
+    private String rerankingMode;
+    @ApiModelProperty(value = "重排模型")
+    private RerankingModelEntity rerankingModel;
+    @ApiModelProperty(value = "权重")
+    private double weights;
+    @ApiModelProperty(value = "topK")
+    private int topK;
+    @ApiModelProperty(value = "是否启用分数阈值")
+    private boolean scoreThresholdEnabled;
+    @ApiModelProperty(value = "分数阈值")
+    private double scoreThreshold;
+
+}

+ 18 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/SummaryIndexSettingEntity.java

@@ -0,0 +1,18 @@
+package com.storlead.knowledge.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "SummaryIndexSettingEntity", description = "摘要设置")
+public class SummaryIndexSettingEntity {
+    @ApiModelProperty(value = "是否启用")
+    private boolean enable;
+    @ApiModelProperty(value = "模型名称")
+    private String model_name;
+    @ApiModelProperty(value = "模型提供者名称")
+    private String model_provider_name;
+    @ApiModelProperty(value = "摘要提示")
+    private String summary_prompt;
+}

+ 16 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/entity/TagEntity.java

@@ -0,0 +1,16 @@
+package com.storlead.knowledge.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "TagEntity", description = "标签")
+public class TagEntity {
+    @ApiModelProperty(value = "标签ID")
+    private String id;
+    @ApiModelProperty(value = "标签名称")
+    private String name;
+    @ApiModelProperty(value = "标签类型")
+    private String type;
+}

+ 35 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/DocFormEnum.java

@@ -0,0 +1,35 @@
+package com.storlead.knowledge.enums;
+
+import lombok.Getter;
+
+/***
+ * 嵌入模式枚举
+ */
+@Getter
+public enum DocFormEnum {
+
+    /**
+     * 文本模式
+     */
+    TEXT(0, "text_model"),
+
+    /**
+     * 父子结果模式
+     */
+    HIERARCHICAL(1, "hierarchical_model"),
+    /**
+     * QA问答模式
+     */
+    QA(2, "qa_model"),
+
+    ;
+
+    public Integer code;
+
+    public String desc;
+
+    DocFormEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 30 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/DocLanguageEnum.java

@@ -0,0 +1,30 @@
+package com.storlead.knowledge.enums;
+
+import lombok.Getter;
+
+/***
+ * 文档语言枚举
+ */
+@Getter
+public enum DocLanguageEnum {
+
+    /**
+     * 英语
+     */
+    ENGLISH(1, "English"),
+
+    /**
+     * 简体中文
+     */
+    CHINESE(0, "Chinese Simplified"),
+    ;
+
+    public Integer code;
+
+    public String desc;
+
+    DocLanguageEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 29 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/IndexingTechniqueEnum.java

@@ -0,0 +1,29 @@
+package com.storlead.knowledge.enums;
+
+import lombok.Getter;
+
+/***
+ * 索引技术枚举
+ */
+@Getter
+public enum IndexingTechniqueEnum {
+    /**
+     * 好质量
+     */
+    QUALITY(0,"high_quality"),
+
+    /**
+     * 经济
+     */
+    ECONOMY(1, "economy"),
+    ;
+
+    public Integer code;
+
+    public String desc;
+
+    IndexingTechniqueEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 47 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/enums/ModelEnum.java

@@ -0,0 +1,47 @@
+package com.storlead.knowledge.enums;
+
+import lombok.Getter;
+
+/***
+ * 嵌入模式枚举
+ */
+@Getter
+public enum ModelEnum {
+
+    /**
+     * 文本嵌入
+     */
+    EMBEDDING(0, "text-embedding"),
+
+    /**
+     * 重排模型
+     */
+    RERANK(1, "rerank"),
+    /**
+     * 大语言模型
+     */
+    LLM(2, "llm"),
+    /**
+     * 文字转语音
+     */
+    TTS(3, "tts"),
+    /**
+     *  语音转文字
+     */
+    SPENCH2TEXT(4, "speech2text"),
+    /**
+     * 模型内容审核
+     */
+    MONDERATION(5, "moderation"),
+
+    ;
+
+    public Integer code;
+
+    public String desc;
+
+    ModelEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 11 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/ChunkDTO.java

@@ -0,0 +1,11 @@
+package com.storlead.knowledge.pojo.dto;
+
+import com.storlead.knowledge.entity.ChunkEntity;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ChunkDTO {
+    private List<ChunkEntity> segments;
+}

+ 7 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/DocumentDTO.java

@@ -0,0 +1,7 @@
+package com.storlead.knowledge.pojo.dto;
+
+import com.storlead.knowledge.entity.DocumentEntity;
+
+public class DocumentDTO extends DocumentEntity {
+
+}

+ 14 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/KnowledgeDTO.java

@@ -0,0 +1,14 @@
+package com.storlead.knowledge.pojo.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class KnowledgeDTO  {
+
+    @ApiModelProperty(value = "名称")
+    private String name;
+
+    @ApiModelProperty(value = "描述")
+    private String description;
+}

+ 16 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/QueryPageDTO.java

@@ -0,0 +1,16 @@
+package com.storlead.knowledge.pojo.dto;
+
+import com.storlead.framework.common.dto.page.PageDTO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 分页查询字段
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class QueryPageDTO extends PageDTO {
+    private String keyword;
+    private String query;
+    private String status;
+}

+ 23 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/pojo/dto/TagDTO.java

@@ -0,0 +1,23 @@
+package com.storlead.knowledge.pojo.dto;
+
+import com.storlead.knowledge.entity.DocumentEntity;
+import com.storlead.knowledge.entity.TagEntity;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TagDTO extends TagEntity {
+    /**
+     * 标签ID
+     */
+    private String tagId;
+    /**
+     * 关联的标签ID
+     */
+    private List<String> tagIds;
+    /**
+     * 关联的文档ID
+     */
+    private String targetId;
+}

+ 299 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/HttpService.java

@@ -0,0 +1,299 @@
+package com.storlead.knowledge.utils;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.storlead.framework.common.result.Result;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.ByteArrayOutputStream;
+import java.net.URI;
+import java.net.http.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.Function;
+
+@Component
+public class HttpService {
+
+    private final HttpClient httpClient;
+    private final ObjectMapper objectMapper = JacksonHolder.OBJECT_MAPPER;
+
+    public HttpService() {
+        this.httpClient = HttpClient.newBuilder()
+                .connectTimeout(Duration.ofSeconds(5))
+                .build();
+    }
+
+    /* ================= Base Request ================= */
+
+    private HttpRequest.Builder baseRequest(String authorization) {
+        HttpRequest.Builder builder = HttpRequest.newBuilder()
+                .timeout(Duration.ofSeconds(10))
+                .header("Content-Type", "application/json");
+
+        if (authorization != null && !authorization.isBlank()) {
+            builder.header("Authorization", authorization);
+        }
+        return builder;
+    }
+
+    /* ================= Response Handler ================= */
+
+    private <T> Result<T> handleResponse(
+            HttpResponse<String> response,
+            Function<String, T> deserializer
+    ) {
+        int status = response.statusCode();
+        String body = response.body();
+
+        if (status >= 200 && status < 300) {
+            try {
+                return Result.ok(deserializer.apply(body));
+            } catch (Exception e) {
+                return (Result<T>) Result.error( "json 解析失败:"+e.getMessage());
+            }
+        }
+        return (Result<T>) Result.error("HTTP " + status + ": " + body);
+    }
+
+    /* ================= GET ================= */
+
+    public <T> Result<T> get(
+            String url,
+            Map<String, ?> queryParams,
+            String authorization,
+            TypeReference<T> typeReference
+    ) {
+        try {
+            String fullUrl = UrlBuilder.build(url, queryParams);
+            HttpRequest request = baseRequest(authorization)
+                    .uri(URI.create(fullUrl))
+                    .GET()
+                    .build();
+
+            HttpResponse<String> response =
+                    httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+            return handleResponse(response,
+                    body -> {
+                        try {
+                            return objectMapper.readValue(body, typeReference);
+                        } catch (JsonProcessingException e) {
+                            throw new RuntimeException(e);
+                        }
+                    });
+        } catch (Exception e) {
+            return (Result<T>) Result.error(e.getMessage());
+        }
+    }
+
+    /* ================= POST ================= */
+
+    public <T> Result<T> post(
+            String url,
+            Map<String, ?> queryParams,
+            String authorization,
+            String body,
+            TypeReference<T> typeReference
+    ) {
+        try {
+            String fullUrl = UrlBuilder.build(url, queryParams);
+            HttpRequest request = baseRequest(authorization)
+                    .uri(URI.create(fullUrl))
+                    .POST(HttpRequest.BodyPublishers.ofString(body))
+                    .build();
+
+            HttpResponse<String> response =
+                    httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+            return handleResponse(response,
+                    res -> {
+                        try {
+                            return objectMapper.readValue(res, typeReference);
+                        } catch (JsonProcessingException e) {
+                            throw new RuntimeException(e);
+                        }
+                    });
+        } catch (Exception e) {
+            return (Result<T>) Result.error(e.getMessage());
+        }
+    }
+
+    /* ================= PUT ================= */
+
+    public <T> Result<T> put(
+            String url,
+            Map<String, ?> queryParams,
+            String authorization,
+            String body,
+            TypeReference<T> typeReference
+    ) {
+        try {
+            String fullUrl = UrlBuilder.build(url, queryParams);
+            HttpRequest request = baseRequest(authorization)
+                    .uri(URI.create(fullUrl))
+                    .PUT(HttpRequest.BodyPublishers.ofString(body))
+                    .build();
+
+            HttpResponse<String> response =
+                    httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+            return handleResponse(response,
+                    res -> {
+                        try {
+                            return objectMapper.readValue(res, typeReference);
+                        } catch (JsonProcessingException e) {
+                            throw new RuntimeException(e);
+                        }
+                    });
+        } catch (Exception e) {
+            return (Result<T>) Result.error(e.getMessage());
+        }
+    }
+
+    /* ================= PATCH ================= */
+
+    public <T> Result<T> patch(
+            String url,
+            Map<String, ?> queryParams,
+            String authorization,
+            String body,
+            TypeReference<T> typeReference
+    ) {
+        try {
+            String fullUrl = UrlBuilder.build(url, queryParams);
+            HttpRequest request = baseRequest(authorization)
+                    .uri(URI.create(fullUrl))
+                    .method("PATCH", HttpRequest.BodyPublishers.ofString(body))
+                    .build();
+
+            HttpResponse<String> response =
+                    httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+            return handleResponse(response,
+                    res -> {
+                        try {
+                            return objectMapper.readValue(res, typeReference);
+                        } catch (JsonProcessingException e) {
+                            throw new RuntimeException(e);
+                        }
+                    });
+        } catch (Exception e) {
+            return (Result<T>) Result.error(e.getMessage());
+        }
+    }
+
+    /* ================= DELETE ================= */
+
+    public <T> Result<T> delete(
+            String url,
+            Map<String, ?> queryParams,
+            String authorization,
+            TypeReference<T> typeReference
+    ) {
+        try {
+            String fullUrl = UrlBuilder.build(url, queryParams);
+            HttpRequest request = baseRequest(authorization)
+                    .uri(URI.create(fullUrl))
+                    .DELETE()
+                    .build();
+
+            HttpResponse<String> response =
+                    httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+            return handleResponse(response,
+                    res -> {
+                        try {
+                            return objectMapper.readValue(res, typeReference);
+                        } catch (JsonProcessingException e) {
+                            throw new RuntimeException(e);
+                        }
+                    });
+        } catch (Exception e) {
+            return (Result<T>) Result.error(e.getMessage());
+        }
+    }
+
+    public <T> Result<T> uploadWithJson(
+            String url,
+            MultipartFile file,
+            String json,
+            String authorization,
+            TypeReference<T> typeReference
+    ) {
+        try {
+            String boundary = UUID.randomUUID().toString();
+
+            Path tempFile = Files.createTempFile("upload-", file.getOriginalFilename());
+            file.transferTo(tempFile.toFile());
+
+            byte[] body = buildMultipart(
+                    tempFile,
+                    file.getOriginalFilename(),
+                    json,
+                    boundary
+            );
+
+            HttpRequest request = HttpRequest.newBuilder()
+                    .uri(URI.create(url))
+                    .header("Authorization", authorization)
+                    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
+                    .POST(HttpRequest.BodyPublishers.ofByteArray(body))
+                    .build();
+
+            HttpResponse<String> response =
+                    httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+            Files.deleteIfExists(tempFile);
+
+            return handleResponse(response,
+                    res -> {
+                        try {
+                            return objectMapper.readValue(res, typeReference);
+                        } catch (JsonProcessingException e) {
+                            throw new RuntimeException(e);
+                        }
+                    });
+
+        } catch (Exception e) {
+            return (Result<T>) Result.error(e.getMessage());
+        }
+    }
+
+
+    private byte[] buildMultipart(
+            Path filePath,
+            String fileName,
+            String json,
+            String boundary
+    ) throws Exception {
+
+        String CRLF = "\r\n";
+        String prefix = "--" + boundary + CRLF;
+        String suffix = CRLF + "--" + boundary + "--";
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+        // ====== JSON Part ======
+        out.write(prefix.getBytes());
+        out.write(("Content-Disposition: form-data; name=\"metadata\"" + CRLF).getBytes());
+        out.write(("Content-Type: application/json" + CRLF + CRLF).getBytes());
+        out.write(json.getBytes(StandardCharsets.UTF_8));
+
+        // ====== File Part ======
+        out.write((CRLF + prefix).getBytes());
+        out.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"" + CRLF).getBytes());
+        out.write(("Content-Type: application/octet-stream" + CRLF + CRLF).getBytes());
+        out.write(Files.readAllBytes(filePath));
+
+        // ====== End ======
+        out.write(suffix.getBytes());
+
+        return out.toByteArray();
+    }
+}

+ 9 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/JacksonHolder.java

@@ -0,0 +1,9 @@
+package com.storlead.knowledge.utils;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+public class JacksonHolder {
+    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
+            .registerModule(new JavaTimeModule());
+}

+ 42 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/JsonUtils.java

@@ -0,0 +1,42 @@
+package com.storlead.knowledge.utils;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JsonUtils {
+
+    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+    /**
+     * 对象 → JSON 字符串
+     */
+    public static String toJson(Object obj) {
+        try {
+            return OBJECT_MAPPER.writeValueAsString(obj);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("对象转 JSON 失败", e);
+        }
+    }
+
+    /**
+     * JSON → Java 对象
+     */
+    public static <T> T fromJson(String json, Class<T> clazz) {
+        try {
+            return OBJECT_MAPPER.readValue(json, clazz);
+        } catch (Exception e) {
+            throw new RuntimeException("JSON 解析失败", e);
+        }
+    }
+
+    /**
+     * JSON → 泛型对象(List / Map / Result<T>)
+     */
+    public static <T> T fromJson(String json, TypeReference<T> typeReference) {
+        try {
+            return OBJECT_MAPPER.readValue(json, typeReference);
+        } catch (Exception e) {
+            throw new RuntimeException("JSON 解析失败", e);
+        }
+    }
+}

+ 26 - 0
java/storlead-knowledge/storlead-knowledge-core/src/main/java/com/storlead/knowledge/utils/UrlBuilder.java

@@ -0,0 +1,26 @@
+package com.storlead.knowledge.utils;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+public class UrlBuilder {
+
+    public static String build(String url, Map<String, ?> queryParams) {
+        if (queryParams == null || queryParams.isEmpty()) {
+            return url;
+        }
+
+        StringBuilder sb = new StringBuilder(url);
+        sb.append(url.contains("?") ? "&" : "?");
+
+        queryParams.forEach((k, v) -> {
+            sb.append(URLEncoder.encode(k, StandardCharsets.UTF_8));
+            sb.append("=");
+            sb.append(URLEncoder.encode(v.toString(), StandardCharsets.UTF_8));
+            sb.append("&");
+        });
+
+        sb.deleteCharAt(sb.length() - 1);
+        return sb.toString();
+    }
+}

+ 13 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/controller/MarketingController.java

@@ -0,0 +1,13 @@
+package com.storlead.crm.marketing.controller;
+
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/marketing")
+@Api(tags = "营销活动")
+public class MarketingController {
+
+
+}

+ 25 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/CustomerBaseEntity.java

@@ -0,0 +1,25 @@
+package com.storlead.crm.marketing.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("customer_base")
+public class CustomerBaseEntity extends SysBaseField {
+
+    @ApiModelProperty(value = "客户id")
+    @TableField("customer_id")
+    private Long customerId;
+
+    @ApiModelProperty(value = "营销活动id")
+    @TableField("marketing_campaign_id")
+    private Long marketingCampaignId;
+
+//    @ApiModelProperty(value = "创建时间")
+//    @TableField("create_time")
+//    private LocalDateTime createTime;
+}

+ 195 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/MarketingCampaignEntity.java

@@ -0,0 +1,195 @@
+package com.storlead.crm.marketing.entity;
+
+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 com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("marketing_campaign")
+public class MarketingCampaignEntity extends SysBaseField {
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "主键id")
+    private Long id;
+
+    @ApiModelProperty(value = "活动名称")
+    @TableField("name")
+    private String name;
+
+    @ApiModelProperty(value = "活动类型")
+    @TableField("type")
+    private Integer type;
+
+    @ApiModelProperty(value = "优先级")
+    @TableField("priority")
+    private Integer priority;
+
+    @ApiModelProperty(value = "开始日期")
+    @TableField("begin_data")
+    private LocalDate beginData;
+
+    @ApiModelProperty(value = "结束日期")
+    @TableField("end_date")
+    private LocalDate endDate;
+
+    @ApiModelProperty(value = "负责人id")
+    @TableField("supervisor")
+    private Long supervisor;
+
+    @ApiModelProperty(value = "关联商机")
+    @TableField("link_to_opportunity")
+    private Long linkToOpportunity;
+
+    @ApiModelProperty(value = "活动描述")
+    @TableField("description")
+    private String description;
+
+    @ApiModelProperty(value = "发送量")
+    @TableField("send_volume")
+    private Integer sendVolume;
+
+    @ApiModelProperty(value = "打开率")
+    @TableField("open rate")
+    private Double openRate;
+
+    @ApiModelProperty(value = "回复率")
+    @TableField("reply_rate")
+    private Double replyRate;
+
+    @ApiModelProperty(value = "商机数")
+    @TableField("opportunity_count")
+    private Integer opportunityCount;
+
+    @ApiModelProperty(value = "渠道配置")
+    @TableField("channel_configuration")
+    private Integer channelConfiguration;
+
+    @ApiModelProperty(value = "发送邮箱")
+    @TableField("email_address")
+    private String emailAddress;
+
+    @ApiModelProperty(value = "发送时间")
+    @TableField("email_sent_time")
+    private String emailSentTime;
+
+    @ApiModelProperty(value = "邮件模板")
+    @TableField("email_template")
+    private String emailTemplate;
+
+    @ApiModelProperty(value = "每批发送量")
+    @TableField("email_batch_size")
+    private Integer emailBatchSize;
+
+    @ApiModelProperty(value = "邮件主题")
+    @TableField("email_subject")
+    private String emailSubject;
+
+    @ApiModelProperty(value = "是否追踪邮件打开")
+    @TableField("track_config_open")
+    private Integer trackConfigOpen;
+
+    @ApiModelProperty(value = "是否追踪链接点击")
+    @TableField("track_config_click")
+    private Integer trackConfigClick;
+
+    @ApiModelProperty(value = "是否追踪回复")
+    @TableField("track_config_reply")
+    private Integer trackConfigReply;
+
+    @ApiModelProperty(value = "SOP序列id")
+    @TableField("sop_id")
+    private Integer sopId;
+
+    @ApiModelProperty(value = "未打开邮件跟进规则")
+    @TableField("follow-up_rules_not_opened")
+    private String followUpRulesNotOpened;
+
+    @ApiModelProperty(value = "未打开邮件跟进天数")
+    @TableField("follow-up_rules_not_opened_days")
+    private String followUpRulesNotOpenedDays;
+
+    @ApiModelProperty(value = "未回复邮件跟进规则")
+    @TableField("follow-up_rules_not_replied")
+    private String followUpRulesNotReplied;
+
+    @ApiModelProperty(value = "未回复邮件跟进天数")
+    @TableField("follow-up_rules_not_replied_days")
+    private String followUpRulesNotRepliedDays;
+
+    @ApiModelProperty(value = "未点击链接跟进规则")
+    @TableField("follow-up_rules_link_not_clicked")
+    private String followUpRulesLinkNotClicked;
+
+    @ApiModelProperty(value = "未点击链接跟进天数")
+    @TableField("follow-up_rules_link_not_clicked_days")
+    private String followUpRulesLinkNotClickedDays;
+
+    @ApiModelProperty(value = "客户回复后自动停止")
+    @TableField("follow-up_rules_replied")
+    private String followUpRulesReplied;
+
+    @ApiModelProperty(value = "客户预约后停止")
+    @TableField("follow-up_rules_appointment_booked")
+    private String followUpRulesAppointmentBooked;
+
+    @ApiModelProperty(value = "A/B测试")
+    @TableField("a_b_testing")
+    private String abTesting;
+
+    @ApiModelProperty(value = "智能调度类型")
+    @TableField("smart_scheduling_type")
+    private String smartSchedulingType;
+
+    @ApiModelProperty(value = "智能调度开始日期")
+    @TableField("smart_scheduling_start_date")
+    private LocalDate smartSchedulingStartDate;
+
+    @ApiModelProperty(value = "智能调度开始时间")
+    @TableField("smart_scheduling_start_time")
+    private String smartSchedulingStartTime;
+
+    @ApiModelProperty(value = "是否已确认内容合规")
+    @TableField("is_content_compliant")
+    private Integer isContentCompliant;
+
+    @ApiModelProperty(value = "是否已确认发送时间合理")
+    @TableField("is_schedule_approved")
+    private Integer isScheduleApproved;
+
+    @ApiModelProperty(value = "是否符合GDPR")
+    @TableField("is_gdpr_compliant")
+    private Integer isGdprCompliant;
+
+    @ApiModelProperty(value = "是否包含退订链接")
+    @TableField("has_unsubscribe_link")
+    private Integer hasUnsubscribeLink;
+
+    @ApiModelProperty(value = "进度百分比")
+    @TableField("progress_percent")
+    private Double progressPercent;
+
+    @ApiModelProperty(value = "状态 0未开始 1运行中 2暂停 3完成")
+    @TableField("status")
+    private Integer status;
+
+//    @ApiModelProperty(value = "创建者")
+//    @TableField("create_by")
+//    private Long createBy;
+//
+//    @ApiModelProperty(value = "更新者")
+//    @TableField("update_by")
+//    private Long updateBy;
+//
+//    @ApiModelProperty(value = "创建时间")
+//    @TableField("create_time")
+//    private LocalDateTime createTime;
+//
+//    @ApiModelProperty(value = "更新时间")
+//    @TableField("update_time")
+//    private LocalDateTime updateTime;
+}

+ 43 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/SopDetailEntity.java

@@ -0,0 +1,43 @@
+package com.storlead.crm.marketing.entity;
+
+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 com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("sop_detail")
+public class SopDetailEntity extends SysBaseField {
+
+    @ApiModelProperty(value = "主键id")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "SOP id")
+    @TableField("sop_id")
+    private Long sopId;
+
+    @ApiModelProperty(value = "步骤序号")
+    @TableField("step")
+    private Integer step;
+
+    @ApiModelProperty(value = "步骤名称")
+    @TableField("name")
+    private String name;
+
+    @ApiModelProperty(value = "间隔天数")
+    @TableField("days")
+    private String days;
+
+    @ApiModelProperty(value = "触达渠道")
+    @TableField("type")
+    private String type;
+
+//    @ApiModelProperty(value = "创建时间")
+//    @TableField("create_time")
+//    private LocalDateTime createTime;
+}

+ 35 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/SopEntity.java

@@ -0,0 +1,35 @@
+package com.storlead.crm.marketing.entity;
+
+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 com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("sop")
+public class SopEntity extends SysBaseField {
+
+    @ApiModelProperty(value = "SOP ID")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "SOP名称")
+    @TableField("name")
+    private String name;
+
+//    @ApiModelProperty(value = "创建人")
+//    @TableField("create_by")
+//    private String createBy;
+//
+//    @ApiModelProperty(value = "创建时间")
+//    @TableField("create_time")
+//    private LocalDateTime createTime;
+//
+//    @ApiModelProperty(value = "更新时间")
+//    @TableField("update_time")
+//    private LocalDateTime updateTime;
+}

+ 22 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/TagEntity.java

@@ -0,0 +1,22 @@
+package com.storlead.crm.marketing.entity;
+
+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 com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@TableName("tag")
+public class TagEntity extends SysBaseField {
+
+    @ApiModelProperty(value = "标签ID")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "标签名称")
+    @TableField("name")
+    private String name;
+}

+ 55 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/TemplateEntity.java

@@ -0,0 +1,55 @@
+package com.storlead.crm.marketing.entity;
+
+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 com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("template")
+public class TemplateEntity extends SysBaseField {
+
+    @ApiModelProperty(value = "模板ID")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "模板类型")
+    @TableField("type")
+    private Integer type;
+
+    @ApiModelProperty(value = "语言")
+    @TableField("language")
+    private String language;
+
+    @ApiModelProperty(value = "主题")
+    @TableField("subject")
+    private String subject;
+
+    @ApiModelProperty(value = "正文")
+    @TableField("content")
+    private String content;
+
+    @ApiModelProperty(value = "模板名称")
+    @TableField("name")
+    private String name;
+
+//    @ApiModelProperty(value = "创建人")
+//    @TableField("craete_by")
+//    private Long craeteBy;
+//
+//    @ApiModelProperty(value = "创建时间")
+//    @TableField("craete_time")
+//    private LocalDateTime craeteTime;
+//
+//    @ApiModelProperty(value = "更新人")
+//    @TableField("update_by")
+//    private Long updateBy;
+//
+//    @ApiModelProperty(value = "更新时间")
+//    @TableField("update_time")
+//    private LocalDateTime updateTime;
+}

+ 26 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/entity/TemplateTagEntity.java

@@ -0,0 +1,26 @@
+package com.storlead.crm.marketing.entity;
+
+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 com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@TableName("template_tag")
+public class TemplateTagEntity extends SysBaseField {
+
+    @ApiModelProperty(value = "主键ID")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "标签ID")
+    @TableField("tag_id")
+    private Long tagId;
+
+    @ApiModelProperty(value = "模板ID")
+    @TableField("template_id")
+    private Long templateId;
+}

+ 9 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/CustomerBaseEntityMapper.java

@@ -0,0 +1,9 @@
+package com.storlead.crm.marketing.mapper;
+
+import com.storlead.crm.marketing.entity.CustomerBaseEntity;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface CustomerBaseEntityMapper extends MyBaseMapper<CustomerBaseEntity> {
+}

+ 9 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/MarketingCampaignEntityMapper.java

@@ -0,0 +1,9 @@
+package com.storlead.crm.marketing.mapper;
+
+import com.storlead.crm.marketing.entity.MarketingCampaignEntity;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface MarketingCampaignEntityMapper extends MyBaseMapper<MarketingCampaignEntity> {
+}

+ 9 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/SopDetailEntityMapper.java

@@ -0,0 +1,9 @@
+package com.storlead.crm.marketing.mapper;
+
+import com.storlead.crm.marketing.entity.SopDetailEntity;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SopDetailEntityMapper extends MyBaseMapper<SopDetailEntity> {
+}

+ 9 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/SopEntityMapper.java

@@ -0,0 +1,9 @@
+package com.storlead.crm.marketing.mapper;
+
+import com.storlead.crm.marketing.entity.SopEntity;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SopEntityMapper extends MyBaseMapper<SopEntity> {
+}

+ 9 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/TagEntityMapper.java

@@ -0,0 +1,9 @@
+package com.storlead.crm.marketing.mapper;
+
+import com.storlead.crm.marketing.entity.TagEntity;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface TagEntityMapper extends MyBaseMapper<TagEntity> {
+}

+ 9 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/TemplateEntityMapper.java

@@ -0,0 +1,9 @@
+package com.storlead.crm.marketing.mapper;
+
+import com.storlead.crm.marketing.entity.TemplateEntity;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface TemplateEntityMapper extends MyBaseMapper<TemplateEntity> {
+}

+ 9 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/mapper/TemplateTagEntityMapper.java

@@ -0,0 +1,9 @@
+package com.storlead.crm.marketing.mapper;
+
+import com.storlead.crm.marketing.entity.TemplateTagEntity;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface TemplateTagEntityMapper extends MyBaseMapper<TemplateTagEntity> {
+}

+ 7 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/CustomerBaseEntityService.java

@@ -0,0 +1,7 @@
+package com.storlead.crm.marketing.service;
+
+import com.storlead.crm.marketing.entity.CustomerBaseEntity;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface CustomerBaseEntityService extends MyBaseService<CustomerBaseEntity> {
+}

+ 8 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/MarketingCampaignEntityService.java

@@ -0,0 +1,8 @@
+package com.storlead.crm.marketing.service;
+
+
+import com.storlead.crm.marketing.entity.MarketingCampaignEntity;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface MarketingCampaignEntityService extends MyBaseService<MarketingCampaignEntity> {
+}

+ 7 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/SopDetailEntityService.java

@@ -0,0 +1,7 @@
+package com.storlead.crm.marketing.service;
+
+import com.storlead.crm.marketing.entity.SopDetailEntity;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface SopDetailEntityService extends MyBaseService<SopDetailEntity> {
+}

+ 7 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/SopEntityService.java

@@ -0,0 +1,7 @@
+package com.storlead.crm.marketing.service;
+
+import com.storlead.crm.marketing.entity.SopEntity;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface SopEntityService extends MyBaseService<SopEntity> {
+}

+ 7 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/TagEntityService.java

@@ -0,0 +1,7 @@
+package com.storlead.crm.marketing.service;
+
+import com.storlead.crm.marketing.entity.TagEntity;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface TagEntityService extends MyBaseService<TagEntity> {
+}

+ 7 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/TemplateEntityService.java

@@ -0,0 +1,7 @@
+package com.storlead.crm.marketing.service;
+
+import com.storlead.crm.marketing.entity.TemplateEntity;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface TemplateEntityService extends MyBaseService<TemplateEntity> {
+}

+ 7 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/TemplateTagEntityService.java

@@ -0,0 +1,7 @@
+package com.storlead.crm.marketing.service;
+
+import com.storlead.crm.marketing.entity.TemplateTagEntity;
+import com.storlead.framework.mybatis.service.MyBaseService;
+
+public interface TemplateTagEntityService extends MyBaseService<TemplateTagEntity> {
+}

+ 14 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/CustomerBaseEntityServiceImpl.java

@@ -0,0 +1,14 @@
+package com.storlead.crm.marketing.service.impl;
+
+
+import com.storlead.crm.marketing.entity.CustomerBaseEntity;
+import com.storlead.crm.marketing.mapper.CustomerBaseEntityMapper;
+import com.storlead.crm.marketing.service.CustomerBaseEntityService;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CustomerBaseEntityServiceImpl
+        extends MyBaseServiceImpl<CustomerBaseEntityMapper, CustomerBaseEntity>
+        implements CustomerBaseEntityService {
+}

+ 14 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/MarketingCampaignEntityServiceImpl.java

@@ -0,0 +1,14 @@
+package com.storlead.crm.marketing.service.impl;
+
+
+import com.storlead.crm.marketing.entity.MarketingCampaignEntity;
+import com.storlead.crm.marketing.mapper.MarketingCampaignEntityMapper;
+import com.storlead.crm.marketing.service.MarketingCampaignEntityService;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MarketingCampaignEntityServiceImpl
+        extends MyBaseServiceImpl<MarketingCampaignEntityMapper, MarketingCampaignEntity>
+        implements MarketingCampaignEntityService {
+}

+ 14 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/SopDetailEntityServiceImpl.java

@@ -0,0 +1,14 @@
+package com.storlead.crm.marketing.service.impl;
+
+
+import com.storlead.crm.marketing.entity.SopDetailEntity;
+import com.storlead.crm.marketing.mapper.SopDetailEntityMapper;
+import com.storlead.crm.marketing.service.SopDetailEntityService;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SopDetailEntityServiceImpl
+        extends MyBaseServiceImpl<SopDetailEntityMapper, SopDetailEntity>
+        implements SopDetailEntityService {
+}

+ 14 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/SopEntityServiceImpl.java

@@ -0,0 +1,14 @@
+package com.storlead.crm.marketing.service.impl;
+
+
+import com.storlead.crm.marketing.entity.SopEntity;
+import com.storlead.crm.marketing.mapper.SopEntityMapper;
+import com.storlead.crm.marketing.service.SopEntityService;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SopEntityServiceImpl
+        extends MyBaseServiceImpl<SopEntityMapper, SopEntity>
+        implements SopEntityService {
+}

+ 14 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/TagEntityServiceImpl.java

@@ -0,0 +1,14 @@
+package com.storlead.crm.marketing.service.impl;
+
+
+import com.storlead.crm.marketing.entity.TagEntity;
+import com.storlead.crm.marketing.mapper.TagEntityMapper;
+import com.storlead.crm.marketing.service.TagEntityService;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TagEntityServiceImpl
+        extends MyBaseServiceImpl<TagEntityMapper, TagEntity>
+        implements TagEntityService {
+}

+ 14 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/TempalteEntityServiceImpl.java

@@ -0,0 +1,14 @@
+package com.storlead.crm.marketing.service.impl;
+
+
+import com.storlead.crm.marketing.entity.TemplateEntity;
+import com.storlead.crm.marketing.mapper.TemplateEntityMapper;
+import com.storlead.crm.marketing.service.TemplateEntityService;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TempalteEntityServiceImpl
+        extends MyBaseServiceImpl<TemplateEntityMapper, TemplateEntity>
+        implements TemplateEntityService {
+}

+ 14 - 0
java/storlead-sasa/storlead-trade/storlead-marketing/src/main/java/com/storlead/crm/marketing/service/impl/TempalteTagEntityServiceImpl.java

@@ -0,0 +1,14 @@
+package com.storlead.crm.marketing.service.impl;
+
+
+import com.storlead.crm.marketing.entity.TemplateTagEntity;
+import com.storlead.crm.marketing.mapper.TemplateTagEntityMapper;
+import com.storlead.crm.marketing.service.TemplateTagEntityService;
+import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TempalteTagEntityServiceImpl
+        extends MyBaseServiceImpl<TemplateTagEntityMapper, TemplateTagEntity>
+        implements TemplateTagEntityService {
+}