2 Commits 808d6b2566 ... 062199c500

Autor SHA1 Mensagem Data
  徐滕 062199c500 Merge remote-tracking branch 'origin/master' 1 week atrás
  徐滕 23ed65bf7e dify聊天窗部分功能代码提交 1 week atrás

+ 19 - 0
pom.xml

@@ -1072,6 +1072,25 @@
             <artifactId>alibaba-dingtalk-service-sdk</artifactId>
             <version>2.0.0</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dysmsapi20170525</artifactId>
+            <version>3.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.5.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
+            <version>2.1.0</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 238 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/dify/DifyApiClient.java

@@ -0,0 +1,238 @@
+package com.jeeplus.modules.knowledgeSharing.dify;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.FormBodyPartBuilder;
+import org.apache.http.entity.mime.HttpMultipartMode;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.FileBody;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 知识分享Controller
+ * @author 徐滕
+ * @create 2022-04-11 09:20
+ */
+public class DifyApiClient {
+
+    // Dify API 密钥和端点
+    private static final String API_KEY = "app-rWTbPVHyPDLqWOqqWX1DQ6EQ"; // 替换为你的 Dify API 密钥
+    private static final String API_URL = "http://localhost/v1/chat-messages"; // 替换为实际的 Dify API 端点
+
+    public static void main(String[] args) {
+        try {
+            // 调用 Dify API
+            JSONObject result = selectKnowledgeBaseList();
+            System.out.println("API Response: " + result.toString(4)); // 格式化输出 JSON 响应
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 聊天窗查询
+     * @return
+     * @throws Exception
+     */
+    public static JSONObject callDifyApi() throws Exception {
+        // 创建 HTTP 客户端
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            // 创建 POST 请求
+            HttpPost httpPost = new HttpPost(API_URL);
+
+            // 设置请求头
+            httpPost.setHeader("Content-Type", "application/json");
+            httpPost.setHeader("Authorization", "Bearer " + API_KEY);
+
+            // 构建请求体(根据 Dify API 文档调整参数)
+            JSONObject requestBody = new JSONObject();
+            requestBody.put("inputs", new JSONObject().put("text", "Hello Dify!")); // 输入文本
+            requestBody.put("query", "新修订《审计法》背景下工程审计概述"); // 查询内容
+            requestBody.put("response_mode", "blocking"); // 响应模式
+            requestBody.put("conversation_id", ""); // 会话 ID(可选)
+            requestBody.put("user", "user-123"); // 用户标识(可选)
+
+            // 设置请求体
+            StringEntity entity = new StringEntity(requestBody.toString(), "UTF-8");
+            httpPost.setEntity(entity);
+
+            // 执行请求并获取响应
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                HttpEntity responseEntity = response.getEntity();
+
+                if (response.getStatusLine().getStatusCode() == 200) {
+                    // 解析响应
+                    String responseString = EntityUtils.toString(responseEntity);
+                    return new JSONObject(responseString);
+                } else {
+                    throw new RuntimeException("API request failed with status code: "
+                            + response.getStatusLine().getStatusCode());
+                }
+            }
+        }
+    }
+
+    /**
+     * 通过文本创建文档
+     * @return
+     * @throws Exception
+     */
+    public static JSONObject createByTextDifyApi() throws Exception {
+        // 创建 HTTP 客户端
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            // 创建 POST 请求
+            HttpPost httpPost = new HttpPost("http://localhost/v1/datasets/e2f96c65-8b83-4305-a404-609304ad355e/document/create-by-text");
+
+
+            // 设置请求头
+            httpPost.setHeader("Content-Type", "application/json");
+            httpPost.setHeader("Authorization", "Bearer " + "dataset-rnKsBl9h5FLwajzFPGd38SEu");
+
+            // 请求体
+            JSONObject requestBody = new JSONObject();
+            requestBody.put("name", "text"); // 文档名称
+            requestBody.put("text", "其中有 3 个变电站为暂估价材料,暂估价材料单价平均为"); // 文档内容
+            requestBody.put("indexing_technique", "high_quality"); // 索引方式
+            requestBody.put("process_rule", new JSONObject().put("mode", "automatic")); // 处理规则
+
+            // 设置请求体
+            StringEntity entity = new StringEntity(requestBody.toString(), "UTF-8");
+            httpPost.setEntity(entity);
+
+            // 执行请求并获取响应
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                HttpEntity responseEntity = response.getEntity();
+
+                if (response.getStatusLine().getStatusCode() == 200) {
+                    // 解析响应
+                    String responseString = EntityUtils.toString(responseEntity);
+                    System.out.println(responseString);
+                    return new JSONObject(responseString);
+                } else {
+                    throw new RuntimeException("API request failed with status code: "
+                            + response.getStatusLine().getStatusCode());
+                }
+            }
+        }
+    }
+
+    /**
+     * 通过文件创建文档
+     * @return
+     * @throws Exception
+     */
+    public static JSONObject createByFileDifyApi() throws Exception {
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            HttpPost httpPost = new HttpPost("http://localhost/v1/datasets/e2f96c65-8b83-4305-a404-609304ad355e/document/create-by-file");
+
+            // 设置 Authorization 头
+            httpPost.setHeader("Authorization", "Bearer dataset-rnKsBl9h5FLwajzFPGd38SEu");
+
+            // 构建 JSON 参数
+            JSONObject dataJson = new JSONObject();
+            dataJson.put("indexing_technique", "high_quality");
+
+            JSONObject processRule = new JSONObject();
+            JSONObject rules = new JSONObject();
+            rules.put("pre_processing_rules", new JSONArray()
+                    .put(new JSONObject().put("id", "remove_extra_spaces").put("enabled", true))
+                    .put(new JSONObject().put("id", "remove_urls_emails").put("enabled", true)));
+            JSONObject segmentation = new JSONObject();
+            segmentation.put("separator", "###");
+            segmentation.put("max_tokens", 500);
+            rules.put("segmentation", segmentation);
+            processRule.put("rules", rules);
+            processRule.put("mode", "custom");
+
+            dataJson.put("process_rule", processRule);
+
+            // 中文文件路径
+            File file = new File("D:/项目导入模板.xlsx"); // 上传文件,支持中文
+
+            // 构建 Multipart 请求体
+            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
+
+            // 添加 JSON 文本部分
+            builder.addTextBody("data", dataJson.toString(), ContentType.APPLICATION_JSON);
+
+            // 构建 FileBody
+            FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
+
+            // 构建支持 UTF-8 文件名的 part
+            FormBodyPartBuilder filePartBuilder = FormBodyPartBuilder.create()
+                    .setName("file")
+                    .setBody(fileBody);
+
+            // 添加 Content-Disposition 支持 filename* 编码
+            String encodedFileName = URLEncoder.encode(file.getName(), "UTF-8");
+            filePartBuilder.addField("Content-Disposition", "form-data; name=\"file\"; filename*=utf-8''" + encodedFileName);
+
+            // 添加文件部分
+            builder.addPart(filePartBuilder.build());
+
+            // 设置最终请求体
+            httpPost.setEntity(builder.build());
+
+            // 执行请求
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                HttpEntity responseEntity = response.getEntity();
+                String responseString = EntityUtils.toString(responseEntity, "UTF-8");
+
+                if (response.getStatusLine().getStatusCode() == 200) {
+                    System.out.println("上传成功: " + responseString);
+                    return new JSONObject(responseString);
+                } else {
+                    System.err.println("错误响应: " + responseString);
+                    throw new RuntimeException("上传失败,状态码: " + response.getStatusLine().getStatusCode());
+                }
+            }
+        }
+    }
+
+
+
+    /**
+     * 知识库文档列表
+     * @return
+     * @throws Exception
+     */
+    public static JSONObject selectKnowledgeBaseList() throws Exception {
+        // 创建 HTTP 客户端
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            // 创建 GET 请求
+            HttpGet httpGet = new HttpGet("http://3081089em4.wicp.vip:20667/v1/datasets?page=1&limit=20");
+
+            // 设置请求头
+            httpGet.setHeader("Authorization", "Bearer dataset-TinelGDdnlrXJPyFe38iA0Zh");
+
+            // 执行请求并获取响应
+            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
+                HttpEntity responseEntity = response.getEntity();
+
+                String responseString = EntityUtils.toString(responseEntity, "UTF-8");
+                if (response.getStatusLine().getStatusCode() == 200) {
+                    System.out.println(responseString);
+                    return new JSONObject(responseString);
+                } else {
+                    throw new RuntimeException("API request failed with status code: "
+                            + response.getStatusLine().getStatusCode() + "\nResponse: " + responseString);
+                }
+            }
+        }
+    }
+
+
+}

