lrj 1 settimana fa
parent
commit
085b82f9ef
34 ha cambiato i file con 1746 aggiunte e 13 eliminazioni
  1. 7 0
      src/main/java/com/example/demo/DemoApplication.java
  2. 32 0
      src/main/java/com/example/demo/config/ProdAsyncConfig.java
  3. 73 0
      src/main/java/com/example/demo/controller/NoveltyController.java
  4. 18 0
      src/main/java/com/example/demo/controller/PdfController.java
  5. 27 0
      src/main/java/com/example/demo/domain/Feature.java
  6. 29 0
      src/main/java/com/example/demo/domain/Project.java
  7. 18 0
      src/main/java/com/example/demo/mapper/FeatureMapper.java
  8. 21 0
      src/main/java/com/example/demo/mapper/ProjectMapper.java
  9. 12 0
      src/main/java/com/example/demo/model/AddFeatureDTO.java
  10. 20 0
      src/main/java/com/example/demo/model/AddProjectDTO.java
  11. 11 0
      src/main/java/com/example/demo/model/ExcelVO.java
  12. 8 0
      src/main/java/com/example/demo/model/GetFeatureDTO.java
  13. 9 0
      src/main/java/com/example/demo/model/GetNoveltyMessageDTO.java
  14. 13 0
      src/main/java/com/example/demo/model/GetNoveltyMessageVO.java
  15. 20 0
      src/main/java/com/example/demo/model/common/ChatMessageDTO.java
  16. 11 0
      src/main/java/com/example/demo/model/common/DifyHistoryMessageDTO.java
  17. 155 0
      src/main/java/com/example/demo/model/common/Response.java
  18. 46 0
      src/main/java/com/example/demo/model/common/ResponseEnum.java
  19. 159 5
      src/main/java/com/example/demo/service/DifyService.java
  20. 185 0
      src/main/java/com/example/demo/service/ExcelService.java
  21. 71 0
      src/main/java/com/example/demo/service/FeatureService.java
  22. 130 0
      src/main/java/com/example/demo/service/NoveltyAiService.java
  23. 37 0
      src/main/java/com/example/demo/service/NoveltyService.java
  24. 2 2
      src/main/java/com/example/demo/service/PDFBoxService.java
  25. 39 0
      src/main/java/com/example/demo/service/ProjectService.java
  26. 313 0
      src/main/java/com/example/demo/utils/JsonUtils.java
  27. 65 0
      src/main/resources/application-dev.yml
  28. 0 1
      src/main/resources/application.properties
  29. 48 0
      src/main/resources/application.yml
  30. 2 0
      src/main/resources/config/cron.setting
  31. 110 0
      src/main/resources/config/logback-spring.xml
  32. 7 0
      src/main/resources/mapper/ProjectMapper.xml
  33. 3 5
      src/test/java/com/example/demo/DemoApplicationTests.java
  34. 45 0
      src/test/java/com/example/demo/ExcelServiceTests.java

+ 7 - 0
src/main/java/com/example/demo/DemoApplication.java

@@ -1,9 +1,16 @@
 package com.example.demo;
 
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.scheduling.annotation.EnableAsync;
 
+
+@EnableCaching
 @SpringBootApplication
+@EnableAsync
+@MapperScan(basePackages = "com.example.demo.mapper")
 public class DemoApplication {
 
     public static void main(String[] args) {

+ 32 - 0
src/main/java/com/example/demo/config/ProdAsyncConfig.java

@@ -0,0 +1,32 @@
+package com.example.demo.config;
+
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+@EnableAsync
+public class ProdAsyncConfig implements AsyncConfigurer {
+
+    @Override
+    public Executor getAsyncExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors() * 2);
+        executor.setMaxPoolSize(100);
+        executor.setQueueCapacity(200);
+        executor.setThreadNamePrefix("Prod-Async-");
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        executor.initialize();
+        return executor;
+    }
+
+    @Override
+    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+        return null; // 自定义异常处理
+    }
+}

+ 73 - 0
src/main/java/com/example/demo/controller/NoveltyController.java

