From fc38e2635216775a80210d0df109dc6174d66813 Mon Sep 17 00:00:00 2001
From: yangbin <yangbin@qq.com>
Date: 星期四, 15 八月 2024 13:57:07 +0800
Subject: [PATCH] 1

---
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FileImgInfo.java                |   58 +
 lxzn-module-system/lxzn-system-start/src/main/resources/application-dev.yml              |    5 
 lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfTurnPngUtils.java                |  115 +++
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/ItemPosition.java                   |   17 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IWebSocketAiService.java       |   14 
 pom.xml                                                                                  |   23 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FilePdfInfoMapper.xml       |    5 
 lxzn-module-ai/src/main/java/org/jeecg/modules/utils/file/FileUtils.java                 |  327 +++++++++
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPosition.java                |   16 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FileImgInfoController.java  |   66 +
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FilePdfInfoServiceImp.java |  133 +++
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FilePdfInfoMapper.java          |   12 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFileImgInfoService.java       |   36 +
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/WebSocketAiService.java    |   28 
 lxzn-module-ai/src/main/java/org/jeecg/modules/utils/AiTestUils.java                     |  101 ++
 lxzn-module-system/lxzn-system-start/src/main/resources/jeecg/jeecg_config.properties    |    2 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/websocket/AiWebSocket.java             |  191 +++++
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FilePdfInfo.java                |   59 +
 lxzn-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java                   |    6 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPositionVo.java              |   17 
 lxzn-module-system/lxzn-system-start/src/test/java/org/jeecg/modules/ai/AiTest.java      |   80 ++
 lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfUtils.java                       |  263 +++++++
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFilePdfInfoService.java       |   33 
 /dev/null                                                                                |   17 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FilePdfInfoController.java  |   59 +
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/MyTextExtractionStrategy.java       |   64 +
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FileImgInfoMapper.xml       |    5 
 lxzn-module-system/lxzn-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java |    2 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FileImgInfoServiceImp.java |   58 +
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/FilePdfSelectVo.java                |   15 
 lxzn-module-ai/src/main/java/org/jeecg/modules/utils/DateUtil.java                       |  142 ++++
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/PhotoListVo.java                    |   27 
 lxzn-module-system/lxzn-system-start/src/main/resources/application-prod.yml             |   12 
 lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FileImgInfoMapper.java          |   12 
 34 files changed, 1,987 insertions(+), 33 deletions(-)

diff --git a/lxzn-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java b/lxzn-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
index ec8ed1c..fbe9bda 100644
--- a/lxzn-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
+++ b/lxzn-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
@@ -100,7 +100,7 @@
                 .securitySchemes(Collections.singletonList(securityScheme()))
                 .securityContexts(securityContexts())
                 .globalOperationParameters(setHeaderToken())