+ 73 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/dify/KnowledgeDifyController.java

@@ -0,0 +1,73 @@
+package com.jeeplus.modules.knowledgeSharing.dify;
+
+import com.jeeplus.common.utils.StringUtils;
+import com.jeeplus.common.web.BaseController;
+import com.jeeplus.modules.knowledgeSharing.entity.KnowledgeSharingInfo;
+import com.jeeplus.modules.knowledgeSharing.entity.KnowledgeSharingTypeInfo;
+import com.jeeplus.modules.knowledgeSharing.service.KnowledgeSharingTypeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+
+/**
+ * 知识分享Controller
+ * @author 徐滕
+ * @create 2022-04-11 09:20
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/dify/knowledgeSharingDetails/knowledgeSharingDetails")
+public class KnowledgeDifyController extends BaseController {
+
+    @Autowired
+    private KnowledgeSharingTypeService typeService;
+
+    /**
+     * 业务提问-所有问题展示页
+     */
+    @RequestMapping(value = {"list", ""})
+    public String list(KnowledgeSharingInfo knowledgeSharingInfo, HttpServletRequest request, Model model) {
+        String difySrc = "http://localhost/chatbot/";
+        List<KnowledgeSharingTypeInfo> typeInfoList = typeService.findList(new KnowledgeSharingTypeInfo());
+        if (StringUtils.isBlank(knowledgeSharingInfo.getColumnId())) {
+
+            model.addAttribute("columnId", "7");
+            knowledgeSharingInfo.setColumnId("7");
+        }else{
+            model.addAttribute("columnId", knowledgeSharingInfo.getColumnId());
+        }
+        model.addAttribute("typeInfoList", typeInfoList);
+        model.addAttribute("difySrc", difySrc + "LlXD0YzBLGPKBlqb");
+        //根据不同的栏目id 跳转不同的dify聊天窗口
+        if (StringUtils.isNotBlank(knowledgeSharingInfo.getColumnId())) {
+            switch (knowledgeSharingInfo.getColumnId()){
+                case "1":   //学习园地
+                    model.addAttribute("difySrc", difySrc + "6A7qteLy6CtDSHVf");
+                    break;
+                case "9":   //国家标准及规范
+                    model.addAttribute("difySrc", difySrc + "2NV1GQvNY9IxM1lA");
+                    break;
+                case "7":   //行业标准及规范
+                    model.addAttribute("difySrc", difySrc + "vKk88XwbCBfgaiQH");
+                    break;
+                case "8":   //公司内部发文和通知
+                    model.addAttribute("difySrc", difySrc + "V7fLUXpZ4w73ftgG");
+                    break;
+                case "2":   //请教专家
+                    model.addAttribute("difySrc", difySrc + "jpxMOy6u9zXQ5Uuz");
+                    break;
+                case "6":   //案例讨论
+                    model.addAttribute("difySrc", difySrc + "LzY2NuohCsayFwmG");
+                    break;
+                default:
+                    model.addAttribute("difySrc", difySrc + "LlXD0YzBLGPKBlqb");
+                    break;
+            }
+        }
+        return "modules/knowledgeSharing/dify/knowledgeSharingDetailsList";
+    }
+}