@@ -0,0 +1,73 @@
+package com.example.demo.controller;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.example.demo.domain.Feature;
+import com.example.demo.model.*;
+import com.example.demo.model.common.ChatMessageDTO;
+import com.example.demo.model.common.DifyHistoryMessageDTO;
+import com.example.demo.model.common.Response;
+import com.example.demo.service.*;
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Flux;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+@RequestMapping("/novelty")
+@RestController
+public class NoveltyController {
+    @Autowired
+    private NoveltyService noveltyService;
+    @Autowired
+    private ProjectService projectService;
+    @Autowired
+    private FeatureService featureService;
+    @Autowired
+    private DifyService difyService;
+    @PostMapping("/getNoveltyMessageFromFile")
+    public Response getNoveltyMessageVOFromFile(@RequestBody GetNoveltyMessageDTO getNoveltyMessageDTO) throws Exception {
+
+        Map<String,Object> getNoveltyMessageVO = noveltyService.getNoveltyMessageVOFromFile(getNoveltyMessageDTO);
+        return Response.success(getNoveltyMessageVO);
+    }
+    @PostMapping("/addProject")
+    public Response addProject(@RequestBody AddProjectDTO addProjectDTO) throws Exception {
+                    Integer id=  projectService.addProject(addProjectDTO);
+        return Response.success(id);
+    }
+    @PostMapping("/getFeatures")
+    public Response getFeatures(@RequestBody GetFeatureDTO getFeatureDTO) throws Exception{
+     List<Feature> featureList=   featureService.getFeatures(getFeatureDTO);
+     return Response.success(featureList);
+    }
+    @PostMapping("/addFeatures")
+    public Response addFeatures(@RequestBody AddFeatureDTO addFeatureDTO) throws Exception{
+        List<Feature> featureList=   featureService.saveFeatures(addFeatureDTO);
+        return Response.success(featureList);
+    }
+
+    @PostMapping("/getNoveltyMessageVO")
+    public Response getNoveltyMessageVO(@RequestBody GetNoveltyMessageDTO getNoveltyMessageDTO) throws Exception {
+
+        GetNoveltyMessageVO getNoveltyMessageVO = noveltyService.getNoveltyMessageVO(getNoveltyMessageDTO);
+        return Response.success(getNoveltyMessageVO);
+    }
+
+    @RequestMapping(value = "/chatMessage", method = RequestMethod.POST, produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+    public Flux<String> chatMessage(@RequestBody ChatMessageDTO chatMessageDTO) throws IOException {
+        return difyService.getOkhttp(chatMessageDTO);
+    }
+    @RequestMapping(value = "/queryHistoryMessage", method = RequestMethod.POST)
+    public Response queryHistoryMessage(@RequestBody DifyHistoryMessageDTO difyHistoryMessageDTO) throws IOException {
+        String jsons = difyService.queryHistoryMessage(difyHistoryMessageDTO);
+        JSONObject jsonObject = JSONObject.parseObject(jsons);
+        return Response.success(jsonObject);
+    }
+}

+ 18 - 0
src/main/java/com/example/demo/controller/PdfController.java

@@ -0,0 +1,18 @@
+package com.example.demo.controller;
+
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.File;
+
+@RequestMapping("/claimManage")
+@RestController
+public class PdfController {
+
+    public void getPatentPictures(String pdfUrl) throws Exception {
+        PDDocument document = Loader.loadPDF(new File("D:\\demo\\file2\\202410725352_CN118294200A.pdf"));
+
+    }
+}

+ 27 - 0
src/main/java/com/example/demo/domain/Feature.java

@@ -0,0 +1,27 @@
+package com.example.demo.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 com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+
+/**
+ * @TableName feature
+ */
+@TableName(value ="feature")
+@Data
+public class Feature extends Model {
+    private Integer id;
+
+    private Integer projectId;
+
+    private String content;
+
+    private Date createTime;
+
+}

+ 29 - 0
src/main/java/com/example/demo/domain/Project.java

@@ -0,0 +1,29 @@
+package com.example.demo.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @TableName project
+ */
+@TableName(value ="project")
+@Data
+public class Project  extends Model {
+    private Integer id;
+
+    private String background;
+
+    private String benefits;
+
+    private String solution;
+
+    private String examples;
+
+    private Date createTime;
+    private String advice;
+    private String missContent;
+}

+ 18 - 0
src/main/java/com/example/demo/mapper/FeatureMapper.java

@@ -0,0 +1,18 @@
+package com.example.demo.mapper;
+
+import com.example.demo.domain.Feature;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author admin
+* @description 针对表【feature(特征表)】的数据库操作Mapper
+* @createDate 2025-08-20 10:45:34
+* @Entity generator.domain.Feature
+*/
+public interface FeatureMapper extends BaseMapper<Feature> {
+
+}
+
+
+
+

+ 21 - 0
src/main/java/com/example/demo/mapper/ProjectMapper.java

@@ -0,0 +1,21 @@
+package com.example.demo.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.demo.domain.Project;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+/**
+* @author admin
+* @description 针对表【project(项目)】的数据库操作Mapper
+* @createDate 2025-08-19 16:44:40
+* @Entity generator.domain.Project
+*/
+public interface ProjectMapper extends BaseMapper<Project> {
+
+}
+
+
+
+

+ 12 - 0
src/main/java/com/example/demo/model/AddFeatureDTO.java

@@ -0,0 +1,12 @@
+package com.example.demo.model;
+
+import com.example.demo.domain.Feature;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class AddFeatureDTO {
+    private Integer projectId;
+    private List<Feature> featureList;
+}

+ 20 - 0
src/main/java/com/example/demo/model/AddProjectDTO.java

@@ -0,0 +1,20 @@
+package com.example.demo.model;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class AddProjectDTO {
+    private Integer id;
+
+    private String background;
+
+    private String benefits;
+
+    private String solution;
+
+    private String examples;
+    private String advice;
+    private String missContent;
+}

+ 11 - 0
src/main/java/com/example/demo/model/ExcelVO.java

@@ -0,0 +1,11 @@
+package com.example.demo.model;
+
+import lombok.Data;
+
+@Data
+public class ExcelVO {
+    private String name;
+    private String timeStr;
+    private String  aiUseCount;
+    private String caseUseCount;
+}

+ 8 - 0
src/main/java/com/example/demo/model/GetFeatureDTO.java

@@ -0,0 +1,8 @@
+package com.example.demo.model;
+
+import lombok.Data;
+
+@Data
+public class GetFeatureDTO {
+    private Integer projectId;
+}

+ 9 - 0
src/main/java/com/example/demo/model/GetNoveltyMessageDTO.java

@@ -0,0 +1,9 @@
+package com.example.demo.model;
+
+import lombok.Data;
+
+@Data
+public class GetNoveltyMessageDTO {
+    private String fileId;
+    private Integer projectId;
+}

+ 13 - 0
src/main/java/com/example/demo/model/GetNoveltyMessageVO.java

@@ -0,0 +1,13 @@
+package com.example.demo.model;
+
+import lombok.Data;
+
+@Data
+public class GetNoveltyMessageVO {
+    private String background;
+    private String benefits;
+    private String solution;
+    private String examples;
+    private String advice;
+    private String missContent;
+}

+ 20 - 0
src/main/java/com/example/demo/model/common/ChatMessageDTO.java

@@ -0,0 +1,20 @@
+package com.example.demo.model.common;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class ChatMessageDTO {
+    private String query;
+    private String conversationId;
+    private Integer projectId;
+    private Integer confessionSessionId;
+    private String fileGuid;
+    private String fileId;
+    private String askType;
+    private String dataResult;
+}

+ 11 - 0
src/main/java/com/example/demo/model/common/DifyHistoryMessageDTO.java

@@ -0,0 +1,11 @@
+package com.example.demo.model.common;
+
+import lombok.Data;
+
+@Data
+public class DifyHistoryMessageDTO {
+    private String conversationId;
+    private String user;
+    private String firstId;
+    private Integer limit;
+}

+ 155 - 0
src/main/java/com/example/demo/model/common/Response.java

@@ -0,0 +1,155 @@
+package com.example.demo.model.common;
+
+import com.example.demo.utils.JsonUtils;
+
+/**
+ * Controller通用结果返回类
+ */
+public class Response {
+
+    private Integer code;
+    private Object data;
+    private String message;
+
+    public static String success() {
+        Response response = new Response();
+        response.setResultEnum(ResponseEnum.SUCCESS);
+        return JsonUtils.objectToJson(response);
+    }
+
+
+    public static Response success(Object data) {
+        Response response = new Response();
+        response.setResultEnum(ResponseEnum.SUCCESS);
+        response.setData(data);
+        return response;
+    }
+
+    public static String successBut(Object data) {
+        Response response = new Response();
+        response.setResultEnum(ResponseEnum.SUCCESSBUT);
+        response.setData(data);
+        return JsonUtils.objectToJson(response);
+    }
+
+    /**
+     * 陈宇 ↓ 直接返回对象(前台默认显示为jsonResult格式对象)
+     */
+    public static Response ok(Object data) {
+        Response response = new Response();
+        response.setResultEnum(ResponseEnum.SUCCESS);
+        response.setData(data);
+        return response;
+    }
+
+    public static Response fail() {
+        Response response = new Response();
+        response.setResultEnum(ResponseEnum.ERROR);
+        return response;
+    }
+
+    public static Response fail(Object data) {
+        Response response = new Response();
+        response.setCode(ResponseEnum.ERROR.getCode());
+        response.setMessage(data + "");
+        response.setData(data);
+        return response;
+    }
+
+    public static String websocket(Object data, ResponseEnum responseEnum) {
+        Response response = new Response();
+        response.setResultEnum(responseEnum);
+        response.setData(data);
+        return JsonUtils.objectToJson(response);
+    }
+
+    public static String error() {
+        Response response = new Response();
+        response.setData(Boolean.FALSE);
+        response.setResultEnum(ResponseEnum.ERROR);
+        return JsonUtils.objectToJson(response);
+    }
+
+    public static Response error(String message) {
+        Response response = new Response();
+        response.setCode(ResponseEnum.ERROR.getCode());
+        response.setData(Boolean.FALSE);
+        response.setMessage(message);
+        return response;
+    }
+
+
+    public static Response error(String code,String message) {
+        Integer erCode= Integer.parseInt(code);
+        Response response = new Response();
+        response.setCode(erCode);
+        response.setMessage(message);
+        return response;
+    }
+    public static Response noPermissions(String message) {
+        Response response = new Response();
+        response.setCode(ResponseEnum.NO_PERMISSION.getCode());
+        response.setData(Boolean.FALSE);
+        response.setMessage(message);
+        return response;
+    }
+
+
+    public static Response unLogin(String message) {
+        Response response = new Response();
+        response.setCode(ResponseEnum.UNAUTHORIZED.getCode());
+        response.setData(Boolean.FALSE);
+        response.setMessage(message);
+        return response;
+    }
+
+    public static Response conditionError(String message) {
+        Response response = new Response();
+        response.setCode(ResponseEnum.CONDITION_ERROR.getCode());
+        response.setData(Boolean.FALSE);
+        response.setMessage(message);
+        return response;
+    }
+    public static String error(ResponseEnum responseEnum) {
+        Response response = new Response();
+        response.setResultEnum(responseEnum);
+        return JsonUtils.objectToJson(response);
+    }
+
+    public Response(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public Response() {
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    private void setResultEnum(ResponseEnum responseEnum) {
+        this.code = responseEnum.getCode();
+        this.message = responseEnum.getMessage();
+    }
+}

+ 46 - 0
src/main/java/com/example/demo/model/common/ResponseEnum.java

@@ -0,0 +1,46 @@
+package com.example.demo.model.common;
+
+public enum ResponseEnum {
+
+    SUCCESS(200, "请求成功"),
+    UNAUTHORIZED(401, "未登录"),
+    NOT_PERMISSION(402, "无操作权限"),
+    SYSTEM_ERROR(500, "系统异常"),
+    SUCCESSBUT(200, "请求成功"),
+    ERROR(708, "请求失败"),
+    NO_PERMISSION(201,"无权限"),
+    PARAMS_ERROR(202,"参数错误"),
+    CONDITION_ERROR(203, "检索式错误"),
+    PATENT_IMPORT_TASK_SUCCESS(903, "导入任务完成"),
+    PATENT_IMPORT_PATENT_PART_SUCCESS(900, "专利信息部分上传成功"),
+    COMPARE_LITERATURE_BATCH(600,"批量上传对比文献"),
+    COMPARE_LITERATURE_BATCH_DONE(601,"批量上传对比文献完成"),
+    PATENT_EXPORT_TASK(602,"导出专利信息"),
+    PATENT_EXPORT_TASK_DONE(603,"导出专利信息完成"),
+    PATENT_PDF_EXPORT_TASK(604,"导出PDF首页"),
+    PATENT_PDF_EXPORT_TASK_DONE(605,"导出PDF首页完成");
+
+    private Integer code;
+    private String message;
+
+    ResponseEnum(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 159 - 5
src/main/java/com/example/demo/service/DifyService.java

@@ -1,25 +1,35 @@
 package com.example.demo.service;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.example.demo.model.DifyChatMessageDTO;
 import com.example.demo.model.DifyGetNumVO;
+import com.example.demo.model.common.ChatMessageDTO;
+import com.example.demo.model.common.DifyHistoryMessageDTO;
 import com.google.gson.Gson;
 import com.google.gson.JsonArray;
-import okhttp3.MediaType;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.RequestBody;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import reactor.core.publisher.Flux;
 
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.Reader;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 @Service
 public class DifyService {
+    private final         String url = "http://192.168.2.24/v1/";
+    private  final     String apiKey="app-ekzGTtvRnSq2aSqwZqKG5EH3";
+    @Value("${FileDownloadUrl}")
+    private String filePath;
     public String chatMessage(DifyChatMessageDTO difyChatMessageDTO, String key) throws IOException {
-        String url = "https://ai.xsip.cn/v1/";
+        String url = "http://192.168.2.24/v1/";
         String param = new Gson().toJson(difyChatMessageDTO);
         RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
         OkHttpClient okHttpClient = new OkHttpClient.Builder()
@@ -74,4 +84,148 @@ public class DifyService {
         vos = JSONArray.parseArray(answer, DifyGetNumVO.class);
         return vos;
     }
+
+
+    public Flux<String> getOkhttp(ChatMessageDTO chatMessageDTO) {
+
+        String conversationId = chatMessageDTO.getConversationId();
+        if(conversationId!=null&&conversationId.equals("null")){
+            conversationId=null;
+        }
+        String userId = "1";
+        String query = chatMessageDTO.getQuery();
+        String fileGuid =chatMessageDTO.getFileId();
+        String temConversationId = conversationId;
+        String askType =chatMessageDTO.getAskType();
+        String dataResult=chatMessageDTO.getDataResult();
+        OkHttpClient client = new OkHttpClient.Builder()
+                .connectTimeout(600, TimeUnit.SECONDS)
+                .writeTimeout(600, TimeUnit.SECONDS)
+                .readTimeout(600, TimeUnit.SECONDS)
+                .build();
+
+        DifyChatMessageDTO difyChatMessageDTO = new DifyChatMessageDTO();
+        Map<String, Object> map = new HashMap<>();
+        String fileContent = filePath +fileGuid ;
+        map.put("data_result",dataResult);
+        map.put("file_path", fileContent);
+        map.put("ask_type", askType);
+        difyChatMessageDTO.setInputs(map);
+        difyChatMessageDTO.setConversationId(conversationId);
+        difyChatMessageDTO.setResponseMode("streaming");
+        difyChatMessageDTO.setUser(userId);
+        difyChatMessageDTO.setQuery(query);
+        difyChatMessageDTO.setFiles(new ArrayList<>());
+
+        String param = new Gson().toJson(difyChatMessageDTO);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        Request request = this.getChatMessageRequest(requestBody);
+
+
+
+         return Flux.create(emitter ->  {
+            client.newCall(request).enqueue(new Callback() {
+                @Override
+                public void onFailure(Call call, IOException e) {
+                    emitter.error(e);
+                }
+
+                @Override
+                public void onResponse(Call call, Response response) throws IOException {
+
+                    if (!response.isSuccessful()) {
+                        emitter.error(new IOException("Unexpected code: " + response));
+                        return;
+                    }
+                    try (Reader reader = response.body().charStream()) {
+                        BufferedReader bufferedReader = new BufferedReader(reader);
+                        String line;
+                        String temConversationId2 = temConversationId;
+                        String prefixToRemove = "data: ";
+                        while ((line = bufferedReader.readLine()) != null) {
+                            if (line.isEmpty()) {
+                                continue;
+                            }
+                            if (line.startsWith(prefixToRemove)) {
+                                line = line.substring(prefixToRemove.length());
+                            }
+                            emitter.next(line); // 将每行数据发送到 Flux
+                        }
+                    } catch (IOException e) {
+                        emitter.error(e);
+                    } finally {
+                        emitter.complete();
+                    }
+
+                }
+            });
+
+
+        });
+
+//         return Flux.create(eimtter->{
+//             new Thread(()->{
+//                 eimtter.next("{\"content\":\"\",\"event\":\"all_start\",\"field\":\"\",\"id\":2142}\t\n");
+//                 eimtter.next("你好");
+//                 try {
+//                     Thread.sleep(10000);
+//                 }
+//                 catch (Exception e){
+//
+//                 }
+//                 eimtter.next("你好2");
+//                 eimtter.complete();
+//             }).start();
+//
+//
+//         });
+    }
+
+    public Request getChatMessageRequest(RequestBody requestBody) {
+        Request request = new Request.Builder()
+                .url(url + "chat-messages")
+                .addHeader("Authorization", "Bearer " + apiKey)
+                .addHeader("Accept", org.springframework.http.MediaType.TEXT_EVENT_STREAM_VALUE )
+                .post(requestBody)
+                .build();
+        return request;
+    }
+
+    public JSONObject stopMessage(String taskId) throws IOException {
+        OkHttpClient client = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        DifyChatMessageDTO difyChatMessageDTO = new DifyChatMessageDTO();
+        difyChatMessageDTO.setUser("1");
+        String param = new Gson().toJson(difyChatMessageDTO);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        Request request = new Request.Builder()
+                .url(url + "chat-messages/" + taskId + "/stop")
+                .addHeader("Authorization", "Bearer " + apiKey).addHeader(HttpHeaders.CONTENT_TYPE, "application/json")
+                .post(requestBody)
+                .build();
+        String json = Objects.requireNonNull(client.newCall(request).execute().body()).string();
+        JSONObject jsonObject = JSONObject.parseObject(json);
+        return jsonObject;
+    }
+    public String queryHistoryMessage(DifyHistoryMessageDTO difyChatMessageDTO) throws IOException {
+        difyChatMessageDTO.setUser("1");
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(600, TimeUnit.SECONDS)
+                .writeTimeout(600, TimeUnit.SECONDS)
+                .readTimeout(600, TimeUnit.SECONDS)
+                .build();
+        String path = "messages?conversation_id=" + difyChatMessageDTO.getConversationId() + "&user=" + difyChatMessageDTO.getUser() + "&limit=" + difyChatMessageDTO.getLimit();
+        if (difyChatMessageDTO.getFirstId() != null) {
+            path += "&first_id=" + difyChatMessageDTO.getFirstId();
+        }
+        Request request = new Request.Builder()
+                .url(url + path)
+                .get()
+                .addHeader("Authorization", "Bearer " + apiKey)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
 }

+ 185 - 0
src/main/java/com/example/demo/service/ExcelService.java

@@ -0,0 +1,185 @@
+package com.example.demo.service;
+
+import com.example.demo.model.ExcelVO;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class ExcelService {
+    public void test() throws Exception {
+        String readPath = "E:\\files\\select_b_PERSONNEL_NAME__DATE_FORMAT_a_c.xlsx";
+        String outPath = "E:\\files\\1.xlsx";
+        List<Map<String, String>> map = new ArrayList<>();
+        List<ExcelVO> excelVOS = new ArrayList<>();
+        FileInputStream inputStream = new FileInputStream(new File(readPath));
+
+        //1.创建工作簿,使用excel能操作的这边都看看操作
+        Workbook workbook = new XSSFWorkbook(inputStream);
+        //2.得到表
+        Sheet sheet = workbook.getSheetAt(0);
+        int rowNum = sheet.getLastRowNum();
+        String name5TimeStr = "2025-05";
+        String name6TimeStr = "2025-06";
+        String name7TimeStr = "2025-07";
+        for (int i = 0; i < rowNum; i++) {
+            Row row = sheet.getRow(i);
+
+
+            if (row.getCell(0) != null) {
+                String name = row.getCell(0).toString();
+                String timeStr = row.getCell(1).toString();
+
+                ExcelVO excelVO = excelVOS.stream().filter(item -> item.getName().equals(name) && item.getTimeStr().equals(timeStr)).findFirst().orElse(null);
+                if (excelVO == null) {
+                    excelVO = new ExcelVO();
+                    excelVO.setName(name);
+                    excelVO.setTimeStr(timeStr);
+                    if (row.getCell(2) != null) {
+                        String useNum = row.getCell(2).toString();
+                        excelVO.setAiUseCount(useNum);
+                    } else {
+                        excelVO.setAiUseCount("0");
+                    }
+                    excelVOS.add(excelVO);
+                } else {
+                    if (row.getCell(2) != null) {
+                        String useNum = row.getCell(2).toString();
+                        excelVO.setAiUseCount(useNum);
+                    } else {
+                        excelVO.setAiUseCount("0");
+                    }
+                }
+            }
+
+            if (row.getCell(6) != null) {
+                String name5 = row.getCell(6).toString();
+                name5.replace("-1", "");
+                ExcelVO excelVO = excelVOS.stream().filter(item -> item.getName().equals(name5) && item.getTimeStr().equals(name5TimeStr)).findFirst().orElse(null);
+                if (excelVO == null) {
+                    excelVO = new ExcelVO();
+                    excelVO.setName(name5);
+                    excelVO.setTimeStr(name5TimeStr);
+                    if (row.getCell(7) != null) {
+                        String useNum = row.getCell(7).toString();
+                        excelVO.setCaseUseCount(useNum);
+                    } else {
+                        excelVO.setCaseUseCount("0");
+                    }
+                    excelVOS.add(excelVO);
+                } else {
+                    if (row.getCell(7) != null) {
+                        String useNum = row.getCell(7).toString();
+                        excelVO.setCaseUseCount(useNum);
+                    } else {
+                        excelVO.setCaseUseCount("0");
+                    }
+                }
+            }
+            if (row.getCell(8) != null) {
+                String name6 = row.getCell(8).toString();
+                name6.replace("-1", "");
+                ExcelVO excelVO = excelVOS.stream().filter(item -> item.getName().equals(name6) && item.getTimeStr().equals(name6TimeStr)).findFirst().orElse(null);
+                if (excelVO == null) {
+                    excelVO = new ExcelVO();
+                    excelVO.setName(name6);
+                    excelVO.setTimeStr(name6TimeStr);
+                    if (row.getCell(9) != null) {
+                        String useNum = row.getCell(9).toString();
+                        excelVO.setCaseUseCount(useNum);
+                    } else {
+                        excelVO.setCaseUseCount("0");
+                    }
+                    excelVOS.add(excelVO);
+                } else {
+                    if (row.getCell(9) != null) {
+                        String useNum = row.getCell(9).toString();
+                        excelVO.setCaseUseCount(useNum);
+                    } else {
+                        excelVO.setCaseUseCount("0");
+                    }
+                }
+            }
+            if (row.getCell(10) != null) {
+                String name7 = row.getCell(10).toString();
+                name7.replace("-1", "");
+                ExcelVO excelVO = excelVOS.stream().filter(item -> item.getName().equals(name7) && item.getTimeStr().equals(name7TimeStr)).findFirst().orElse(null);
+                if (excelVO == null) {
+                    excelVO = new ExcelVO();
+                    excelVO.setName(name7);
+                    excelVO.setTimeStr(name7TimeStr);
+                    if (row.getCell(11) != null) {
+                        String useNum = row.getCell(11).toString();
+                        excelVO.setCaseUseCount(useNum);
+                    } else {
+                        excelVO.setCaseUseCount("0");
+                    }
+                    excelVOS.add(excelVO);
+                } else {
+                    if (row.getCell(11) != null) {
+                        String useNum = row.getCell(11).toString();
+                        excelVO.setCaseUseCount(useNum);
+                    } else {
+                        excelVO.setCaseUseCount("0");
+                    }
+                }
+            }
+        }
+        System.out.println(excelVOS);
+        List<ExcelVO> excelVOS2 = excelVOS.stream().filter(item -> item.getAiUseCount() != null).collect(Collectors.toList());
+        Set<ExcelVO> excelVOS3 = new HashSet<>();
+        excelVOS.forEach(item -> {
+            String name = item.getName();
+            String timeStr = item.getTimeStr();
+            List<ExcelVO> excelVOS1 = excelVOS.stream().filter(tem -> tem.getName().equals(name)).collect(Collectors.toList());
+            ExcelVO excelVO = excelVOS1.stream().filter(tem -> tem.getAiUseCount() != null).findFirst().orElse(null);
+            if (excelVO != null) {
+                excelVOS3.addAll(excelVOS1);
+            }
+
+        });
+        Workbook workbook2 = new XSSFWorkbook();
+        Sheet sheet1 = workbook2.createSheet();
+        int i = 0;
+        for (ExcelVO excelVO : excelVOS3) {
+            Row row = sheet1.createRow(i);
+            Cell cell = row.createCell(0);
+            cell.setCellValue(excelVO.getName());
+            Cell cell1 = row.createCell(1);
+            cell1.setCellValue(excelVO.getTimeStr());
+            Cell cell2 = row.createCell(2);
+            String aiUseCount = excelVO.getAiUseCount();
+            if (aiUseCount != null) {
+                cell2.setCellValue(excelVO.getAiUseCount().replace(".0", ""));
+            }
+            else {
+                cell2.setCellValue("0");
+
+            }
+            Cell cell3 = row.createCell(3);
+            if (excelVO.getCaseUseCount() != null&&!excelVO.getCaseUseCount().trim().equals("")) {
+                cell3.setCellValue(excelVO.getCaseUseCount().replace(".0", ""));
+            }
+            else {
+                cell3.setCellValue("0");
+
+            }
+            i++;
+        }
+        inputStream.close();
+        FileOutputStream fileOutputStream = new FileOutputStream(new File(outPath));
+        workbook2.write(fileOutputStream);
+
+
+    }
+}

+ 71 - 0
src/main/java/com/example/demo/service/FeatureService.java

@@ -0,0 +1,71 @@
+package com.example.demo.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.domain.Feature;
+import com.example.demo.mapper.FeatureMapper;
+import com.example.demo.model.AddFeatureDTO;
+import com.example.demo.model.GetFeatureDTO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author admin
+ * @description 针对表【feature(特征表)】的数据库操作Service实现
+ * @createDate 2025-08-20 10:45:34
+ */
+@Service
+public class FeatureService extends ServiceImpl<FeatureMapper, Feature> {
+    @Autowired
+    private NoveltyAiService noveltyAiService;
+
+    public List<Feature> getFeatures(GetFeatureDTO getFeatureDTO) throws Exception {
+        Integer projectId = getFeatureDTO.getProjectId();
+        List<Feature> features = this.getFeatureByProject(projectId);
+        if (features == null || features.size() == 0) {
+            features = new ArrayList<>();
+            List<String> contents = noveltyAiService.getFeatures(projectId, null, "feature");
+            for (String s : contents) {
+                Feature feature = new Feature();
+                feature.setContent(s);
+                feature.setProjectId(projectId);
+                features.add(feature);
+            }
+            AddFeatureDTO addFeatureDTO = new AddFeatureDTO();
+            addFeatureDTO.setProjectId(projectId);
+            addFeatureDTO.setFeatureList(features);
+            features = this.saveFeatures(addFeatureDTO);
+        }
+        return features;
+    }
+
+    public List<Feature> getFeatureByProject(Integer projectId) {
+        LambdaQueryWrapper<Feature> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(Feature::getProjectId, projectId);
+        List<Feature> features = this.list(queryWrapper);
+        return features;
+    }
+
+    public List<Feature> saveFeatures(AddFeatureDTO addFeatureDTO) {
+        Integer projectId = addFeatureDTO.getProjectId();
+        List<Feature> features = addFeatureDTO.getFeatureList();
+        LambdaQueryWrapper<Feature> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(Feature::getProjectId, projectId);
+        this.remove(queryWrapper);
+        if (features != null && features.size() > 0) {
+            features.forEach(item -> {
+                item.setId(null);
+                item.setProjectId(projectId);
+            });
+            this.saveBatch(features);
+        }
+        return features;
+    }
+}
+
+
+
+

File diff suppressed because it is too large
+ 130 - 0
src/main/java/com/example/demo/service/NoveltyAiService.java


+ 37 - 0
src/main/java/com/example/demo/service/NoveltyService.java

@@ -0,0 +1,37 @@
+package com.example.demo.service;
+
+import com.example.demo.domain.Project;
+import com.example.demo.model.GetNoveltyMessageDTO;
+import com.example.demo.model.GetNoveltyMessageVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+@Service
+public class NoveltyService {
+    @Value("${FileDownloadUrl}")
+    private String filePath;
+    @Autowired
+    private NoveltyAiService noveltyAiService;
+    @Autowired
+    private ProjectService projectService;
+
+    public Map<String,Object> getNoveltyMessageVOFromFile(GetNoveltyMessageDTO getNoveltyMessageDTO) throws Exception {
+        Map<String,Object> string = noveltyAiService.getNoveltyMessageVOFromFile(getNoveltyMessageDTO, null, "内容结束");
+        return string;
+    }
+
+    public GetNoveltyMessageVO getNoveltyMessageVO(GetNoveltyMessageDTO getNoveltyMessageDTO) {
+        GetNoveltyMessageVO getNoveltyMessageVO = new GetNoveltyMessageVO();
+        Integer projectId = getNoveltyMessageDTO.getProjectId();
+        Project project = projectService.getById(projectId);
+        if (project != null) {
+            BeanUtils.copyProperties(project, getNoveltyMessageVO);
+        }
+        return getNoveltyMessageVO;
+
+    }
+}

+ 2 - 2
src/main/java/com/example/demo/service/PDFBoxService.java

@@ -38,8 +38,8 @@ public class PDFBoxService {
     public void test() throws Exception {
         PDDocument document = Loader.loadPDF(new File("D:\\demo\\file2\\202410725352_CN118294200A.pdf"));
         String instruction = this.getPatentInstruction(document);
-        List<DifyGetNumVO> difyGetNumVOS = difyService.getAn();
-//        List<DifyGetNumVO> difyGetNumVOS = difyService.getAnswerFromAI(instruction);
+//        List<DifyGetNumVO> difyGetNumVOS = difyService.getAn();
+        List<DifyGetNumVO> difyGetNumVOS = difyService.getAnswerFromAI(instruction);
         int pageNum = 0;
         Integer a = document.getNumberOfPages();
         System.out.println(a);

+ 39 - 0
src/main/java/com/example/demo/service/ProjectService.java

@@ -0,0 +1,39 @@
+package com.example.demo.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.example.demo.domain.Project;
+import com.example.demo.mapper.ProjectMapper;
+import com.example.demo.model.AddProjectDTO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author admin
+ * @description 针对表【project(项目)】的数据库操作Service实现
+ * @createDate 2025-08-19 16:44:40
+ */
+@Service
+public class ProjectService extends ServiceImpl<ProjectMapper, Project> {
+    public Integer addProject(AddProjectDTO addProjectDTO) {
+        Integer id = addProjectDTO.getId();
+        Project project = new Project();
+        if (id != null) {
+            project = this.getById(id);
+            project.setBackground(addProjectDTO.getBackground());
+            project.setBenefits(addProjectDTO.getBenefits());
+            project.setExamples(addProjectDTO.getExamples());
+            project.setSolution(addProjectDTO.getSolution());
+            project.setAdvice(addProjectDTO.getAdvice());
+            project.setMissContent(addProjectDTO.getMissContent());
+            project.updateById();
+        } else {
+            BeanUtils.copyProperties(addProjectDTO, project);
+            project.insert();
+        }
+        return project.getId();
+    }
+}
+
+
+
+

+ 313 - 0
src/main/java/com/example/demo/utils/JsonUtils.java

@@ -0,0 +1,313 @@
+package com.example.demo.utils;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * json解析的工具类
+ */
+public class JsonUtils {
+
+    // 定义jackson对象
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+    public static Logger log = LoggerFactory.getLogger(JsonUtils.class);
+
+    /**
+     * 把对象转换为json数据
+     *
+     * @param obj
+     * @return 2018年5月7日  下午5:27:16
+     */
+    public static String objectToJson(Object obj) {
+        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
+        try {
+            String json = gson.toJson(obj);
+            return json;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 将Object转换成Map
+     *
+     * @param obj
+     * @return
+     */
+    public static Map<String, Object> objectToMap(Object obj) {
+
+        try {
+            Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
+            String json = gson.toJson(obj);
+            return jsonToMap(json);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 将Object类型的map转换成String类型
+     *
+     * @param map
+     * @return
+     */
+    public static Map<String, String> mapToMap(Map<String, Object> map) {
+        Map<String, String> returnMap = new HashMap<>();
+        for (String key : map.keySet()) {
+            returnMap.put(key, String.valueOf(map.get(key)));
+        }
+        return returnMap;
+    }
+
+    /**
+     * 任意类型转换成Map
+     * @return
+     */
+    public static Map<String, String> object2Map(Object obj) {
+        Map<String, String> hashMap = new HashMap();
+        try {
+            Class c = obj.getClass();
+            Method m[] = c.getDeclaredMethods();
+            for (int i = 0; i < m.length; i++) {
+                if (m[i].getName().indexOf("get")==0) {
+                    // 得到Map的key
+                    String suffixKey = m[i].getName().substring(4);
+                    String prefixKey = m[i].getName().substring(3,4).toLowerCase();
+                    hashMap.put(prefixKey + suffixKey, String.valueOf(m[i].invoke(obj, new Object[0])));
+                }
+            }
+        } catch (Throwable e) {
+            log.error(e.getMessage());
+        }
+        return hashMap;
+    }
+
+
+    /**
+     * 把json字符串转化为对象
+     *
+     * @param jsonString
+     * @param clazz
+     * @return
+     */
+    public static Object jsonToObject(String jsonString, Class<?> clazz) {
+
+        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
+        Object obj = null;
+        try {
+            obj = gson.fromJson(jsonString, clazz);
+        } catch (JsonSyntaxException e) {
+            e.printStackTrace();
+        }
+        return obj;
+    }
+
+    /**
+     * josn转arrayList
+     *
+     * @param jsonArray
+     * @return
+     */
+    public static ArrayList<?> jsonArrayToArrayList(String jsonArray) {
+
+        Gson gson = new GsonBuilder()
+                .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
+                .setDateFormat("yyyy-MM-dd HH:mm:ss")
+                .serializeNulls()
+                .create();
+        ArrayList<?> list = null;
+        try {
+            Type listType = new TypeToken<ArrayList<?>>() {
+            }.getType();
+
+            list = gson.fromJson(jsonArray, listType);
+        } catch (JsonSyntaxException e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
+
+    /**
+     * JSON 转 ArrayList
+     */
+    public static ArrayList<?> jsonArrayToArrayList(String jsonArray, Class<?> clazz) {
+
+        Gson gson = new GsonBuilder()
+                .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
+                .setDateFormat("yyyy-MM-dd HH:mm:ss")
+                .serializeNulls()
+                .create();
+        ArrayList<?> list = null;
+        try {
+
+            list = (ArrayList<?>) gson.fromJson(jsonArray, clazz);
+        } catch (JsonSyntaxException e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
+
+    /**
+     * 把json转换为map类型的数据
+     *
+     * @param json
+     * @return
+     */
+    public static Map<String, Object> jsonToMap(String json) {
+
+        Gson gson = new GsonBuilder()
+                .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
+                .setDateFormat("yyyy-MM-dd HH:mm:ss")
+                .serializeNulls()
+                .create();
+        Map<String, Object> map = null;
+        try {
+            Type type = new TypeToken<Map<String, Object>>() {
+            }.getType();
+
+            map = gson.fromJson(json, type);
+        } catch (JsonSyntaxException e) {
+            e.printStackTrace();
+        }
+        return map;
+    }
+
+    /**
+     * 将Json转换成Map<String, ?>
+     *
+     * @param json
+     * @param clazz
+     * @return
+     */
+    public static Map<String, ?> jsonToMap(String json, Class<?> clazz) {
+
+        Gson gson = new GsonBuilder()
+                .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
+                .setDateFormat("yyyy-MM-dd HH:mm:ss")
+                .serializeNulls()
+                .create();
+        Map<String, ?> map = null;
+        try {
+            Type type = new TypeToken<Map<String, ?>>() {
+            }.getType();
+
+            map = gson.fromJson(json, type);
+        } catch (JsonSyntaxException e) {
+            e.printStackTrace();
+        }
+        return map;
+    }
+
+    /**
+     * 将map转换成pojo
+     *
+     * @param map
+     * @param beanType
+     * @param <T>
+     * @return
+     */
+    public static <T> T mapToPojo(Map<String, Object> map, Class<T> beanType) {
+
+        Gson gson = new GsonBuilder()
+                .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
+                .setDateFormat("yyyy-MM-dd HH:mm:ss")
+                .serializeNulls()
+                .create();
+
+        JsonElement jsonElement = gson.toJsonTree(map);
+        T pojo = gson.fromJson(jsonElement, beanType);
+
+        return pojo;
+    }
+
+    /**
+     * 将json结果集转化为对象
+     *
+     * @param jsonData
+     * @param beanType
+     * @param <T>
+     * @return
+     */
+    public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
+        try {
+            T t = MAPPER.readValue(jsonData, beanType);
+            return t;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 将json数据转换成pojo对象list
+     *
+     * @param jsonData
+     * @param beanType
+     * @return
+     */
+    public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
+        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
+        try {
+            List<T> list = MAPPER.readValue(jsonData, javaType);
+            return list;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /**
+     * 将任意pojo转化成map
+     *
+     * @param t pojo对象
+     * @return
+     */
+    public static <T> Map<String, Object> pojoToMap(T t) {
+        Map<String, Object> result = new HashMap<String, Object>();
+        Method[] methods = t.getClass().getMethods();
+        try {
+            for (Method method : methods) {
+                Class<?>[] paramClass = method.getParameterTypes();
+                // 如果方法带参数,则跳过
+                if (paramClass.length > 0) {
+                    continue;
+                }
+                String methodName = method.getName();
+                if (methodName.startsWith("get")) {
+                    Object value = method.invoke(t);
+                    result.put(methodName, value);
+                }
+            }
+        } catch (IllegalArgumentException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        } catch (InvocationTargetException e) {
+            e.printStackTrace();
+        } catch (SecurityException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+}

+ 65 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,65 @@
+spring:
+  rabbitmq:
+    host: 192.168.2.24
+    port: 5672
+    username: admin
+    password: 123456
+  data:
+    redis:
+      host: 192.168.2.24
+      port: 6379
+      database: 3
+      password: Xx0GWxdWQJxx6Swe
+      lettuce:
+        pool:
+          max-active: 20
+          max-idle: 20
+          min-idle: 0
+          max-wait: -1ms
+      timeout: 2000ms
+  datasource:
+    url: jdbc:mysql://192.168.2.24:3306/novelty?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=GMT%2B8
+    username: root
+    password: rrzTwWAYX8Gxh5JH
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    type: com.alibaba.druid.pool.DruidDataSource
+    druid:
+      stat-view-servlet:
+        login-username: admin
+        login-password: Cslg2022+
+      web-stat-filter:
+        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
+
+authorUrl: http://192.168.2.24:8871
+PCSUrl: http://192.168.2.24:8871
+#OPSUrl: http://192.168.2.24:5001
+OPSUrl: http://47.116.194.135:5001
+PASUrl: http://localhost:8879
+FMSUrl: http://192.168.2.24:8803
+WDUrl: http://1.116.113.26:81
+PythonUrl: http://192.168.2.24:8001
+FileDownloadUrl: http://192.168.2.24:8803/fileManager/downloadFile?fileId=
+FileSource: 1
+ES:
+  patentVector: patent_vector
+  patent: wxpatent
+  config: 192.168.2.24
+WDSYS:
+  account: caiyangl
+  password: Lqftiu807005
+management:
+  endpoints:
+    web:
+      exposure:
+        include: "*"
+  endpoint:
+    health:
+      show-details: always
+DIFY:
+  apiKey: app-DDGJt4QUmzlc2aFQ5voOAXIj
+#  cliamKey: app-fxpiWOYqtJM1BOaJnG54NlCZ
+  OAApiKey: app-NvKwdHvEK2UmJdmjTGDR0xu6
+  checkApiKey: aa
+  cliamKey: app-jF3akhYKgljPLdpeIpTNbs6f
+  gInstructionKey: app-7ImBmlr7kvBTSvBj1mTvgKyp
+  url: http://192.168.2.24/v1/

+ 0 - 1
src/main/resources/application.properties

@@ -1 +0,0 @@
-spring.application.name=demo

+ 48 - 0
src/main/resources/application.yml

@@ -0,0 +1,48 @@
+server:
+  servlet:
+    context-path: /
+  port: 8071
+#  sa-token:
+#  activity-timeout: 18000
+#  token-name: token
+#  token-style: tik
+spring:
+  thymeleaf:
+    cache: false
+    mode: HTML5
+  aop:
+    auto: true
+    proxy-target-class: true
+  application:
+    name: pas
+  servlet:
+    multipart:
+      max-file-size: 1000MB
+      max-request-size: 1000MB
+  profiles:
+    active: dev
+  jackson:
+    default-property-inclusion: non_null
+    serialization:
+      INDENT_OUTPUT: true
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: Asia/Shanghai
+logging:
+  config: classpath:config/logback-spring.xml
+  level:
+    cn.cslg.pas.mapper: debug
+#mybatis
+mybatis-plus:
+  typeAliasesPackage: com.example.demo.domain
+  global-config:
+    db-config:
+      id-type: AUTO
+      logic-delete-value: 0
+      logic-not-delete-value: 1
+      update-strategy: ALWAYS
+  configuration:
+    #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+  mapper-locations: classpath:mapper/*.xml
+queueName: emailProd.queue

+ 2 - 0
src/main/resources/config/cron.setting

@@ -0,0 +1,2 @@
+[cn.cslg.pas.common.utils]
+BackupUtils.run = 00 03 * * *

+ 110 - 0
src/main/resources/config/logback-spring.xml

@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <contextName>${APP_NAME}</contextName>
+
+    <springProperty name="APP_NAME" scope="context" source="spring.application.name"/>
+    <springProperty name="LOG_FILE" scope="context" source="logging.file" defaultValue="./logs/${APP_NAME}"/>
+    <springProperty name="LOG_POINT_FILE" scope="context" source="logging.file" defaultValue="./logs/point"/>
+    <springProperty name="LOG_MAXFILESIZE" scope="context" source="logback.filesize" defaultValue="50MB"/>
+    <springProperty name="LOG_FILEMAXDAY" scope="context" source="logback.filemaxday" defaultValue="7"/>
+    <springProperty name="ServerIP" scope="context" source="server.address" defaultValue="0.0.0.0"/>
+    <springProperty name="ServerPort" scope="context" source="server.port" defaultValue="0000"/>
+
+    <!-- 彩色日志 -->
+    <!-- 彩色日志依赖的渲染类 -->
+    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
+    <conversionRule conversionWord="wex"
+                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
+    <conversionRule conversionWord="wEx"
+                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
+
+    <!-- 彩色日志格式 -->
+    <property name="CONSOLE_LOG_PATTERN"
+              value="[${APP_NAME}:${ServerIP}:${ServerPort}] [%clr(%X{traceid}){yellow},%clr(%X{X-B3-TraceId}){yellow}] %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr(${PID}){magenta} %clr([%thread]){orange} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
+    <property name="CONSOLE_LOG_PATTERN_NO_COLOR"
+              value="[${APP_NAME}:${ServerIP}:${ServerPort}] [%X{traceid},%X{X-B3-TraceId}] %d{yyyy-MM-dd HH:mm:ss.SSS} %level ${PID} [%thread] %logger %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
+
+
+    <!-- 控制台日志 -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <withJansi>true</withJansi>
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <!-- 按照每天生成常规日志文件 -->
+    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_FILE}/${APP_NAME}-error.log</file>
+        <!-- 基于时间的分包策略 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_FILE}/${APP_NAME}-error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <!--保留时间,单位:天-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <MaxFileSize>100MB</MaxFileSize>
+        </triggeringPolicy>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 按照每天生成常规日志文件 -->
+    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_FILE}/${APP_NAME}-info.log</file>
+        <!-- 基于时间的分包策略 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_FILE}/${APP_NAME}-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <!--保留时间,单位:天-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>INFO</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 按照每天生成常规日志文件 -->
+    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_FILE}/${APP_NAME}-debug.log</file>
+        <!-- 基于时间的分包策略 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_FILE}/${APP_NAME}-debug.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <!--保留时间,单位:天-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>DEBUG</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="ERROR"/>
+        <appender-ref ref="INFO"/>
+        <appender-ref ref="DEBUG"/>
+    </root>
+
+</configuration>

+ 7 - 0
src/main/resources/mapper/ProjectMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.demo.mapper.ProjectMapper">
+
+</mapper>

+ 3 - 5
src/test/java/com/example/demo/DemoApplicationTests.java

@@ -4,10 +4,7 @@ import com.example.demo.model.DifyGetNumVO;
 import com.example.demo.model.DrawMessVO;
 import com.example.demo.model.PictureNumVO;
 import com.example.demo.model.PicturePositionVO;
-import com.example.demo.service.DifyService;
-import com.example.demo.service.GetPictureNumService;
-import com.example.demo.service.ImageCoordinateExtractor;
-import com.example.demo.service.PDFBoxService;
+import com.example.demo.service.*;
 import net.sourceforge.tess4j.ITesseract;
 import net.sourceforge.tess4j.Tesseract;
 import net.sourceforge.tess4j.TesseractException;
@@ -54,7 +51,8 @@ class DemoApplicationTests {
     private PDFBoxService pdfBoxService;
     @Autowired
     private DifyService difyService;
-
+    @Autowired
+    private ExcelService excelService;
     @Test
     void contextLoads() throws Exception {
 

+ 45 - 0
src/test/java/com/example/demo/ExcelServiceTests.java

@@ -0,0 +1,45 @@
+package com.example.demo;
+
+import com.example.demo.model.PictureNumVO;
+import com.example.demo.model.PicturePositionVO;
+import com.example.demo.service.*;
+import net.sourceforge.tess4j.ITesseract;
+import net.sourceforge.tess4j.Tesseract;
+import net.sourceforge.tess4j.Word;
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.bytedeco.opencv.global.opencv_core;
+import org.bytedeco.opencv.opencv_core.Mat;
+import org.bytedeco.opencv.opencv_core.Scalar;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.List;
+
+import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
+import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
+
+
+@SpringBootTest
+class ExcelServiceTests {
+    @Autowired
+    private GetPictureNumService getPictureNumService;
+    @Autowired
+    private PDFBoxService pdfBoxService;
+    @Autowired
+    private DifyService difyService;
+    @Autowired
+    private ExcelService excelService;
+
+    @Test
+    public void test() throws Exception {
+        excelService.test();
+        System.out.println("a");
+    }
+}