-                .groupName("MDC");
+                .groupName("AI");
     }
 
     /***
@@ -133,14 +133,14 @@
     private ApiInfo apiInfo() {
         return new ApiInfoBuilder()
                 // //澶ф爣棰�
-                .title("JeecgBoot 鍚庡彴鏈嶅姟API鎺ュ彛鏂囨。")
+                .title(" 鍚庡彴鏈嶅姟API鎺ュ彛鏂囨。")
                 // 鐗堟湰鍙�
                 .version("1.0")
 //				.termsOfServiceUrl("NO terms of service")
                 // 鎻忚堪
                 .description("鍚庡彴API鎺ュ彛")
                 // 浣滆��
-                .contact(new Contact("鍖椾含鍥界偓淇℃伅鎶�鏈湁闄愬叕鍙�","www.jeccg.com","jeecgos@163.com"))
+                .contact(new Contact("瑗垮畨鐏电","www.xalxzn.com","xalxzn.com"))
                 .license("The Apache License, Version 2.0")
                 .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
                 .build();
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FileImgInfoController.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FileImgInfoController.java
new file mode 100644
index 0000000..ec441b9
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FileImgInfoController.java
@@ -0,0 +1,66 @@
+package org.jeecg.modules.ai.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.common.util.StrUtils;
+import org.jeecg.modules.ai.entity.FileImgInfo;
+import org.jeecg.modules.ai.entity.FilePdfInfo;
+import org.jeecg.modules.ai.service.IFileImgInfoService;
+import org.jeecg.modules.ai.service.IFilePdfInfoService;
+import org.jeecg.modules.ai.vo.FilePdfSelectVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author clown
+ * * @date 2024/8/9
+ */
+@Slf4j
+@Api(tags = "PDF鍥剧墖鏂囦欢绠$悊")
+@RestController
+@RequestMapping("/ai/fileImg")
+public class FileImgInfoController extends JeecgController<FileImgInfo, IFileImgInfoService> {
+
+    @Autowired
+    private IFilePdfInfoService filePdfInfoService;
+
+    @AutoLog(value = "鍒嗛〉鍒楄〃鏌ヨ")
+    @ApiOperation(value = "鍒嗛〉鍒楄〃鏌ヨ", notes = "鍒嗛〉鍒楄〃鏌ヨ")
+    @GetMapping(value = "/list")
+    public Result<?> queryPageList(FilePdfSelectVo vo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize){
+
+        Page page = new Page<>(pageNo, pageSize);
+        FilePdfInfo info = null;
+        if (StrUtils.isNotBlankOrNull(vo.getPdfFileId())) {
+            info = filePdfInfoService.getById(vo.getPdfFileId());
+        } else if (StrUtils.isNotBlankOrNull(vo.getPdfName())) {
+            info = filePdfInfoService.findNewFilePDF(vo.getPdfName());
+        }
+
+        if (info == null) {
+            return Result.error("鏃犳鏂囦欢");
+        }
+        IPage<FileImgInfo> imgInfos = service.queryPageList(info.getId(), page);
+        return Result.OK(imgInfos);
+    }
+
+
+
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FilePdfInfoController.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FilePdfInfoController.java
new file mode 100644
index 0000000..cd3643a
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/controller/FilePdfInfoController.java
@@ -0,0 +1,59 @@
+package org.jeecg.modules.ai.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.modules.ai.entity.FileImgInfo;
+import org.jeecg.modules.ai.entity.FilePdfInfo;
+import org.jeecg.modules.ai.service.IFilePdfInfoService;
+import org.jeecg.modules.ai.vo.FilePdfSelectVo;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/8/7
+ */
+@Slf4j
+@Api(tags = "PDF鏂囦欢绠$悊")
+@RestController
+@RequestMapping("/ai/filePdf")
+public class FilePdfInfoController extends JeecgController<FilePdfInfo, IFilePdfInfoService> {
+
+    @AutoLog(value = "PDF鏂囦欢绠$悊-妫�绱㈡煡璇�")
+    @ApiOperation(value = "PDF鏂囦欢绠$悊-妫�绱㈡煡璇�", notes = "PDF鏂囦欢绠$悊-妫�绱㈡煡璇�")
+    @PutMapping(value = "/findImgList")
+    public Result<?> findImgPathList(@RequestBody FilePdfSelectVo vo) {
+        List<FileImgInfo> infos =  service.findImgPathList(vo);
+        /*Thread.sleep();*/
+        return Result.OK(infos);
+    }
+
+   /* @AutoLog(value = "aiTest")
+    @ApiOperation(value = "aiTest", notes = "aiTest")*/
+    @GetMapping(value = "/aiTest")
+    public Result<?> aiTest(String nameList) {
+       /* String name = "{\"id\":\"683a65fd-8feb-4446-ad32-714c4785f667\",\"messages\":[{\"role\":\"user\",\"content\":\"缁欐垜璁蹭釜鏁呬簨锛焅"}],\"stream\":true,\"max_tokens\":500}"; // JSON鏁版嵁
+        String url = "https://836u458t54.vicp.fun/chat/test_chat";
+        String aiPost =  AiTestUils.sendJsonToHttpsPost(url, name);*/
+
+        String s = "\"data\": {\"id\": \"683a65fd-8feb-4446-ad32-714c4785f667\", \"created\": 1723105518, \"model\": \"YxCareer0.7\", \"choices\": [{\"index\": 0, \"delta\": {\"role\": \"assistant\", \"content\": \"\"}, \"finish_reason\": null}]}";
+        System.out.println(s.replace("data:" ,""));
+        return Result.OK("");
+    }
+
+
+    @AutoLog(value = "PDF鏂囦欢鍒楄〃")
+    @ApiOperation(value = "PDF鏂囦欢鍒楄〃", notes = "PDF鏂囦欢鍒楄〃")
+    @GetMapping(value = "/filePdfList")
+    public Result<?> aiFindFiles() {
+        List<FilePdfInfo> infos = service.list();
+        return Result.OK(infos);
+    }
+
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FileImgInfo.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FileImgInfo.java
new file mode 100644
index 0000000..4e7b6a4
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FileImgInfo.java
@@ -0,0 +1,58 @@
+package org.jeecg.modules.ai.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author clown
+ * * @date 2024/8/1
+ */
+@Data
+@TableName("ai_file_img_info")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class FileImgInfo implements Serializable {
+    private static final long serialVersionUID = 1519876512924700514L;
+    @TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "涓婚敭")
+    private String id;
+    private String fileId;
+    /*椤电爜*/
+    private Integer pageNumber;
+    /*鍥剧墖璺緞*/
+    private String imgPath;
+    /*鍥剧墖鍚嶇О*/
+    private String imgName;
+
+    private String imgEncodeName;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    private Date createTime;
+    @Excel(name = "鍒涘缓浜�",width = 15)
+    @ApiModelProperty("鍒涘缓浜�")
+    private String createBy;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    private Date updateTime;
+    @Excel(name = "鏇存柊浜�",width = 15)
+    @ApiModelProperty("鏇存柊浜�")
+    private String updateBy;
+    @Excel(name = "鍒犻櫎鐘舵��", width = 15, dicCode = "del_flag")
+    @ApiModelProperty(value = "鍒犻櫎鐘舵�侊紙0锛屾甯革紝1宸插垹闄わ級")
+    private String delFlag;
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FilePdfInfo.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FilePdfInfo.java
new file mode 100644
index 0000000..b4b5a46
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/entity/FilePdfInfo.java
@@ -0,0 +1,59 @@
+package org.jeecg.modules.ai.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author clown
+ * * @date 2024/8/1
+ */
+@Data
+@TableName("ai_file_pdf_Info")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class FilePdfInfo implements Serializable {
+    private static final long serialVersionUID = 1519876512924700514L;
+    @TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "涓婚敭")
+    private String id;
+    private String filePath;
+    private String fileName;
+    // 鏂囦欢鍔犲瘑鍚庣殑鍚嶇О
+    private String fileEncodeName;
+    // 鏂囦欢澶у皬锛圞B锛�
+    private Long fileSize;
+    // 鏂囦欢鍚庣紑
+    private String fileSuffix;
+    /*鏁版帶绯荤粺*/
+    private String controlSystem;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    private Date createTime;
+    @Excel(name = "鍒涘缓浜�",width = 15)
+    @ApiModelProperty("鍒涘缓浜�")
+    private String createBy;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    private Date updateTime;
+    @Excel(name = "鏇存柊浜�",width = 15)
+    @ApiModelProperty("鏇存柊浜�")
+    private String updateBy;
+    @Excel(name = "鍒犻櫎鐘舵��", width = 15, dicCode = "del_flag")
+    @ApiModelProperty(value = "鍒犻櫎鐘舵�侊紙0锛屾甯革紝1宸插垹闄わ級")
+    private String delFlag;
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FileImgInfoMapper.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FileImgInfoMapper.java
new file mode 100644
index 0000000..8c24a5a
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FileImgInfoMapper.java
@@ -0,0 +1,12 @@
+package org.jeecg.modules.ai.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.ai.entity.FileImgInfo;
+
+/**
+ * @author clown
+ * * @date 2024/8/5
+ */
+public interface FileImgInfoMapper extends BaseMapper<FileImgInfo> {
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FilePdfInfoMapper.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FilePdfInfoMapper.java
new file mode 100644
index 0000000..7423eb1
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/FilePdfInfoMapper.java
@@ -0,0 +1,12 @@
+package org.jeecg.modules.ai.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.ai.entity.FilePdfInfo;
+
+/**
+ * @author clown
+ * * @date 2024/8/5
+ */
+public interface FilePdfInfoMapper extends BaseMapper<FilePdfInfo> {
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FileImgInfoMapper.xml b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FileImgInfoMapper.xml
new file mode 100644
index 0000000..0341bb7
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FileImgInfoMapper.xml
@@ -0,0 +1,5 @@
+<?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="org.jeecg.modules.ai.mapper.FileImgInfoMapper">
+
+</mapper>
\ No newline at end of file
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FilePdfInfoMapper.xml b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FilePdfInfoMapper.xml
new file mode 100644
index 0000000..ccf33cc
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/mapper/xml/FilePdfInfoMapper.xml
@@ -0,0 +1,5 @@
+<?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="org.jeecg.modules.ai.mapper.FilePdfInfoMapper">
+
+</mapper>
\ No newline at end of file
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFileImgInfoService.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFileImgInfoService.java
new file mode 100644
index 0000000..27c5a6f
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFileImgInfoService.java
@@ -0,0 +1,36 @@
+package org.jeecg.modules.ai.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.ai.entity.FileImgInfo;
+import org.jeecg.modules.ai.vo.FilePdfSelectVo;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/8/5
+ */
+public interface IFileImgInfoService extends IService<FileImgInfo> {
+
+    /**
+     * 瑙f瀽pdf鏂囦欢锛岀敓鎴愬浘鐗囦繚瀛樿褰�
+     * @param file
+     * @return
+     */
+    boolean analysisPDfFromFile(File file);
+
+    /**
+     *
+     * @param fileId
+     * @param pageNumbers
+     * @return
+     */
+    List<FileImgInfo> findFileImgInfos(String fileId,List<Integer> pageNumbers);
+
+
+    IPage<FileImgInfo> queryPageList(String fileId, Page page);
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFilePdfInfoService.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFilePdfInfoService.java
new file mode 100644
index 0000000..d539e04
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IFilePdfInfoService.java
@@ -0,0 +1,33 @@
+package org.jeecg.modules.ai.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.ai.entity.FileImgInfo;
+import org.jeecg.modules.ai.entity.FilePdfInfo;
+import org.jeecg.modules.ai.vo.FilePdfSelectVo;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/8/5
+ */
+public interface IFilePdfInfoService extends IService<FilePdfInfo> {
+
+    /**
+     * 鏂囦欢
+     * @param file
+     * @return
+     */
+    boolean uploadFilePdf(File file);
+
+    /**
+     *
+     * @param fileVo
+     * @return
+     */
+    List<FileImgInfo> findImgPathList(FilePdfSelectVo fileVo);
+
+
+    FilePdfInfo findNewFilePDF(String fileName);
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IWebSocketAiService.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IWebSocketAiService.java
new file mode 100644
index 0000000..937f0c8
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/IWebSocketAiService.java
@@ -0,0 +1,14 @@
+package org.jeecg.modules.ai.service;
+
+/**
+ * @author clown
+ * * @date 2024/8/8
+ */
+public interface IWebSocketAiService {
+
+
+    /**
+     * 鏌ヨ
+     */
+    void selectChatIA();
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FileImgInfoServiceImp.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FileImgInfoServiceImp.java
new file mode 100644
index 0000000..fe6c455
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FileImgInfoServiceImp.java
@@ -0,0 +1,58 @@
+package org.jeecg.modules.ai.service.imp;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
+import com.baomidou.mybatisplus.core.incrementer.ImadcnIdentifierGenerator;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.incrementer.KingbaseKeyGenerator;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.hibernate.HibernateException;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.id.IdentifierGenerator;
+import org.jeecg.modules.ai.entity.FileImgInfo;
+import org.jeecg.modules.ai.entity.FilePdfInfo;
+import org.jeecg.modules.ai.mapper.FileImgInfoMapper;
+import org.jeecg.modules.ai.service.IFileImgInfoService;
+import org.jeecg.modules.ai.service.IFilePdfInfoService;
+import org.jeecg.modules.ai.vo.FilePdfSelectVo;
+import org.jeecg.modules.utils.BeanMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/8/5
+ */
+@Service
+public class FileImgInfoServiceImp extends ServiceImpl<FileImgInfoMapper,FileImgInfo> implements IFileImgInfoService {
+
+    @Override
+    public boolean analysisPDfFromFile(File file) {
+        return false;
+    }
+
+
+    @Override
+    public List<FileImgInfo> findFileImgInfos(String fileId,List<Integer>  pageNumbers) {
+        List<FileImgInfo> mdcPlanCloses = this.getBaseMapper().
+                selectList(new LambdaQueryWrapper<FileImgInfo>().
+                in(FileImgInfo::getPageNumber, pageNumbers).
+                eq(FileImgInfo::getFileId,fileId).
+                orderByAsc(FileImgInfo::getPageNumber)
+                );
+        return mdcPlanCloses;
+    }
+
+    @Override
+    public IPage<FileImgInfo> queryPageList(String fileId, Page page) {
+        LambdaQueryWrapper<FileImgInfo> wrapper =new LambdaQueryWrapper<>();
+        wrapper.eq(FileImgInfo::getFileId,fileId);
+        return baseMapper.selectPage(page,wrapper);
+    }
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FilePdfInfoServiceImp.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FilePdfInfoServiceImp.java
new file mode 100644
index 0000000..a866ee2
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/FilePdfInfoServiceImp.java
@@ -0,0 +1,133 @@
+package org.jeecg.modules.ai.service.imp;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.api.vo.FileUploadResult;
+import org.jeecg.modules.ai.entity.FileImgInfo;
+import org.jeecg.modules.ai.entity.FilePdfInfo;
+import org.jeecg.modules.ai.mapper.FilePdfInfoMapper;
+import org.jeecg.modules.ai.service.IFileImgInfoService;
+import org.jeecg.modules.ai.service.IFilePdfInfoService;
+import org.jeecg.modules.ai.vo.FilePdfSelectVo;
+import org.jeecg.modules.ai.vo.KeyWordPositionVo;
+import org.jeecg.modules.ai.vo.PhotoListVo;
+import org.jeecg.modules.utils.BeanMapper;
+import org.jeecg.modules.utils.DateUtil;
+import org.jeecg.modules.utils.PdfTurnPngUtils;
+import org.jeecg.modules.utils.PdfUtils;
+import org.jeecg.modules.utils.file.FileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.crypto.KeyGenerator;
+import java.io.File;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @author clown
+ * * @date 2024/8/5
+ */
+@Service
+public class FilePdfInfoServiceImp extends ServiceImpl<FilePdfInfoMapper,FilePdfInfo> implements IFilePdfInfoService {
+
+    @Autowired
+    private IFileImgInfoService fileImgInfoService;
+
+    @Value("${jeecg.path.upload}")
+    public String fileUploadFolder;
+
+
+
+    @Override
+    public boolean uploadFilePdf(File file) {
+        FileUploadResult result = FileUtils.uploadFileInFile(file);
+        FilePdfInfo info = new FilePdfInfo();
+        info.setFileName(result.getFileName());
+        info.setFileEncodeName(result.getFileEncodeName());
+        info.setFilePath(result.getFilePath());
+        info.setFileSize(result.getFileSize());
+        info.setFileSuffix(result.getFileSuffix());
+        boolean b = save(info);
+        if (!b) {
+            return false;
+        }
+        try {
+            List<PhotoListVo> pngList = PdfTurnPngUtils.pdf2pngList(file,"png",info.getId());
+            if (pngList == null || pngList.isEmpty() ) {
+                return false;
+            }
+            List<FileImgInfo> fileImgs = new ArrayList<>();
+            for (PhotoListVo vo : pngList) {
+                FileImgInfo img = new FileImgInfo();
+                BeanMapper.copy(vo,img);
+                img.setFileId(info.getId());
+                fileImgs.add(img);
+            }
+
+            boolean c = fileImgInfoService.saveBatch(fileImgs);
+            if (c) {
+                return true;
+            } else {
+                removeById(info.getId());
+                return false;
+            }
+
+        } catch (Exception e) {
+            removeById(info.getId());
+            return false;
+        }
+
+    }
+
+    @Override
+    public List<FileImgInfo> findImgPathList(FilePdfSelectVo fileVo) {
+        FilePdfInfo info = new FilePdfInfo();
+        if (StringUtils.isNotBlank(fileVo.getPdfFileId())) {
+            info = super.getById(fileVo.getPdfFileId());
+        } else {
+            //寰呬紭鍖�
+            List<FilePdfInfo> list = super.list(new LambdaQueryWrapper<FilePdfInfo>().
+                    eq(FilePdfInfo::getFileName, fileVo.getPdfName()).
+                    orderByDesc(FilePdfInfo::getCreateTime)
+            );
+            if (list == null || list.isEmpty()) {
+                return null;
+            }
+            BeanMapper.copy(list.get(0),info);
+        }
+        if (info == null ) {
+            return null;
+        }
+        List<KeyWordPositionVo> workVo = PdfUtils.findListWord(fileUploadFolder + "/" + info.getFilePath() + "/" + info.getFileEncodeName(),fileVo.getPdfContent());
+        if (workVo == null || workVo.isEmpty()) {
+            return null;
+        }
+        List<Integer> sb = new ArrayList<>();
+        for (KeyWordPositionVo key : workVo) {
+            sb.add(key.getPage());
+        }
+        List<FileImgInfo> list = fileImgInfoService.findFileImgInfos(fileVo.getPdfFileId(),sb);
+        return list;
+    }
+
+    @Override
+    public FilePdfInfo findNewFilePDF(String fileName) {
+        FilePdfInfo info = new FilePdfInfo();
+        List<FilePdfInfo> list = super.list(new LambdaQueryWrapper<FilePdfInfo>().
+                eq(FilePdfInfo::getFileName, fileName).
+                orderByDesc(FilePdfInfo::getCreateTime)
+        );
+        if (list == null || list.isEmpty()) {
+            return null;
+        }
+        BeanMapper.copy(list.get(0),info);
+        return info;
+    }
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/WebSocketAiService.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/WebSocketAiService.java
new file mode 100644
index 0000000..eb287ea
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/service/imp/WebSocketAiService.java
@@ -0,0 +1,28 @@
+package org.jeecg.modules.ai.service.imp;
+
+import org.jeecg.modules.ai.service.IWebSocketAiService;
+import org.jeecg.modules.ai.websocket.AiWebSocket;
+import org.jeecg.modules.utils.AiTestUils;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author clown
+ * * @date 2024/8/8
+ */
+@Service
+public class WebSocketAiService implements IWebSocketAiService {
+
+
+    @Override
+    @Scheduled(cron = "0/10 * * * * ?")
+    public void selectChatIA() {
+        String name = "{\"id\":\"683a65fd-8feb-4446-ad32-714c4785f667\",\"messages\":[{\"role\":\"user\",\"content\":\"缁欐垜璁蹭釜鏁呬簨锛焅"}],\"stream\":true,\"max_tokens\":500}"; // JSON鏁版嵁
+        String url = "https://836u458t54.vicp.fun/chat/test_chat";
+        String aiPost =  AiTestUils.sendJsonToHttpsPost(url, name);
+        System.out.println(aiPost);
+        for (String s : AiWebSocket.getSessionPoolAi().keySet()) {
+            AiWebSocket.pushMessage(s,aiPost);
+        }
+    }
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/FilePdfSelectVo.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/FilePdfSelectVo.java
new file mode 100644
index 0000000..ef6d893
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/FilePdfSelectVo.java
@@ -0,0 +1,15 @@
+package org.jeecg.modules.ai.vo;
+
+import lombok.Data;
+
+/**
+ * @author clown
+ * * @date 2024/8/7
+ */
+@Data
+public class FilePdfSelectVo {
+    private String pdfContent;
+    private String pdfName;
+    private String pdfPath;
+    private String pdfFileId;
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/ItemPosition.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/ItemPosition.java
new file mode 100644
index 0000000..503754e
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/ItemPosition.java
@@ -0,0 +1,17 @@
+package org.jeecg.modules.ai.vo;
+
+import com.itextpdf.text.Rectangle;
+import lombok.Data;
+
+/**
+ * @author clown
+ * * @date 2024/7/23
+ * 瀛椾綋鐨勪綅缃俊鎭�
+ */
+@Data
+public class ItemPosition {
+    private Integer page;
+    private String text;
+    //杩欎釜瀛楃殑鐭╁舰鍧愭爣
+    private Rectangle rectangle;
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPosition.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPosition.java
new file mode 100644
index 0000000..b5a29f0
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPosition.java
@@ -0,0 +1,16 @@
+package org.jeecg.modules.ai.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/7/23
+ * 闇�瑕侀珮浜樉绀虹殑鍏抽敭瀛楀潗鏍囦俊鎭�
+ */
+@Data
+public class KeyWordPosition {
+    private String text;
+    private List<ItemPosition> listItem;
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPositionVo.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPositionVo.java
new file mode 100644
index 0000000..155c92a
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/KeyWordPositionVo.java
@@ -0,0 +1,17 @@
+package org.jeecg.modules.ai.vo;
+
+import com.itextpdf.text.Rectangle;
+import lombok.Data;
+
+/**
+ * @author clown
+ * * @date 2024/8/7
+ */
+@Data
+public class KeyWordPositionVo {
+    private Integer page;
+    private String text;
+    //杩欎釜瀛楃殑鐭╁舰鍧愭爣
+    private Rectangle rectangle;
+    private String rectangleString;
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/MyTextExtractionStrategy.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/MyTextExtractionStrategy.java
new file mode 100644
index 0000000..3bc7b33
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/MyTextExtractionStrategy.java
@@ -0,0 +1,64 @@
+package org.jeecg.modules.ai.vo;
+
+import com.itextpdf.text.Rectangle;
+import com.itextpdf.text.pdf.parser.ImageRenderInfo;
+import com.itextpdf.text.pdf.parser.TextExtractionStrategy;
+import com.itextpdf.text.pdf.parser.TextRenderInfo;
+import com.itextpdf.text.pdf.parser.Vector;
+
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/7/23
+ * 璁板綍鎵�鏈変綅缃�+瀛椾綋淇℃伅锛岃繖绉嶆柟寮忚幏鍙栧潗鏍囦俊鎭拰瀛椾綋淇℃伅鏂逛究涓�鐐�
+ *
+ */
+public class MyTextExtractionStrategy  implements TextExtractionStrategy {
+    private List<ItemPosition> positions;
+    private Integer page;
+
+    public MyTextExtractionStrategy() {}
+
+    public MyTextExtractionStrategy(List<ItemPosition> positions, Integer page) {
+        this.positions = positions;
+        this.page = page;
+    }
+    @Override
+    public void beginTextBlock() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void renderText(TextRenderInfo renderInfo) {
+        ItemPosition ItemPosition = new ItemPosition();
+        Vector bottomLeftPoint = renderInfo.getDescentLine().getStartPoint();
+        Vector topRightPoint = renderInfo.getAscentLine().getEndPoint();
+        //璁板綍鐭╁舰鍧愭爣
+        Rectangle rectangle = new Rectangle(bottomLeftPoint.get(Vector.I1), bottomLeftPoint.get(Vector.I2),
+                topRightPoint.get(Vector.I1), topRightPoint.get(Vector.I2));
+        ItemPosition.setPage(page);
+        ItemPosition.setRectangle(rectangle);
+        ItemPosition.setText(renderInfo.getText());
+        positions.add(ItemPosition);
+    }
+
+    @Override
+    public void endTextBlock() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void renderImage(ImageRenderInfo renderInfo) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public String getResultantText() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/PhotoListVo.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/PhotoListVo.java
new file mode 100644
index 0000000..87cb8a5
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/vo/PhotoListVo.java
@@ -0,0 +1,27 @@
+package org.jeecg.modules.ai.vo;
+
+import lombok.Data;
+
+/**
+ * @author clown
+ * * @date 2024/8/6
+ */
+@Data
+public class PhotoListVo {
+    private Integer pageNumber;
+    // 鏂囦欢鍚嶇О 涓嶅甫鍚庣紑
+    private String imgName;
+
+    // 鏂囦欢鍔犲瘑鍚庣殑鍚嶇О
+    private String imgEncodeName;
+
+    // 鏂囦欢淇濆瓨鐩稿璺緞
+    private String imgPath;
+
+    // 鏂囦欢澶у皬锛圞B锛�
+    private Long imgSize;
+
+    // 鏂囦欢鍚庣紑
+    private String imgSuffix;
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/websocket/AiWebSocket.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/websocket/AiWebSocket.java
new file mode 100644
index 0000000..a08bd9a
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/ai/websocket/AiWebSocket.java
@@ -0,0 +1,191 @@
+package org.jeecg.modules.ai.websocket;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.base.BaseMap;
+import org.jeecg.common.constant.WebsocketConst;
+import org.jeecg.common.modules.redis.client.JeecgRedisClient;
+import org.jeecg.modules.ai.service.IWebSocketAiService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author clown
+ * * @date 2024/8/8
+ */
+@Component
+@Slf4j
+@ServerEndpoint("/websocket/ai/{userId}")
+public class AiWebSocket {
+    /**绾跨▼瀹夊叏Map*/
+    private static ConcurrentHashMap<String, Session> sessionPoolAi = new ConcurrentHashMap<>();
+    /**
+     * Redis瑙﹀彂鐩戝惉鍚嶅瓧
+     */
+    public static final String REDIS_TOPIC_NAME_AI = "websocketAiHandler";
+    @Resource
+    private JeecgRedisClient jeecgRedisClient;
+
+    public static Map<String, Session> getSessionPoolAi() {
+        return sessionPoolAi;
+    }
+    //==========銆恮ebsocket鎺ュ彈銆佹帹閫佹秷鎭瓑鏂规硶 鈥斺�� 鍏蜂綋鏈嶅姟鑺傜偣鎺ㄩ�亀s娑堟伅銆�========================================================================================
+    @OnOpen
+    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
+        try {
+            sessionPoolAi.put(userId, session);
+            log.info("銆愮郴缁� WebSocket銆戞湁鏂扮殑杩炴帴锛屾�绘暟涓�:" + sessionPoolAi.size());
+        } catch (Exception e) {
+        }
+    }
+
+    @OnClose
+    public void onClose(@PathParam("userId") String userId) {
+        try {
+            sessionPoolAi.remove(userId);
+            log.info("銆愮郴缁� WebSocket銆戣繛鎺ユ柇寮�锛屾�绘暟涓�:" + sessionPoolAi.size());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * ws鎺ㄩ�佹秷鎭�
+     *
+     * @param userId
+     * @param message
+     */
+    public static void pushMessage(String userId, String message) {
+
+        Session session = sessionPoolAi.get(userId);
+        if (session != null && session.isOpen()) {
+            try {
+                //update-begin-author:taoyan date:20211012 for: websocket鎶ラ敊 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
+                synchronized (session){
+                    session.getBasicRemote().sendText(message);
+                }
+                //update-end-author:taoyan date:20211012 for: websocket鎶ラ敊 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        /*for (Map.Entry<String, Session> item : sessionPoolAi.entrySet()) {
+            //userId key鍊�= {鐢ㄦ埛id + "_"+ 鐧诲綍token鐨刴d5涓瞹
+            //TODO vue2鏈敼key鏂拌鍒欙紝鏆傛椂涓嶅奖鍝嶉�昏緫
+            if (item.getKey().contains(userId)) {
+                Session session = item.getValue();
+                try {
+                    //update-begin-author:taoyan date:20211012 for: websocket鎶ラ敊 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
+                    synchronized (session){
+                        log.info("銆愮郴缁� WebSocket銆戞帹閫佸崟浜烘秷鎭�:" + message);
+                        session.getBasicRemote().sendText(message);
+                    }
+                    //update-end-author:taoyan date:20211012 for: websocket鎶ラ敊 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
+                } catch (Exception e) {
+                    log.error(e.getMessage(),e);
+                }
+            }
+        }*/
+    }
+
+    /**
+     * ws閬嶅巻缇ゅ彂娑堟伅
+     */
+    public void pushMessage(String message) {
+        try {
+            for (Map.Entry<String, Session> item : sessionPoolAi.entrySet()) {
+                try {
+                    item.getValue().getAsyncRemote().sendText(message);
+                } catch (Exception e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+            log.info("銆愮郴缁� WebSocket銆戠兢鍙戞秷鎭�:" + message);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+
+    /**
+     * ws鎺ュ彈瀹㈡埛绔秷鎭�
+     */
+    @OnMessage
+    public void onMessage(String message, @PathParam(value = "userId") String userId) {
+        if(!"ping".equals(message) && !WebsocketConst.CMD_CHECK.equals(message)){
+            log.info("銆愮郴缁� WebSocket銆戞敹鍒板鎴风娑堟伅:" + message);
+        }else{
+            log.debug("銆愮郴缁� WebSocket銆戞敹鍒板鎴风娑堟伅:" + message);
+        }
+       /* JSONObject obj = new JSONObject();
+        //涓氬姟绫诲瀷
+        obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_CHECK);
+        //娑堟伅鍐呭
+        obj.put(WebsocketConst.MSG_TXT, "蹇冭烦鍝嶅簲");*/
+        /*webSocketAiService.selectChatIA(message);*/
+        /*this.pushMessage(userId, obj.toJSONString());*/
+
+    }
+
+    /**
+     * 閰嶇疆閿欒淇℃伅澶勭悊
+     *
+     * @param session
+     * @param t
+     */
+    @OnError
+    public void onError(Session session, Throwable t) {
+        log.warn("銆愮郴缁� WebSocket銆戞秷鎭嚭鐜伴敊璇�");
+        //t.printStackTrace();
+    }
+    //==========銆愮郴缁� WebSocket鎺ュ彈銆佹帹閫佹秷鎭瓑鏂规硶 鈥斺�� 鍏蜂綋鏈嶅姟鑺傜偣鎺ㄩ�亀s娑堟伅銆�========================================================================================
+
+
+    //==========銆愰噰鐢╮edis鍙戝竷璁㈤槄妯″紡鈥斺�旀帹閫佹秷鎭��========================================================================================
+    /**
+     * 鍚庡彴鍙戦�佹秷鎭埌redis
+     *
+     * @param message
+     */
+    public void sendMessage(String message) {
+        BaseMap baseMap = new BaseMap();
+        baseMap.put("userId", "");
+        baseMap.put("message", message);
+        jeecgRedisClient.sendMessage(REDIS_TOPIC_NAME_AI, baseMap);
+    }
+
+    /**
+     * 姝や负鍗曠偣娑堟伅 redis
+     *
+     * @param userId
+     * @param message
+     */
+    public void sendMessage(String userId, String message) {
+        BaseMap baseMap = new BaseMap();
+        jeecgRedisClient.sendMessage(REDIS_TOPIC_NAME_AI, baseMap);
+    }
+
+    /**
+     * 姝や负鍗曠偣娑堟伅(澶氫汉) redis
+     *
+     * @param userIds
+     * @param message
+     */
+    public void sendMessage(String[] userIds, String message) {
+
+    }
+
+    // 姝や负鍗曠偣娑堟伅
+    public void sendOneMessage(String userId, String message) {
+
+    }
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/AiTestUils.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/AiTestUils.java
new file mode 100644
index 0000000..388929e
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/AiTestUils.java
@@ -0,0 +1,101 @@
+package org.jeecg.modules.utils;
+
+
+import javax.net.ssl.*;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+public class AiTestUils {
+
+    private static class TrustAnyTrustManager implements X509TrustManager {
+        /**
+         * 璇ユ柟娉曟鏌ュ鎴风鐨勮瘉涔︼紝鑻ヤ笉淇′换璇ヨ瘉涔﹀垯鎶涘嚭寮傚父銆傜敱浜庢垜浠笉闇�瑕佸瀹㈡埛绔繘琛岃璇侊紝鍥犳鎴戜滑鍙渶瑕佹墽琛岄粯璁ょ殑淇′换绠$悊鍣ㄧ殑杩�
+         * 涓柟娉曘��
+         * JSSE涓紝榛樿鐨勪俊浠荤鐞嗗櫒绫讳负TrustManager銆�
+         */
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType)
+                throws CertificateException {
+        }
+
+        /**
+         * 璇ユ柟娉曟鏌ユ湇鍔″櫒鐨勮瘉涔︼紝鑻ヤ笉淇′换璇ヨ瘉涔﹀悓鏍锋姏鍑哄紓甯搞�傞�氳繃鑷繁瀹炵幇璇ユ柟娉曪紝鍙互浣夸箣淇′换鎴戜滑鎸囧畾鐨勪换浣曡瘉涔︺��
+         * 鍦ㄥ疄鐜拌鏂规硶鏃讹紝涔熷彲浠ョ畝鍗曠殑涓嶅仛浠讳綍澶勭悊锛� 鍗充竴涓┖鐨勫嚱鏁颁綋锛岀敱浜庝笉浼氭姏鍑哄紓甯革紝瀹冨氨浼氫俊浠讳换浣曡瘉涔︺��(non-Javadoc)
+         */
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType)
+                throws CertificateException {
+        }
+
+        /**
+         * @return 杩斿洖鍙椾俊浠荤殑X509璇佷功鏁扮粍銆�
+         */
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[]{};
+        }
+    }
+
+    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
+        @Override
+        public boolean verify(String hostname, SSLSession session) {
+            return true;
+        }
+    }
+
+    /**
+     * post鏂瑰紡璇锋眰鏈嶅姟鍣�(https鍗忚)
+     * @param url     姹傚湴鍧�
+     * @param content 鍙傛暟
+     * @return
+     */
+    public static String sendJsonToHttpsPost(String url, String content) {
+        try {
+            /*
+             * 绫籋ttpsURLConnection浼间箮骞舵病鏈夋彁渚涙柟娉曡缃俊浠荤鐞嗗櫒銆傚叾瀹烇紝
+             * HttpsURLConnection閫氳繃SSLSocket鏉ュ缓绔嬩笌HTTPS鐨勫畨鍏ㄨ繛鎺�
+             * 锛孲SLSocket瀵硅薄鏄敱SSLSocketFactory鐢熸垚鐨勩��
+             * HttpsURLConnection鎻愪緵浜嗘柟娉晄etSSLSocketFactory
+             * (SSLSocketFactory)璁剧疆瀹冧娇鐢ㄧ殑SSLSocketFactory瀵硅薄銆�
+             * SSLSocketFactory閫氳繃SSLContext瀵硅薄鏉ヨ幏寰楋紝鍦ㄥ垵濮嬪寲SSLContext瀵硅薄鏃讹紝鍙寚瀹氫俊浠荤鐞嗗櫒瀵硅薄銆�
+             */
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, new TrustManager[]{new TrustAnyTrustManager()},
+                    new java.security.SecureRandom());
+
+            URL console = new URL(url);
+            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
+            conn.setSSLSocketFactory(sc.getSocketFactory());
+            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+            conn.setDoOutput(true);
+            // 璁剧疆璇锋眰澶�
+            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
+            conn.connect();
+            DataOutputStream out = new DataOutputStream(conn.getOutputStream());
+            out.write(content.getBytes());
+            // 鍒锋柊銆佸叧闂�
+            out.flush();
+            out.close();
+            InputStream is = conn.getInputStream();
+            if (is != null) {
+                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+                byte[] buffer = new byte[1024];
+                int len = 0;
+                while ((len = is.read(buffer)) != -1) {
+                    outStream.write(buffer, 0, len);
+                }
+                is.close();
+                return outStream.toString();
+            }
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/DateUtil.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/DateUtil.java
new file mode 100644
index 0000000..93faef4
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/DateUtil.java
@@ -0,0 +1,142 @@
+package org.jeecg.modules.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Created by Administrator on 2015/8/28.
+ */
+@Slf4j
+public class DateUtil {
+    public static final String STR_DATE = "yyyy-MM-dd";
+    public static final String STR_YEAR_MONTH = "yyyy-MM";
+    public static final String STR_DATE_TIME = "yyyy-MM-dd HH:mm:ss.SSS";
+    public static final String STR_DATE_TIME_SMALL = "yyyy-MM-dd HH:mm:ss";
+    public static final String STR_DATE_TIME_MIN = "yyyy-MM-dd HH:mm";
+    public static final String STR_DATE_TIME_HOUR = "yyyy-MM-dd HH";
+    public static final String STR_DATE_TIME_FULL = "yyyyMMddHHmmssSSS";
+    public static final String STR_YEARMONTH = "yyyyMM";
+    public static final String STR_YEAR = "yyyy";
+
+    /**
+     * 鑾峰彇褰撳墠鏃堕棿
+     * @return
+     */
+    public static Date getNow() {
+        return new Date(System.currentTimeMillis());
+    }
+
+    /**
+     * <p>
+     * Description: 鍘绘帀鏃ユ湡鏃堕棿涓殑鏃堕棿閮ㄥ垎
+     * </p>
+     * 濡�: 2013-11-11 18:56:33 ---> 2013-11-11 00:00:00
+     *
+     * @param date 闇�瑕佷慨鏀圭殑鏃堕棿
+     * @return 淇敼鍚庣殑鏃堕棿
+     */
+    public static Date removeTime(Date date) {
+        Date result = null;
+        try {
+            SimpleDateFormat df = new SimpleDateFormat(STR_DATE);
+            String dateStr = df.format(date);
+            result = df.parse(dateStr);
+        } catch (ParseException e) {
+            log.error(e.getMessage(), e.getStackTrace());
+            return null;
+        }
+        return result;
+    }
+
+    /**
+     * <p>
+     * Description: 鎸夋寚瀹氭牸寮忚幏鍙栨椂闂村瓧绗︿覆
+     * </p>
+     *
+     * @param date   瑕佽浆鎹㈢殑鏃ユ湡
+     * @param format 鏍煎紡,渚嬪:yyyy-MM-dd HH:mm:ss.SSS
+     * @return 杞崲鍚庣殑鏃堕棿瀛楃涓�
+     */
+    public static String format(Date date, String format) {
+        SimpleDateFormat df = new SimpleDateFormat(format);
+        return df.format(date);
+    }
+
+    /**
+     * 鑾峰彇鏃ユ湡鐨勫ぉ瀛楃涓�
+     * @param date
+     * @return
+     */
+    public static String getDayStr(Date date) {
+        Calendar calendar = Calendar.getInstance(); // 寰楀埌鏃ュ巻
+        calendar.setTime(date);// 鎶婂綋鍓嶆椂闂磋祴缁欐棩鍘�
+        int day = calendar.get(Calendar.DATE);//鑾峰彇鏃�
+        String dayStr = day < 10 ? "0" + day : day + "";
+        return dayStr;
+    }
+
+    /**
+     * 鑾峰彇鏃ユ湡鐨勫勾浠藉瓧绗︿覆
+     * @param date
+     * @return
+     */
+    public static String getYearStr(Date date) {
+        Calendar calendar = Calendar.getInstance(); // 寰楀埌鏃ュ巻
+        calendar.setTime(date);// 鎶婂綋鍓嶆椂闂磋祴缁欐棩鍘�
+        String yearStr = calendar.get(Calendar.YEAR) + "";//鑾峰彇鏃�
+        return yearStr;
+    }
+
+    /**
+     * 鑾峰彇鏃ユ湡鐨勬湀浠藉瓧绗︿覆
+     * @param date
+     * @return
+     */
+    public static String getMonthStr(Date date) {
+        Calendar calendar = Calendar.getInstance(); // 寰楀埌鏃ュ巻
+        calendar.setTime(date);// 鎶婂綋鍓嶆椂闂磋祴缁欐棩鍘�
+        int month = calendar.get(Calendar.MONTH);//鑾峰彇鏃�
+        String monthStr = month < 10 ? "0" + month : month + "";
+        return monthStr;
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃堕棿 鍓嶅悗i澶�
+     * 绮剧‘鍒扮
+     * @param i 涓烘鏁颁唬琛ㄥ姞i澶╋紝涓鸿礋鏁颁唬琛ㄥ噺i澶�
+     * @return
+     */
+    public static Date addDay(Date date, int i){
+        Calendar calendar = Calendar.getInstance(); // 寰楀埌鏃ュ巻
+        calendar.setTime(date);// 鎶婂綋鍓嶆椂闂磋祴缁欐棩鍘�
+        calendar.add(Calendar.DAY_OF_MONTH, i); // 璁剧疆澶╂暟鍔犲噺
+        return calendar.getTime();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃堕棿 鍓嶅悗i绉�
+     * 绮剧‘鍒扮
+     * @param i 涓烘鏁颁唬琛ㄥ姞i绉掞紝涓鸿礋鏁颁唬琛ㄥ噺i绉�
+     * @return
+     */
+    public static Date addSeconds(Date date, int i){
+        Calendar calendar = Calendar.getInstance(); // 寰楀埌鏃ュ巻
+        calendar.setTime(date);// 鎶婂綋鍓嶆椂闂磋祴缁欐棩鍘�
+        calendar.add(Calendar.SECOND, i); // 璁剧疆绉掓暟鍔犲噺
+        return calendar.getTime();
+    }
+
+    public static Date toDate(String date, String format) {
+        SimpleDateFormat df = new SimpleDateFormat(format);
+        try {
+            return df.parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfTurnPngUtils.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfTurnPngUtils.java
new file mode 100644
index 0000000..18f3a12
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfTurnPngUtils.java
@@ -0,0 +1,115 @@
+package org.jeecg.modules.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.rendering.PDFRenderer;
+import org.jeecg.common.util.SHA256Util;
+import org.jeecg.modules.ai.vo.PhotoListVo;
+import org.jeecg.modules.utils.file.FileUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/8/1
+ */
+@Slf4j
+@Component
+public class PdfTurnPngUtils {
+
+    private static String filePngPath;
+
+    @Value("${jeecg.path.upload}")
+    public void setFilePngPath(String filePngPath) {
+        PdfTurnPngUtils.filePngPath = filePngPath;
+    }
+
+
+
+    /**
+     * 浣跨敤pdfbox灏嗘暣涓猵df杞崲鎴愬浘鐗�
+     *
+     * @param fileAddress 鏂囦欢鍦板潃 濡�:C:\\Users\\user\\Desktop\\test
+     * @param filename    PDF鏂囦欢鍚嶄笉甯﹀悗缂�鍚�
+     * @param type        鍥剧墖绫诲瀷 png 鍜宩pg
+     */
+    public static void pdf2png(String fileAddress, String filename, String type) {
+        long startTime = System.currentTimeMillis();
+        // 灏嗘枃浠跺湴鍧�鍜屾枃浠跺悕鎷兼帴鎴愯矾寰� 娉ㄦ剰锛氱嚎涓婄幆澧冧笉鑳戒娇鐢╘\鎷兼帴
+        File file = new File(fileAddress + "\\" + filename + ".pdf");
+        try {
+            // 鍐欏叆鏂囦欢
+            PDDocument doc = PDDocument.load(file);
+            PDFRenderer renderer = new PDFRenderer(doc);
+            int pageCount = doc.getNumberOfPages();
+            for (int i = 0; i < pageCount ; i++) {
+                // dpi涓�144锛岃秺楂樿秺娓呮櫚锛岃浆鎹㈣秺鎱�
+                BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
+                // 灏嗗浘鐗囧啓鍑哄埌璇ヨ矾寰勪笅
+                ImageIO.write(image, type,
+                        new File(fileAddress + "\\澶囦唤\\" + filename + "_" + (i+1) + "." + type));
+            }
+            long endTime = System.currentTimeMillis();
+            System.out.println("鍏辫�楁椂锛�" + ((endTime - startTime) / 1000.0) + "绉�");  //杞寲鐢ㄦ椂
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static List<PhotoListVo> pdf2pngList(File filePdf, String type,String pathImg){
+        PDDocument doc = null;
+        try {
+            List<PhotoListVo> files = new ArrayList<>();
+            doc = PDDocument.load(filePdf);
+            String pdfName = FileUtils.getFilenameNonSuffix(filePdf.getName());
+            if (doc == null ) {
+                return null;
+            }
+            PDFRenderer renderer = new PDFRenderer(doc);
+            int pageCount = doc.getNumberOfPages();
+            Date currentDate = DateUtil.getNow();
+            String monthStr = DateUtil.format(currentDate, DateUtil.STR_YEAR_MONTH);
+            String relativePath = "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/"+ pathImg + "/";
+            //缁濆璺緞
+            String absolutePath =  filePngPath + "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/" + pathImg + "/";
+            for (int i = 0; i < pageCount ; i++) {
+                PhotoListVo pVo = new PhotoListVo();
+                // dpi涓�144锛岃秺楂樿秺娓呮櫚锛岃浆鎹㈣秺鎱�
+                BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI  144
+                // 灏嗗浘鐗囧啓鍑哄埌璇ヨ矾寰勪笅
+                //鏂囦欢璺緞
+                //鐩稿璺緞
+                String encodeFileName = SHA256Util.getSHA256Str(pdfName + "_" + (i+1) + System.currentTimeMillis());
+                String imgPath = absolutePath + "/" + encodeFileName + "." + type;
+                File targetFile = new File(imgPath);
+                if(!targetFile.getParentFile().exists()){
+                    targetFile.getParentFile().mkdirs();
+                }
+                ImageIO.write(image, type, targetFile);
+                pVo.setImgEncodeName(encodeFileName + "." + type);
+                pVo.setImgName(pdfName + "_" + (i+1));
+                pVo.setImgSize(Long.valueOf(new File(imgPath).length()));
+                pVo.setImgSuffix(type);
+                pVo.setPageNumber(i+1);
+                pVo.setImgPath(relativePath);
+                files.add(pVo);
+            }
+            return files;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+
+}
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfUtils.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfUtils.java
new file mode 100644
index 0000000..c0218e9
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/PdfUtils.java
@@ -0,0 +1,263 @@
+package org.jeecg.modules.utils;
+
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.pdf.PdfContentByte;
+import com.itextpdf.text.pdf.PdfReader;
+import com.itextpdf.text.pdf.PdfStamper;
+import com.itextpdf.text.pdf.parser.PdfTextExtractor;
+import org.jeecg.modules.ai.vo.ItemPosition;
+import org.jeecg.modules.ai.vo.KeyWordPosition;
+import org.jeecg.modules.ai.vo.KeyWordPositionVo;
+import org.jeecg.modules.ai.vo.MyTextExtractionStrategy;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author clown
+ * * @date 2024/7/23
+ */
+public class PdfUtils {
+    /**
+     * 鐢ㄤ簬渚涘閮ㄧ被璋冪敤鑾峰彇鍏抽敭瀛楁墍鍦≒DF鏂囦欢鍧愭爣
+     * @param filepath
+     * @param keyWords
+     * @return
+     */
+    public static List<KeyWordPosition> getKeyWordsByPath(String filepath, String keyWords) {
+        List<KeyWordPosition> matchItems = null;
+        try{
+            PdfReader pdfReader = new PdfReader(filepath);
+            matchItems = getKeyWords(pdfReader, keyWords);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return matchItems;
+    }
+
+    /**
+     * 鑾峰彇鍏抽敭瀛楁墍鍦≒DF鍧愭爣
+     * @param pdfReader
+     * @param keyWords
+     * @return
+     */
+    private static List<KeyWordPosition> getKeyWords(PdfReader pdfReader, String keyWords) {
+        int page = 0;
+
+        List<KeyWordPosition> matchItems = new ArrayList<>();
+        try{
+            int pageNum = pdfReader.getNumberOfPages();
+            StringBuilder allText = null;
+
+            //閬嶅巻椤�
+            for (page = 1; page <= pageNum; page++) {
+                //鍙褰曞綋椤电殑鎵�鏈夊唴瀹癸紝闇�瑕佽褰曞叏閮ㄩ〉鏀惧湪寰幆澶栭潰
+                List<ItemPosition> allItems = new ArrayList<>();
+                //鎵弿鍐呭
+                MyTextExtractionStrategy myTextExtractionStrategy = new MyTextExtractionStrategy(allItems, page);
+                PdfTextExtractor.getTextFromPage(pdfReader, page, myTextExtractionStrategy);
+                //褰撻〉鐨勬枃瀛楀唴瀹癸紝鐢ㄤ簬鍏抽敭璇嶅尮閰�
+                allText = new StringBuilder();
+                //涓�涓瓧涓�涓瓧鐨勯亶鍘�
+                for (int i=0; i<allItems.size(); i++) {
+                    ItemPosition item = allItems.get(i);
+                    allText.append(item.getText());
+                    //鍏抽敭瀛楀瓨鍦ㄨ繛缁涓潡涓�
+                    if(allText.indexOf(keyWords) != -1) {
+                        KeyWordPosition keyWordPosition = new KeyWordPosition();
+                        //璁板綍鍏抽敭璇嶆瘡涓瓧鐨勪綅缃紝鍙褰曞紑濮嬬粨鏉熸爣璁版椂浼氭湁闂
+                        List<ItemPosition> listItem = new ArrayList<>();
+                        for(int j=i-keyWords.length()+1; j<=i; j++) {
+                            listItem.add(allItems.get(j));
+                        }
+                        keyWordPosition.setListItem(listItem);
+                        keyWordPosition.setText(keyWords);
+                        matchItems.add(keyWordPosition);
+                        allText.setLength(0);
+                    }
+                }
+
+
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return matchItems;
+    }
+
+
+
+
+    public static void main(String[] args) throws Exception {
+        String keyword = "涓�鏃﹀彂鐢熸満搴婂畨鍏ㄤ簨鏁�";
+        String sourcePdf = "F:\\123.pdf";
+        String watermarkPdf = "F:\\12_bak.pdf";
+        Long start = System.currentTimeMillis();
+        System.out.println("寮�濮嬫壂鎻�....");
+        List<KeyWordPosition> matchItems = getKeyWordsByPath(sourcePdf, keyword);
+        System.out.println(matchItems);
+        System.out.println("鎵弿缁撴潫["+(System.currentTimeMillis()-start)+"ms]锛屽叡鎵惧埌鍏抽敭瀛梉"+keyword+"]鍑虹幇["+matchItems.size()+"]娆�");
+        start = System.currentTimeMillis();
+        System.out.println("寮�濮嬫坊鍔犳爣璁�....");
+        andRectangleMark(sourcePdf
+                , watermarkPdf
+                , matchItems
+                , BaseColor.RED
+                , 2
+                , 2);
+        //鏂囦欢鏁寸悊
+        System.out.println("鏍囪娣诲姞瀹屾垚["+(System.currentTimeMillis()-start)+"ms]");
+
+    }
+
+
+    public static List<KeyWordPositionVo> findListWord(String sourcePath, String keyWord){
+        System.out.println("寮�濮嬫壂鎻�....");
+        try {
+            List<KeyWordPositionVo> matchItems = getKeyWordsByPathOne(sourcePath, keyWord);
+            return matchItems;
+        }catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * 鐢ㄤ簬渚涘閮ㄧ被璋冪敤鑾峰彇鍏抽敭瀛楁墍鍦≒DF鏂囦欢鍧愭爣
+     * @param filepath
+     * @param keyWords
+     * @return
+     */
+    public static List<KeyWordPositionVo> getKeyWordsByPathOne(String filepath, String keyWords) {
+        List<KeyWordPositionVo> matchItems = null;
+        try{
+            PdfReader pdfReader = new PdfReader(filepath);
+            matchItems = getKeyWordPage(pdfReader, keyWords);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return matchItems;
+    }
+
+    /**
+     * 鑾峰彇鍏抽敭瀛楁墍鍦≒DF鍧愭爣 涓�椤靛彧鍙栫涓�鏉�
+     * @param pdfReader
+     * @param keyWords
+     * @return
+     */
+    private static List<KeyWordPositionVo> getKeyWordPage(PdfReader pdfReader, String keyWords) {
+        int page = 0;
+        List<KeyWordPositionVo> matchItems = new ArrayList<>();
+        try{
+            int pageNum = pdfReader.getNumberOfPages();
+            StringBuilder allText = null;
+            //閬嶅巻椤�
+            for (page = 1; page <= pageNum; page++) {
+                //鍙褰曞綋椤电殑鎵�鏈夊唴瀹癸紝闇�瑕佽褰曞叏閮ㄩ〉鏀惧湪寰幆澶栭潰
+                List<ItemPosition> allItems = new ArrayList<>();
+                //鎵弿鍐呭
+                MyTextExtractionStrategy myTextExtractionStrategy = new MyTextExtractionStrategy(allItems, page);
+                PdfTextExtractor.getTextFromPage(pdfReader, page, myTextExtractionStrategy);
+                //褰撻〉鐨勬枃瀛楀唴瀹癸紝鐢ㄤ簬鍏抽敭璇嶅尮閰�
+                allText = new StringBuilder();
+                //涓�涓瓧涓�涓瓧鐨勯亶鍘�
+                for (int i=0; i<allItems.size(); i++) {
+                    ItemPosition item = allItems.get(i);
+                    allText.append(item.getText());
+                    //鍏抽敭瀛楀瓨鍦ㄨ繛缁涓潡涓�
+                    if(allText.indexOf(keyWords) != -1) {
+                        KeyWordPosition keyWordPosition = new KeyWordPosition();
+                        //璁板綍鍏抽敭璇嶆瘡涓瓧鐨勪綅缃紝鍙褰曞紑濮嬬粨鏉熸爣璁版椂浼氭湁闂
+                        KeyWordPositionVo vo = new KeyWordPositionVo();
+                        for(int j=i-keyWords.length()+1; j<=i; j++) {
+                            if (allItems.get(j).getText().indexOf(keyWords)!= -1) {
+                                vo.setPage(allItems.get(j).getPage());
+                                vo.setRectangle(allItems.get(j).getRectangle());
+                                vo.setText(allItems.get(j).getText());
+                                vo.setRectangleString(allItems.get(j).getRectangle().toString());
+                                matchItems.add(vo);
+                                break;
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return matchItems;
+    }
+
+    /**
+     * 娣诲姞鐭╁舰鏍囪
+     * @param oldPath
+     * @param newPath
+     * @param matchItems 鍏抽敭璇�
+     * @param color 鏍囪棰滆壊
+     * @param lineWidth 绾挎潯绮楃粏
+     * @param padding 杈规鍐呰竟璺�
+     * @throws DocumentException
+     * @throws IOException
+     */
+    public static void andRectangleMark(String oldPath, String newPath, List<KeyWordPosition> matchItems, BaseColor color, int lineWidth, int padding) throws DocumentException, IOException{
+        // 寰呭姞姘村嵃鐨勬枃浠�
+        PdfReader reader = new PdfReader(oldPath);
+        // 鍔犲畬姘村嵃鐨勬枃浠�
+        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(newPath));
+
+        PdfContentByte content;
+
+        // 璁剧疆瀛椾綋
+        // 寰幆瀵规瘡椤垫彃鍏ユ按鍗�
+        for (KeyWordPosition keyWordPosition:matchItems)
+        {
+            //涓�涓叧閿瘝鐨勬墍鏈夊瓧鍧愭爣
+            List<ItemPosition> oneKeywordItems = keyWordPosition.getListItem();
+            for(int i=0; i<oneKeywordItems.size(); i++) {
+                ItemPosition item = oneKeywordItems.get(i);
+                ItemPosition preItem = i==0?null:oneKeywordItems.get(i-1);
+                //甯︾‘瀹炴槸鍚︽按鍗�
+
+                // 姘村嵃鐨勮捣濮�
+                content = stamper.getOverContent(item.getPage());
+                // 寮�濮嬪啓鍏ユ按鍗�
+                content.setLineWidth(lineWidth);
+                content.setColorStroke(color);
+                System.out.println(item.toString());
+
+                //搴曠嚎
+                content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);
+                content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getBottom()-padding);
+                if(i!=0 && preItem!=null && (preItem.getRectangle().getBottom()-padding)==(item.getRectangle().getBottom()-padding) && (preItem.getRectangle().getRight()+padding)!=(item.getRectangle().getLeft()-padding)) {
+                    content.moveTo(preItem.getRectangle().getRight()+padding, preItem.getRectangle().getBottom()-padding);
+                    content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);
+                }
+                //涓婄嚎
+                content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);
+                content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getTop()+padding);
+                if(i!=0 && preItem!=null && (preItem.getRectangle().getTop()+padding)==(item.getRectangle().getTop()+padding) && (preItem.getRectangle().getRight()+padding)!=(item.getRectangle().getLeft()-padding)) {
+                    content.moveTo(preItem.getRectangle().getRight()+padding, preItem.getRectangle().getTop()+padding);
+                    content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);
+                }
+
+                //宸︾嚎
+                if(i==0) {
+                    content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);
+                    content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()+padding);
+                }
+                //鍙崇嚎
+                if(i==(oneKeywordItems.size()-1)) {
+                    content.moveTo(item.getRectangle().getRight()+padding, item.getRectangle().getBottom()-padding);
+                    content.lineTo(item.getRectangle().getRight()+padding, item.getRectangle().getTop()+padding);
+                }
+
+                content.stroke();
+            }
+        }
+        stamper.close();
+    }
+}
+
diff --git a/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/file/FileUtils.java b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/file/FileUtils.java
new file mode 100644
index 0000000..04611c0
--- /dev/null
+++ b/lxzn-module-ai/src/main/java/org/jeecg/modules/utils/file/FileUtils.java
@@ -0,0 +1,327 @@
+package org.jeecg.modules.utils.file;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.api.vo.FileUploadResult;
+import org.jeecg.common.util.SHA256Util;
+import org.jeecg.modules.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.Date;
+
+@Slf4j
+@Component
+public class FileUtils {
+
+    private static String fileUploadFolder;
+
+    @Value("${jeecg.path.upload}")
+    public void setFileUploadFolder(String fileUploadFolder) {
+        FileUtils.fileUploadFolder = fileUploadFolder;
+    }
+
+    /**
+     * 鏂囦欢璺緞涓婁紶淇濆瓨
+     * @param filePath
+     * @return
+     */
+    public static FileUploadResult uploadFilePath(String filePath) {
+        File file = new File(filePath);
+        if(file == null) {
+            return null;
+        }
+        String fileName = file.getName();
+        String suffix = getFileSuffix(fileName);
+        Date currentDate = DateUtil.getNow();
+        String monthStr = DateUtil.format(currentDate, DateUtil.STR_YEAR_MONTH);
+        //鐩稿璺緞
+        String relativePath = "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/";
+        //缁濆璺緞
+        String absolutePath =  fileUploadFolder + "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/";
+        String fileNameNonSuffix = getFilenameNonSuffix(fileName);
+        if(fileNameNonSuffix == null)
+            return null;
+        String encodeFileName = SHA256Util.getSHA256Str(fileNameNonSuffix + System.currentTimeMillis());
+        if(StringUtils.isNotBlank(suffix)) {
+            encodeFileName = encodeFileName + "." + suffix;
+        }
+        Long b = uploadFileInput(file, absolutePath, encodeFileName);
+        FileUploadResult dto = new FileUploadResult();
+        dto.setFileName(fileNameNonSuffix);
+        dto.setFilePath(encodeFileName);
+        dto.setFilePath(relativePath);
+        dto.setFileSize(b);
+        dto.setFileSuffix(suffix);
+        return dto;
+    }
+
+    /**
+     * 鏂囦欢File涓婁紶淇濆瓨
+     * @param file
+     * @return
+     */
+    public static FileUploadResult uploadFileInFile(File file) {
+        if(file == null) {
+            return null;
+        }
+        String fileName = file.getName();
+        String suffix = getFileSuffix(fileName);
+        Date currentDate = DateUtil.getNow();
+        String monthStr = DateUtil.format(currentDate, DateUtil.STR_YEAR_MONTH);
+        //鐩稿璺緞
+        String relativePath = "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/";
+        //缁濆璺緞
+        String absolutePath =  fileUploadFolder + "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/";
+        String fileNameNonSuffix = getFilenameNonSuffix(fileName);
+        if(fileNameNonSuffix == null) {
+            return null;
+        }
+        String encodeFileName = SHA256Util.getSHA256Str(fileNameNonSuffix + System.currentTimeMillis());
+        if(StringUtils.isNotBlank(suffix)) {
+            encodeFileName = encodeFileName + "." + suffix;
+        }
+        Long b = uploadFileInput(file, absolutePath, encodeFileName);
+        FileUploadResult dto = new FileUploadResult();
+        dto.setFileName(fileNameNonSuffix);
+        dto.setFileEncodeName(encodeFileName);
+        dto.setFilePath(relativePath);
+        dto.setFileSize(b);
+        dto.setFileSuffix(suffix);
+        return dto;
+    }
+
+
+    /**
+     * MultipartFile 鏂瑰紡淇濆瓨
+     * @param file
+     * @return
+     */
+    public static FileUploadResult uploadMultipartFile(MultipartFile file) {
+        if(file == null || file.isEmpty()) {
+            return null;
+        }
+        String fileName = file.getOriginalFilename();
+        String suffix = getFileSuffix(fileName);
+        Date currentDate = DateUtil.getNow();
+        String monthStr = DateUtil.format(currentDate, DateUtil.STR_YEAR_MONTH);
+        //鐩稿璺緞
+        String relativePath = "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/";
+        //缁濆璺緞
+        String absolutePath =  fileUploadFolder + "/" + monthStr + "/" + DateUtil.getDayStr(currentDate) + "/";
+        String fileNameNonSuffix = getFilenameNonSuffix(fileName);
+        if(fileNameNonSuffix == null)
+            return null;
+        String encodeFileName = SHA256Util.getSHA256Str(fileNameNonSuffix + System.currentTimeMillis());
+        Long fileSize = file.getSize();
+        if(StringUtils.isNotBlank(suffix)) {
+            encodeFileName = encodeFileName + "." + suffix;
+        }
+        boolean b = uploadFile(file, absolutePath, encodeFileName);
+        if(!b)
+            return null;
+        FileUploadResult dto = new FileUploadResult();
+        dto.setFileName(fileNameNonSuffix);
+        dto.setFilePath(encodeFileName);
+        dto.setFilePath(relativePath);
+        dto.setFileSize(fileSize);
+        dto.setFileSuffix(suffix);
+        return dto;
+    }
+
+    public static void downLoadFile(HttpServletResponse response, String fileName, String filePath, String toFileName) {
+        String absolutePath = fileUploadFolder + filePath;
+        File file = new File(absolutePath , fileName);
+        if(file.exists()) {
+            byte[] buffer = new byte[1024];
+            FileInputStream fis = null;
+            BufferedInputStream bis = null;
+            try {
+                response.setHeader("Content-Type", "application/octet-stream;charset=utf-8"); // 鍛婅瘔娴忚鍣ㄨ緭鍑哄唴瀹逛负娴�
+                response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(toFileName, "UTF-8"));
+                fis = new FileInputStream(file);
+                bis = new BufferedInputStream(fis);
+                OutputStream os = response.getOutputStream();
+                int i = bis.read(buffer);
+                while (i != -1) {
+                    os.write(buffer, 0, i);
+                    i = bis.read(buffer);
+                }
+            }catch (Exception e) {
+                log.error(e.getMessage(), e.getStackTrace());
+            }finally {
+                if(bis != null) {
+                    try {
+                        bis.close();
+                    } catch (IOException e) {
+                    }
+                }
+                if(fis != null) {
+                    try {
+                        fis.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }else {
+
+        }
+    }
+
+
+
+    /**
+     * 涓婁紶鏂囦欢宸ュ叿绫�
+     * @param file
+     * @param path
+     * @param fileNewName  鏂扮殑鏂囦欢鍚�
+     * @return
+     */
+    public static Long uploadFileInput(File file, String path, String fileNewName) {
+        File targetFile = new File(path, fileNewName);
+        if(!targetFile.getParentFile().exists()){
+            targetFile.getParentFile().mkdirs();
+        }
+        try {
+            FileInputStream fis = new FileInputStream(file);
+            FileOutputStream fos = new FileOutputStream(targetFile);
+            //FileInputStream fis = new FileInputStream(file);
+            byte[] bytes = new byte[1024 * 4];
+            int index = 0;
+            long total = 0;
+            while ((index = fis.read(bytes)) != -1) {
+                fos.write(bytes, 0, index);
+                total =+ index;
+            }
+            fis.close();
+            fos.flush();
+            fos.close();
+            return total;
+        } catch (Exception e) {
+            log.error(e.getMessage(), e.getStackTrace());
+            return 0L;
+        }
+    }
+    /**
+     * 涓婁紶鏂囦欢宸ュ叿绫�
+     * @param multipartFile
+     * @param path
+     * @param fileNewName  鏂扮殑鏂囦欢鍚�
+     * @return
+     */
+    public static boolean uploadFile(MultipartFile multipartFile, String path, String fileNewName) {
+        File targetFile = new File(path, fileNewName);
+        if(!targetFile.getParentFile().exists()){
+            targetFile.getParentFile().mkdirs();
+        }
+        try {
+            multipartFile.transferTo(targetFile);
+            return true;
+        } catch (Exception e) {
+            log.error(e.getMessage(), e.getStackTrace());
+            return false;
+        }
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚庣紑  鏃犲悗缂�鏂囦欢杩斿洖NULL
+     * @param fileName
+     * @return
+     */
+    public static String getFileSuffix(String fileName) {
+        if (fileName.contains(".")) {
+            String suffix = fileName.substring(fileName.lastIndexOf('.') + 1);
+            return suffix;
+        }else {
+            return null;
+        }
+
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚� 涓嶅甫鍚庣紑鍜岀偣鍙�
+     * @param fileName
+     * @return
+     */
+    public static String getFilenameNonSuffix(String fileName) {
+        if (fileName.contains(".")) {
+            String filename = fileName.substring(0, fileName.lastIndexOf('.'));
+            return filename;
+        }else {
+            return fileName;
+        }
+
+    }
+
+
+
+    public static String checkFileEncode(File file) {
+        String charset = "GBK";
+        byte[] first3Bytes = new byte[3];
+        BufferedInputStream bis = null;
+        try {
+            boolean checked = false;
+            bis = new BufferedInputStream(new FileInputStream(file));
+            bis.mark(0);
+            int read = bis.read(first3Bytes, 0, 3);
+            if (read == -1)
+                return charset;
+            if(first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE ) {
+                charset = "UTF-16LE";
+                checked = true;
+            }else if ( first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF ) {
+                charset = "UTF-16BE";
+                checked = true;
+            }else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF ) {
+                charset = "UTF-8";
+                checked = true;
+            }
+            bis.reset();
+            if (!checked) {
+                while ((read = bis.read()) != -1 ) {
+                    if ( read >= 0xF0 )
+                        break;
+                    if ( 0x80 <= read && read <= 0xBF ) // 鍗曠嫭鍑虹幇BF浠ヤ笅鐨勶紝涔熺畻鏄疓BK
+                        break;
+                    if ( 0xC0 <= read && read <= 0xDF ) {
+                        read = bis.read();
+                        if ( 0x80 <= read && read <= 0xBF ) // 鍙屽瓧鑺� (0xC0 - 0xDF) (0x80 - 0xBF),涔熷彲鑳藉湪GBK缂栫爜鍐吢犅�
+                             continue;
+                        else
+                            break;
+                    } else if ( 0xE0 <= read && read <= 0xEF ) {
+                        // 涔熸湁鍙兘鍑洪敊锛屼絾鏄嚑鐜囪緝灏�
+                        read = bis.read();
+                        if ( 0x80 <= read && read <= 0xBF ) {
+                            read = bis.read();
+                            if ( 0x80 <= read && read <= 0xBF ) {
+                                 charset = "UTF-8";
+                                 break;
+                            } else
+                                break;
+                        } else {
+                            break;
+                        }
+                    }
+                }
+            }
+            return charset;
+        }catch (Exception e) {
+            return null;
+        }finally {
+            if(bis != null) {
+                try {
+                    bis.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+
+    }
+
+
+}
diff --git a/lxzn-module-system/lxzn-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java b/lxzn-module-system/lxzn-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java
index 01335dc..633249d 100644
--- a/lxzn-module-system/lxzn-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java
+++ b/lxzn-module-system/lxzn-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java
@@ -27,7 +27,7 @@
     }
 
     public static void main(String[] args) throws UnknownHostException {
-            ConfigurableApplicationContext application = SpringApplication.run(JeecgSystemApplication.class, args);
+        ConfigurableApplicationContext application = SpringApplication.run(JeecgSystemApplication.class, args);
         Environment env = application.getEnvironment();
         String ip = InetAddress.getLocalHost().getHostAddress();
         String port = env.getProperty("server.port");
diff --git a/lxzn-module-system/lxzn-system-start/src/main/resources/application-dev.yml b/lxzn-module-system/lxzn-system-start/src/main/resources/application-dev.yml
index ec34a99..aa1777e 100644
--- a/lxzn-module-system/lxzn-system-start/src/main/resources/application-dev.yml
+++ b/lxzn-module-system/lxzn-system-start/src/main/resources/application-dev.yml
@@ -263,8 +263,3 @@
       # appSecret
       client-secret: ??
       agent-id: ??
-webservice:
-  url: http://localhost:8081/services/EquipmentService?wsdl
-  namespace: http://service.server.webservice.example.com
-  statusMethod: equipmentStatus
-  rateMethod: equipmentRate
\ No newline at end of file
diff --git a/lxzn-module-system/lxzn-system-start/src/main/resources/application-prod.yml b/lxzn-module-system/lxzn-system-start/src/main/resources/application-prod.yml
index 7a66255..be081df 100644
--- a/lxzn-module-system/lxzn-system-start/src/main/resources/application-prod.yml
+++ b/lxzn-module-system/lxzn-system-start/src/main/resources/application-prod.yml
@@ -127,16 +127,16 @@
         connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
       datasource:
         master:
-          url: jdbc:sqlserver://195.0.1.10:1433;databasename=SSGX_kns
-          username: sa
-          password: Sa123456789
-          driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
+         url: jdbc:postgresql://192.168.253.133:5432/ai_service?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
+         username: postgres
+         password: ABC@13579
+         driverClassName: org.postgresql.Driver
   #redis 閰嶇疆
   redis:
     database: 0
     host: 127.0.0.1
     port: 6379
-    password:
+    password: ''
 #mybatis plus 璁剧疆
 mybatis-plus:
   mapper-locations: classpath*:org/jeecg/modules/**/xml/*Mapper.xml
@@ -170,7 +170,7 @@
     pc: http://localhost:3100
     app: http://localhost:8051
   path:
-    #鏂囦欢涓婁紶鏍圭洰褰� 璁剧疆
+    #鏂囦欢涓婁紶鏍圭洰褰曡缃�
     upload: C://opt//upFiles
     #webapp鏂囦欢璺緞
     webapp: C://opt//upFiles
diff --git a/lxzn-module-system/lxzn-system-start/src/main/resources/jeecg/jeecg_config.properties b/lxzn-module-system/lxzn-system-start/src/main/resources/jeecg/jeecg_config.properties
index 6a9d602..21cea27 100644
--- a/lxzn-module-system/lxzn-system-start/src/main/resources/jeecg/jeecg_config.properties
+++ b/lxzn-module-system/lxzn-system-start/src/main/resources/jeecg/jeecg_config.properties
@@ -1,7 +1,7 @@
 #code_generate_project_path
 project_path=F:\\java_workspace
 #bussi_package[User defined]
-bussi_package=org.jeecg.modules.mdc
+bussi_package=org.jeecg.modules.ai
 
 
 #default code path
diff --git a/lxzn-module-system/lxzn-system-start/src/test/java/org/jeecg/modules/ai/AiTest.java b/lxzn-module-system/lxzn-system-start/src/test/java/org/jeecg/modules/ai/AiTest.java
new file mode 100644
index 0000000..1aec897
--- /dev/null
+++ b/lxzn-module-system/lxzn-system-start/src/test/java/org/jeecg/modules/ai/AiTest.java
@@ -0,0 +1,80 @@
+package org.jeecg.modules.ai;
+
+import org.jeecg.JeecgSystemApplication;
+import org.jeecg.modules.ai.service.IFilePdfInfoService;
+import org.jeecg.modules.ai.service.IWebSocketAiService;
+import org.jeecg.modules.ai.vo.FilePdfSelectVo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.File;
+
+/**
+ * @author clown
+ * * @date 2024/7/16
+ */
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = JeecgSystemApplication.class)
+public class AiTest {
+
+    @Autowired
+    private IFilePdfInfoService filePdfInfoService;
+    @Autowired
+    private IWebSocketAiService webSocketAiService;
+
+    @Test
+    public void selectChatIA() {
+        webSocketAiService.selectChatIA();
+    }
+
+    @Test
+    public void filePdf() {
+        // 鎸囧畾鏂囦欢澶硅矾寰�
+        String directoryPath = "F:\\file";
+        // 鍒涘缓File瀵硅薄琛ㄧず鏂囦欢澶�
+        File directory = new File(directoryPath);
+        // 鑾峰彇鏂囦欢澶逛腑鎵�鏈夋枃浠跺拰鏂囦欢澶�
+        File[] files = directory.listFiles();
+        // 妫�鏌ユ枃浠舵暟缁勬槸鍚︿负绌轰互鍙婃槸鍚﹀瓨鍦ㄦ枃浠�
+        if (files != null && files.length > 0) {
+            // 閬嶅巻鏂囦欢鏁扮粍锛屾墦鍗版瘡涓枃浠剁殑鍚嶅瓧
+            for (File file : files) {
+                if (file.isFile()) { // 纭繚鏄枃浠惰�岄潪鏂囦欢澶�
+                    System.out.println(file.getName());
+                    filePdfInfoService.uploadFilePdf
+                            (new File(directoryPath + "\\" + file.getName()));
+                }
+            }
+        } else {
+            System.out.println("鏂囦欢澶逛负绌烘垨涓嶅瓨鍦ㄣ��");
+        }
+
+    }
+
+    @Test
+    public void filePdfImg() {
+        FilePdfSelectVo vo = new FilePdfSelectVo();
+        vo.setPdfContent("鍒�闀�");
+        vo.setPdfFileId("1821103772084142082");
+        filePdfInfoService.findImgPathList(vo);
+    }
+
+    @Test
+    public void sendJsonToHttpsPost() {
+      /*  String name = "{\"id\":\"683a65fd-8feb-4446-ad32-714c4785f667\",\"messages\":[{\"role\":\"user\",\"content\":\"缁欐垜璁蹭釜鏁呬簨锛焅"}],\"stream\":true,\"max_tokens\":500}"; // JSON鏁版嵁
+        String url = "https://836u458t54.vicp.fun/chat/test_chat";
+        String aiPost =  AiTestUils.sendJsonToHttpsPost(url, name);
+        System.out.println(aiPost);*/
+
+        String s = "\"data\": {\"id\": \"683a65fd-8feb-4446-ad32-714c4785f667\", \"created\": 1723105518, \"model\": \"YxCareer0.7\", \"choices\": [{\"index\": 0, \"delta\": {\"role\": \"assistant\", \"content\": \"\"}, \"finish_reason\": null}]}";
+        System.out.println(s);
+
+
+
+    }
+
+}
diff --git a/lxzn-module-system/lxzn-system-start/src/test/java/org/jeecg/modules/mdcJc/MesTest.java b/lxzn-module-system/lxzn-system-start/src/test/java/org/jeecg/modules/mdcJc/MesTest.java
deleted file mode 100644
index 7a9dea5..0000000
--- a/lxzn-module-system/lxzn-system-start/src/test/java/org/jeecg/modules/mdcJc/MesTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.jeecg.modules.mdcJc;
-
-import org.jeecg.JeecgSystemApplication;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-/**
- * @author clown
- * * @date 2024/7/16
- */
-@RunWith(SpringRunner.class)
-@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = JeecgSystemApplication.class)
-public class MesTest {
-}
diff --git a/pom.xml b/pom.xml
index 4b91570..59ebbff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,8 +125,31 @@
 			<artifactId>pegdown</artifactId>
 			<version>${pegdown.version}</version>
 		</dependency>
+		<!--浣跨敤itextpdf锛屾瘮pdfbox绠�鍗曚簺-->
+		<dependency>
+			<groupId>com.itextpdf</groupId>
+			<artifactId>itextpdf</artifactId>
+			<version>5.5.13.2</version>
+		</dependency>
+		<!--蹇呴』鍔犲叆杩欎釜锛屽惁鍒欎腑鏂囦細涔辩爜鎴栦负绌�-->
+		<dependency>
+			<groupId>com.itextpdf</groupId>
+			<artifactId>itext-asian</artifactId>
+			<version>5.2.0</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sourceforge.tess4j</groupId>
+			<artifactId>tess4j</artifactId>
+			<version>4.5.1</version>
+		</dependency>
+
+
 	</dependencies>
 
+
+
+
+
 	<dependencyManagement>
 		<dependencies>
 			<!-- spring-cloud-->

--
Gitblit v1.9.3