+ 40 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/entity/ExternalKnowledgeInfo.java

@@ -0,0 +1,40 @@
+package com.jeeplus.modules.knowledgeSharing.entity;
+
+public class ExternalKnowledgeInfo {
+    private String externalKnowledgeApiName;
+    private String externalKnowledgeApiId;
+    private String externalKnowledgeApiEndpoint;
+    private String externalKnowledgeId;
+
+    public String getExternalKnowledgeApiName() {
+        return externalKnowledgeApiName;
+    }
+
+    public void setExternalKnowledgeApiName(String externalKnowledgeApiName) {
+        this.externalKnowledgeApiName = externalKnowledgeApiName;
+    }
+
+    public String getExternalKnowledgeApiId() {
+        return externalKnowledgeApiId;
+    }
+
+    public void setExternalKnowledgeApiId(String externalKnowledgeApiId) {
+        this.externalKnowledgeApiId = externalKnowledgeApiId;
+    }
+
+    public String getExternalKnowledgeApiEndpoint() {
+        return externalKnowledgeApiEndpoint;
+    }
+
+    public void setExternalKnowledgeApiEndpoint(String externalKnowledgeApiEndpoint) {
+        this.externalKnowledgeApiEndpoint = externalKnowledgeApiEndpoint;
+    }
+
+    public String getExternalKnowledgeId() {
+        return externalKnowledgeId;
+    }
+
+    public void setExternalKnowledgeId(String externalKnowledgeId) {
+        this.externalKnowledgeId = externalKnowledgeId;
+    }
+}

+ 31 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/entity/ExternalRetrievalModel.java

@@ -0,0 +1,31 @@
+package com.jeeplus.modules.knowledgeSharing.entity;
+
+public class ExternalRetrievalModel {
+    private Object scoreThreshold;
+    private boolean scoreThresholdEnabled;
+    private int topK;
+
+    public Object getScoreThreshold() {
+        return scoreThreshold;
+    }
+
+    public void setScoreThreshold(Object scoreThreshold) {
+        this.scoreThreshold = scoreThreshold;
+    }
+
+    public boolean isScoreThresholdEnabled() {
+        return scoreThresholdEnabled;
+    }
+
+    public void setScoreThresholdEnabled(boolean scoreThresholdEnabled) {
+        this.scoreThresholdEnabled = scoreThresholdEnabled;
+    }
+
+    public int getTopK() {
+        return topK;
+    }
+
+    public void setTopK(int topK) {
+        this.topK = topK;
+    }
+}

+ 222 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/entity/KnowledgeBase.java

@@ -0,0 +1,222 @@
+package com.jeeplus.modules.knowledgeSharing.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.jeeplus.common.persistence.DataEntity;
+import com.jeeplus.modules.knowledgeSharing.utils.CustomDateConverter;
+
+import java.util.Date;
+import java.util.List;
+
+public class KnowledgeBase extends DataEntity<KnowledgeBase> {
+    @JsonProperty("document_count")
+    private int documentCount;
+    @JsonProperty("indexing_technique")
+    private String indexingTechnique;
+    @JsonProperty("retrieval_model_dict")
+    private RetrievalModelDict retrievalModelDict;
+    private ExternalRetrievalModel externalRetrievalModel;
+    private String embeddingModel;
+    private String docForm;
+    private String description;
+
+    @JsonDeserialize(converter = CustomDateConverter.class)
+    private Date createdAt;
+
+    private String permission;
+    private String dataSourceType;
+    private String createdBy;
+    private List<String> tags;
+    private String embeddingModelProvider;
+    private int wordCount;
+
+    @JsonDeserialize(converter = CustomDateConverter.class)
+    private Date updatedAt;
+
+    private String provider;
+    private String name;
+    private String updatedBy;
+    private ExternalKnowledgeInfo externalKnowledgeInfo;
+    private String id;
+    private boolean embeddingAvailable;
+    private int appCount;
+
+    public int getDocumentCount() {
+        return documentCount;
+    }
+
+    public void setDocumentCount(int documentCount) {
+        this.documentCount = documentCount;
+    }
+
+    public String getIndexingTechnique() {
+        return indexingTechnique;
+    }
+
+    public void setIndexingTechnique(String indexingTechnique) {
+        this.indexingTechnique = indexingTechnique;
+    }
+
+    public RetrievalModelDict getRetrievalModelDict() {
+        return retrievalModelDict;
+    }
+
+    public void setRetrievalModelDict(RetrievalModelDict retrievalModelDict) {
+        this.retrievalModelDict = retrievalModelDict;
+    }
+
+    public ExternalRetrievalModel getExternalRetrievalModel() {
+        return externalRetrievalModel;
+    }
+
+    public void setExternalRetrievalModel(ExternalRetrievalModel externalRetrievalModel) {
+        this.externalRetrievalModel = externalRetrievalModel;
+    }
+
+    public String getEmbeddingModel() {
+        return embeddingModel;
+    }
+
+    public void setEmbeddingModel(String embeddingModel) {
+        this.embeddingModel = embeddingModel;
+    }
+
+    public String getDocForm() {
+        return docForm;
+    }
+
+    public void setDocForm(String docForm) {
+        this.docForm = docForm;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Date getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(Date createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public String getPermission() {
+        return permission;
+    }
+
+    public void setPermission(String permission) {
+        this.permission = permission;
+    }
+
+    public String getDataSourceType() {
+        return dataSourceType;
+    }
+
+    public void setDataSourceType(String dataSourceType) {
+        this.dataSourceType = dataSourceType;
+    }
+
+    public String getCreatedBy() {
+        return createdBy;
+    }
+
+    public void setCreatedBy(String createdBy) {
+        this.createdBy = createdBy;
+    }
+
+    public List<String> getTags() {
+        return tags;
+    }
+
+    public void setTags(List<String> tags) {
+        this.tags = tags;
+    }
+
+    public String getEmbeddingModelProvider() {
+        return embeddingModelProvider;
+    }
+
+    public void setEmbeddingModelProvider(String embeddingModelProvider) {
+        this.embeddingModelProvider = embeddingModelProvider;
+    }
+
+    public int getWordCount() {
+        return wordCount;
+    }
+
+    public void setWordCount(int wordCount) {
+        this.wordCount = wordCount;
+    }
+
+    public Date getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(Date updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public String getProvider() {
+        return provider;
+    }
+
+    public void setProvider(String provider) {
+        this.provider = provider;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getUpdatedBy() {
+        return updatedBy;
+    }
+
+    public void setUpdatedBy(String updatedBy) {
+        this.updatedBy = updatedBy;
+    }
+
+    public ExternalKnowledgeInfo getExternalKnowledgeInfo() {
+        return externalKnowledgeInfo;
+    }
+
+    public void setExternalKnowledgeInfo(ExternalKnowledgeInfo externalKnowledgeInfo) {
+        this.externalKnowledgeInfo = externalKnowledgeInfo;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public boolean isEmbeddingAvailable() {
+        return embeddingAvailable;
+    }
+
+    public void setEmbeddingAvailable(boolean embeddingAvailable) {
+        this.embeddingAvailable = embeddingAvailable;
+    }
+
+    public int getAppCount() {
+        return appCount;
+    }
+
+    public void setAppCount(int appCount) {
+        this.appCount = appCount;
+    }
+}

+ 51 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/entity/KnowledgeBaseResponse.java

@@ -0,0 +1,51 @@
+package com.jeeplus.modules.knowledgeSharing.entity;
+
+import java.util.List;
+
+public class KnowledgeBaseResponse {
+    private int total;
+    private List<KnowledgeBase> data;
+    private int limit;
+    private boolean hasMore;
+    private int page;
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+    public List<KnowledgeBase> getData() {
+        return data;
+    }
+
+    public void setData(List<KnowledgeBase> data) {
+        this.data = data;
+    }
+
+    public int getLimit() {
+        return limit;
+    }
+
+    public void setLimit(int limit) {
+        this.limit = limit;
+    }
+
+    public boolean isHasMore() {
+        return hasMore;
+    }
+
+    public void setHasMore(boolean hasMore) {
+        this.hasMore = hasMore;
+    }
+
+    public int getPage() {
+        return page;
+    }
+
+    public void setPage(int page) {
+        this.page = page;
+    }
+}

+ 22 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/entity/RerankingModel.java

@@ -0,0 +1,22 @@
+package com.jeeplus.modules.knowledgeSharing.entity;
+
+public class RerankingModel {
+    private String rerankingProviderName;
+    private String rerankingModelName;
+
+    public String getRerankingProviderName() {
+        return rerankingProviderName;
+    }
+
+    public void setRerankingProviderName(String rerankingProviderName) {
+        this.rerankingProviderName = rerankingProviderName;
+    }
+
+    public String getRerankingModelName() {
+        return rerankingModelName;
+    }
+
+    public void setRerankingModelName(String rerankingModelName) {
+        this.rerankingModelName = rerankingModelName;
+    }
+}

+ 78 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/entity/RetrievalModelDict.java

@@ -0,0 +1,78 @@
+package com.jeeplus.modules.knowledgeSharing.entity;
+
+import com.jeeplus.common.persistence.DataEntity;
+
+public class RetrievalModelDict extends DataEntity<RetrievalModelDict> {
+    private Object scoreThreshold;
+    private Object rerankingMode;
+    private boolean scoreThresholdEnabled;
+    private RerankingModel rerankingModel;
+    private int topK;
+    private Object weights;
+    private String searchMethod;
+    private boolean rerankingEnable;
+
+    public Object getScoreThreshold() {
+        return scoreThreshold;
+    }
+
+    public void setScoreThreshold(Object scoreThreshold) {
+        this.scoreThreshold = scoreThreshold;
+    }
+
+    public Object getRerankingMode() {
+        return rerankingMode;
+    }
+
+    public void setRerankingMode(Object rerankingMode) {
+        this.rerankingMode = rerankingMode;
+    }
+
+    public boolean isScoreThresholdEnabled() {
+        return scoreThresholdEnabled;
+    }
+
+    public void setScoreThresholdEnabled(boolean scoreThresholdEnabled) {
+        this.scoreThresholdEnabled = scoreThresholdEnabled;
+    }
+
+    public RerankingModel getRerankingModel() {
+        return rerankingModel;
+    }
+
+    public void setRerankingModel(RerankingModel rerankingModel) {
+        this.rerankingModel = rerankingModel;
+    }
+
+    public int getTopK() {
+        return topK;
+    }
+
+    public void setTopK(int topK) {
+        this.topK = topK;
+    }
+
+    public Object getWeights() {
+        return weights;
+    }
+
+    public void setWeights(Object weights) {
+        this.weights = weights;
+    }
+
+    public String getSearchMethod() {
+        return searchMethod;
+    }
+
+    public void setSearchMethod(String searchMethod) {
+        this.searchMethod = searchMethod;
+    }
+
+    public boolean isRerankingEnable() {
+        return rerankingEnable;
+    }
+
+    public void setRerankingEnable(boolean rerankingEnable) {
+        this.rerankingEnable = rerankingEnable;
+    }
+}

+ 15 - 0
src/main/java/com/jeeplus/modules/knowledgeSharing/utils/CustomDateConverter.java

@@ -0,0 +1,15 @@
+package com.jeeplus.modules.knowledgeSharing.utils;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.util.StdConverter;
+
+import java.util.Date;
+
+public class CustomDateConverter extends StdConverter<Long, Date> {
+    @Override
+    public Date convert(Long value) {
+        return new Date(value * 1000); // 秒转毫秒
+    }
+}

+ 81 - 0
src/main/webapp/webpage/modules/knowledgeSharing/dify/knowledgeSharingDetailsList.jsp

@@ -0,0 +1,81 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+	<title>知识分享-栏目列表</title>
+	<meta name="decorator" content="default"/>
+	<script type="text/javascript" src="${ctxStatic}/ckeditor/ckeditor.js"></script>
+	<script type="text/javascript">
+		$(document).ready(function() {
+			//搜索框收放
+			$('#moresee').click(function(){
+				if($('#moresees').is(':visible'))
+				{
+					$('#moresees').slideUp(0,resizeListWindow1);
+					$('#moresee i').removeClass("glyphicon glyphicon-menu-up").addClass("glyphicon glyphicon-menu-down");
+				}else{
+					$('#moresees').slideDown(0,resizeListWindow1);
+					$('#moresee i').removeClass("glyphicon glyphicon-menu-down").addClass("glyphicon glyphicon-menu-up");
+				}
+			});
+
+			var columnId = '${columnId}';
+			$(".list-tabs li").each(function(){
+				$(this).removeAttr("class","active");
+				var id='#'+$(this).find("span").html();
+				$(id).attr("class","hide");
+				if($(this).val() == columnId){
+					$(this).attr("class","active");
+					var id='#'+$(this).find("span").html();
+					$(id).removeAttr("class","hide");
+				}
+				$("#columnId").val(columnId)
+			})
+
+			$(".list-tabs li").click(function(){
+				$(".list-tabs li").each(function(){
+					$(this).removeAttr("class","active");
+					var id='#'+$(this).find("span").html();
+					$(id).attr("class","hide");
+				})
+				$(this).attr("class","active");
+				var id='#'+$(this).find("span").html();
+				$(id).removeAttr("class","hide");
+
+				$("#columnId").val($(this).val())
+				$("#searchForm").submit();
+			})
+		});
+	</script>
+</head>
+<body>
+<div class="wrapper wrapper-content">
+	<sys:message content="${message}"/>
+	<div class="list-form-tab contentShadow shadowLTR" id="tabDiv">
+		<ul class="list-tabs" >
+			<c:forEach items="${typeInfoList}" var="typeInfo">
+				<li value="${typeInfo.key}"><a>${typeInfo.value}</a></li>
+			</c:forEach>
+		</ul>
+	</div>
+	<iframe
+			src="${difySrc}"
+			style="width: 100%; height: 90%; min-height: 700px"
+			frameborder="0"
+			allow="microphone">
+	</iframe>
+	<form:form id="searchForm" modelAttribute="knowledgeSharingInfo" action="${ctx}/dify/knowledgeSharingDetails/knowledgeSharingDetails/list" method="post" class="form-inline">
+		<input id="columnId" name="columnId" type="hidden" value="${columnId}"/>
+	</form:form>
+	<div id="changewidth"></div>
+</div>
+<script src="${ctxStatic}/layer-v2.3/layui/layui.all.js" charset="utf-8"></script>
+
+<script>
+	resizeListWindow1();
+	$(window).resize(function(){
+		resizeListWindow1();
+	});
+</script>
+</body>
+</html>

+ 7 - 2
src/main/webapp/webpage/modules/ruralprojectrecords/cost/projectcontentinfo/new/reportForm.jsp

@@ -701,15 +701,20 @@
 			top.layer.msg("已确认!", {icon: 1});
 		}
 		function getFee() {
+			console.log("进入fee方法")
 			//送审价
 			var rf = $("#reviewFee").val();
 			//审定价
 			var af = $("#approvalFee").val();
 			if(rf != '' && rf != '0.00' && af !='' && af !='0.00'){
 				var hf = (af*100-rf*100)/100;
-				var rate = parseFloat(hf) / parseFloat(rf) * 100
 				$("#verifyFee").val(hf.toFixed(2));
-				$("#verifyRate").val(rate.toFixed(2));
+				if(rf == 0){
+					$("#verifyRate").val(0);
+				}else{
+					var rate = parseFloat(hf) / parseFloat(rf) * 100
+					$("#verifyRate").val(rate.toFixed(2));
+				}
 			}
 			if(af !=''){
 				$("#consultFee").val(af)

+ 22 - 0
src/main/webapp/webpage/modules/sys/sysIndex.jsp

@@ -18,6 +18,28 @@
     <script src="${ctxStatic}/common/contabs.js"></script>
     <meta name="keywords" content="JeePlus快速开发平台">
     <meta name="description" content="JeePlus,采用spring mvc+mybatis+shiro+bootstrap,集成代码生成器的快速开发平台">
+
+<%-- 添加dify AI对话窗口 --%>
+    <script>
+        window.difyChatbotConfig = {
+            token: 'LlXD0YzBLGPKBlqb',
+            baseUrl: 'http://localhost'
+        }
+    </script>
+    <script
+            src="http://localhost/embed.min.js"
+            id="LlXD0YzBLGPKBlqb"
+            defer>
+    </script>
+    <style>
+        #dify-chatbot-bubble-button {
+            background-color: #1C64F2 !important;
+        }
+        #dify-chatbot-bubble-window {
+            width: 64rem !important;
+            height: 60rem !important;
+        }
+    </style>
     <script type="text/javascript">
         $(document).ready(function() {
             if('${fns:getDictLabel(cookie.theme.value,'theme','默认主题')}' == '天蓝主题'){

+ 1 - 1
src/main/webapp/webpage/modules/workreimbursement/new/workReimbursementNewFormAdd.jsp

@@ -1364,7 +1364,7 @@
                         <th width="100px"><font color="red">*</font>金额</th>
                         <th width="100px"><font color="red">*</font>税额</th>
                         <th width="100px"><font color="red">*</font>价税合计</th>
-                        <td style="width: 200px; max-width: 200px; text-align: center; vertical-align: middle; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">文件预览</th>
+                        <th style="width: 200px; max-width: 200px; text-align: center; vertical-align: middle; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">文件预览</th>
                         <th width="100px">上传人</th>
                         <th width="150px">上传时间</th>
                         <th width="200px">操作<th>