guanz преди 1 година
родител
ревизия
8a9ef5006f
променени са 16 файла, в които са добавени 877 реда и са изтрити 31 реда
  1. 23 0
      src/main/java/com/pavis/backend/slim/common/utils/CommonUtils.java
  2. 175 0
      src/main/java/com/pavis/backend/slim/common/utils/SnowflakeIdWorkerUtils.java
  3. 30 5
      src/main/java/com/pavis/backend/slim/project/system/client/AlgKgClient.java
  4. 70 0
      src/main/java/com/pavis/backend/slim/project/system/controller/AnnotationController.java
  5. 71 0
      src/main/java/com/pavis/backend/slim/project/system/domain/AnnotationList.java
  6. 34 0
      src/main/java/com/pavis/backend/slim/project/system/domain/annotation/AnnotationListParam.java
  7. 33 0
      src/main/java/com/pavis/backend/slim/project/system/domain/annotation/ImportAnnotationDataset.java
  8. 27 0
      src/main/java/com/pavis/backend/slim/project/system/domain/annotation/ImportDataset.java
  9. 20 0
      src/main/java/com/pavis/backend/slim/project/system/mapper/AnnotationListMapper.java
  10. 47 0
      src/main/java/com/pavis/backend/slim/project/system/service/AnnotationListService.java
  11. 11 0
      src/main/java/com/pavis/backend/slim/project/system/service/SysFileService.java
  12. 231 0
      src/main/java/com/pavis/backend/slim/project/system/service/impl/AnnotationListServiceImpl.java
  13. 52 23
      src/main/java/com/pavis/backend/slim/project/system/service/impl/SysFileServiceImpl.java
  14. 10 2
      src/main/java/com/pavis/backend/slim/project/system/service/impl/SysKbFileServiceImpl.java
  15. 2 1
      src/main/resources/application-ghj.yml
  16. 41 0
      src/main/resources/mapper/system/AnnotationListMapper.xml

+ 23 - 0
src/main/java/com/pavis/backend/slim/common/utils/CommonUtils.java

@@ -4,6 +4,10 @@ import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.FileInputStream;
 
 /**
  * @version: java version 1.8
@@ -55,4 +59,23 @@ public class CommonUtils {
         }
         return false;
     }
+
+    public static boolean checkMd5(String filename, String md5) {
+        try {
+            FileInputStream fs = new FileInputStream(filename);
+            String uploadFileMd5 = DigestUtils.md5Hex(fs);
+            log.info("uploadFileMd5,{}", uploadFileMd5);
+            if (StringUtils.equalsIgnoreCase(md5, uploadFileMd5)) {
+                return true;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+        return false;
+    }
+
+    public static void main(String[] args) {
+        checkMd5("test1001.docx","saf");
+    }
 }

+ 175 - 0
src/main/java/com/pavis/backend/slim/common/utils/SnowflakeIdWorkerUtils.java

@@ -0,0 +1,175 @@
+package com.pavis.backend.slim.common.utils;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description:
+ * @date: 2023-11-06 16:16
+ */
+public class SnowflakeIdWorkerUtils {
+    /**
+     * 开始时间戳 (2015-01-01)
+     */
+    private final long twepoch = 1420041600000L;
+
+    /**
+     * 机器id所占的位数
+     */
+    private final long workerIdBits = 5L;
+
+    /**
+     * 数据标识id所占的位数
+     */
+    private final long datacenterIdBits = 5L;
+
+    /**
+     * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
+     */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /**
+     * 支持的最大数据标识id,结果是31
+     */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+
+    /**
+     * 序列在id中占的位数
+     */
+    private final long sequenceBits = 12L;
+
+    /**
+     * 机器ID向左移12位
+     */
+    private final long workerIdShift = sequenceBits;
+
+    /**
+     * 数据标识id向左移17位(12+5)
+     */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+    /**
+     * 时间戳向左移22位(5+5+12)
+     */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    /**
+     * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
+     */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /**
+     * 工作机器ID(0~31)
+     */
+    private long workerId;
+
+    /**
+     * 数据中心ID(0~31)
+     */
+    private long datacenterId;
+
+    /**
+     * 毫秒内序列(0~4095)
+     */
+    private long sequence = 0L;
+
+    /**
+     * 上次生成ID的时间戳
+     */
+    private long lastTimestamp = -1L;
+
+    //==============================Constructors=====================================
+
+    /**
+     * 构造函数
+     *
+     * @param workerId     工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public SnowflakeIdWorkerUtils(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    // ==============================Methods==========================================
+
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     *
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间戳
+        lastTimestamp = timestamp;
+
+        //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     *
+     * @param lastTimestamp 上次生成ID的时间戳
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间
+     *
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    /**
+     * 测试
+     */
+    public static void main(String[] args) {
+        System.out.println("开始:" + System.currentTimeMillis());
+        SnowflakeIdWorkerUtils idWorker = new SnowflakeIdWorkerUtils(0, 0);
+        for (int i = 0; i < 50; i++) {
+            long id = idWorker.nextId();
+            System.out.println(id);
+            //System.out.println(Long.toBinaryString(id));
+        }
+        System.out.println("结束:" + System.currentTimeMillis());
+    }
+}

+ 30 - 5
src/main/java/com/pavis/backend/slim/project/system/client/AlgKgClient.java

@@ -5,6 +5,8 @@ import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.PostMapping;
 
+import java.util.Map;
+
 /**
  * @version: java version 1.8
  * @Author: Guan H.J.
@@ -16,28 +18,51 @@ public interface AlgKgClient {
 
     /**
      * 发送标注数据给算法服务,生成图谱。
+     * url: http://192.168.1.150:12000/labels/import
+     *
      * @param data
      * @return
      */
-    @PostMapping(value = "/annotation/testGenerateKgGraph",produces = {MediaType.APPLICATION_JSON_VALUE},
+    // @PostMapping(value = "/annotation/testGenerateKgGraph",produces = {MediaType.APPLICATION_JSON_VALUE},
+    @PostMapping(value = "/labels/import", produces = {MediaType.APPLICATION_JSON_VALUE},
             consumes = "application/json")
     String sendToAlgForGenerateKgGraph(String data);
 
     /**
      * 发送文档需转换为txt的数据给算法服务。
+     *
      * @param data
      * @return
      */
-    @PostMapping(value = "/annotation/convertToTxt",produces = {MediaType.APPLICATION_JSON_VALUE},
-            consumes = "application/json")
+    // @PostMapping(value = "/annotation/convertToTxt",produces = {MediaType.APPLICATION_JSON_VALUE},
+    @PostMapping(value = "/data_import/data_access", produces = {MediaType.APPLICATION_JSON_VALUE},
+            consumes="application/json")
     String convertToTxt(String data);
 
     /**
-     * 通用知识图谱构建,即图谱下无实体、关系数据。
+     * 算法解析txt文本内容返回结果
+     * 根据fileIds获取算法解析的txt文本内容。即去标注时,选择文档去标注时,调用。
+     * @param data
+     * @return
+     */
+    @PostMapping(value = "/data_import/batch_read", produces = {MediaType.APPLICATION_JSON_VALUE},
+            consumes="application/json")
+    String getAlgTxt(String data);
+
+    @PostMapping(value = "/data_import/upload_file",
+            consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
+            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    String getAlgTxtByFile(Map<String, ?> params);
+
+
+    /**
+     * todo 通用知识图谱构建,即图谱下无实体、关系数据。-----> 暂未对接。
+     * 入参:文档ID、图谱ID。
+     *
      * @param data
      * @return
      */
-    @PostMapping(value = "/annotation/universalGgraphToAlg",produces = {MediaType.APPLICATION_JSON_VALUE},
+    @PostMapping(value = "/annotation/universalGgraphToAlg", produces = {MediaType.APPLICATION_JSON_VALUE},
             consumes = "application/json")
     String universalGgraphToAlg(String data);
 }

+ 70 - 0
src/main/java/com/pavis/backend/slim/project/system/controller/AnnotationController.java

@@ -4,23 +4,29 @@ import com.alibaba.fastjson2.JSON;
 import com.pavis.backend.slim.framework.web.domain.AjaxResult;
 import com.pavis.backend.slim.project.system.domain.annotation.AnnotationEntity;
 import com.pavis.backend.slim.project.system.domain.annotation.AnnotationEntityRelation;
+import com.pavis.backend.slim.project.system.domain.annotation.AnnotationListParam;
 import com.pavis.backend.slim.project.system.domain.annotation.AnnotationToAlg;
+import com.pavis.backend.slim.project.system.domain.annotation.ImportAnnotationDataset;
 import com.pavis.backend.slim.project.system.domain.annotation.UniversalGgraphToAlg;
+import com.pavis.backend.slim.project.system.service.AnnotationListService;
 import com.pavis.backend.slim.project.system.service.EntityLablesRelationService;
 import com.pavis.backend.slim.project.system.service.EntityLablesSpanService;
 import com.pavis.backend.slim.project.system.service.SysFileService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -48,6 +54,69 @@ public class AnnotationController {
     @Autowired
     private SysFileService sysFileService;
 
+    @Autowired
+    private AnnotationListService annotationListService;
+
+    @ApiOperation("获取标注数据列表接口")
+    @PostMapping("/getAnnotationLists")
+    public AjaxResult getAnnotationLists(@RequestBody AnnotationListParam annotationListParam) {
+        log.info("数据标注列表接口 annotationListParam:{}", JSON.toJSONString(annotationListParam));
+        if (null != annotationListParam.getKgId() && StringUtils.isNotEmpty(annotationListParam.getKgId()) && null != annotationListParam.getPageNum() && null != annotationListParam.getPageSize()) {
+            return AjaxResult.success("获取数据标注列表成功", annotationListService.getAnnotationLists(annotationListParam));
+        }
+        return AjaxResult.error("参数不能为空");
+    }
+
+    @ApiOperation("删除标注数据列表接口")
+    @PostMapping("/delAnnotationLists")
+    public AjaxResult delAnnotationLists(@RequestBody List<String> ids) {
+        log.info("删除标注数据列表接口 ids:{}", JSON.toJSONString(ids));
+        if (!CollectionUtils.isEmpty(ids)) {
+            Boolean delRes = annotationListService.delAnnotationLists(ids);
+            if (delRes) {
+                return AjaxResult.success("删除标注数据列表成功", delRes);
+            } else {
+                return AjaxResult.error("删除标注数据列表失败", delRes);
+            }
+        }
+        return AjaxResult.error("参数不能为空");
+    }
+
+    @ApiOperation("数据集导入之知识库文档导入接口")
+    @PostMapping("/importAnnotationDataset")
+    public AjaxResult importAnnotationDataset(@RequestBody ImportAnnotationDataset importAnnotationDataset) {
+        log.info("数据集导入之知识库文档导入接口 importAnnotationDataset:{}", JSON.toJSONString(importAnnotationDataset));
+        if (null != importAnnotationDataset.getKgId() && StringUtils.isNotEmpty(importAnnotationDataset.getKgId()) && null != importAnnotationDataset.getImportType() && !CollectionUtils.isEmpty(importAnnotationDataset.getImportDatasets())) {
+            Boolean saveRes = annotationListService.importAnnotationDataset(importAnnotationDataset);
+            if (saveRes) {
+                return AjaxResult.success("数据集导入成功", saveRes);
+            } else {
+                return AjaxResult.error("数据集导入失败", saveRes);
+            }
+        }
+        return AjaxResult.error("参数不能为空");
+    }
+
+    @ApiOperation("数据集导入之本地文件导入接口")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "file", value = "需要上传的文件", required = true, paramType = "form")
+    })
+    @PostMapping(value = "/importLocalAnnotationDataset")
+    public AjaxResult importLocalAnnotationDataset(String kgId, @RequestParam("file") MultipartFile file) throws Exception {
+        if (null != kgId && StringUtils.isNotEmpty(kgId)){
+            if (!file.isEmpty()){
+                return AjaxResult.success("数据集导入之本地文件导入成功!", annotationListService.importLocalAnnotationDataset(kgId,file));
+            }else {
+                return AjaxResult.error("文件不能为空");
+            }
+        }else {
+            return AjaxResult.error("参数不能为空");
+        }
+    }
+
+    // 数据集的导入和导出。
+
+
     /**
      * 文档标注数据存储接口-实体。
      * 同时注意数据回显。
@@ -104,6 +173,7 @@ public class AnnotationController {
         return AjaxResult.error(1001, "参数不能为空");
     }
 
+
     // ----------------------------以下接口均为模拟算法测试接口,后续可删除下列接口------------------------------------。
 
     @ApiOperation("算法 接收标注信息接口 结束后可删除")

+ 71 - 0
src/main/java/com/pavis/backend/slim/project/system/domain/AnnotationList.java

@@ -0,0 +1,71 @@
+package com.pavis.backend.slim.project.system.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.pavis.backend.slim.framework.web.domain.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description: 标注数据列表。
+ * @date: 2023-11-06 13:47
+ */
+@Builder
+@Data
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class AnnotationList extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 主键id。
+     */
+    @ApiModelProperty("主键id")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 知识库所属用户ID。
+     */
+    @ApiModelProperty(value = "图谱ID",required = true)
+    private String kgId;
+
+    /**
+     * 文档ID。
+     */
+    @ApiModelProperty(value = "文档ID",required = true)
+    private String fileId;
+
+    /**
+     * 文档名称。
+     */
+    @ApiModelProperty("文档名称")
+    private String originalName;
+
+    /**
+     * 文档解析txt状态,1 解析完成 0 解析中 -1 解析出错。
+     */
+    @ApiModelProperty("文档解析txt状态")
+    private Integer parseStatus;
+
+    /**
+     * 文档转txt内容。
+     */
+    @ApiModelProperty("文档转txt内容")
+    private String textContent;
+
+    /**
+     * 文档是否被标注,0 未标注 1 已标注。
+     */
+    @ApiModelProperty("文档标注状态")
+    private Integer annotationStatus;
+
+}

+ 34 - 0
src/main/java/com/pavis/backend/slim/project/system/domain/annotation/AnnotationListParam.java

@@ -0,0 +1,34 @@
+package com.pavis.backend.slim.project.system.domain.annotation;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.experimental.SuperBuilder;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description: 标注列表数据获取参数。
+ * @date: 2023-10-26 9:47
+ */
+@SuperBuilder
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class AnnotationListParam{
+    // 图谱ID
+    @ApiModelProperty("图谱ID")
+    private String kgId;
+
+    @ApiModelProperty("搜索条件,即文件名")
+    private String originalName;
+
+    @ApiModelProperty("页数")
+    private Integer pageNum;
+
+    @ApiModelProperty("条数")
+    private Integer pageSize;
+}

+ 33 - 0
src/main/java/com/pavis/backend/slim/project/system/domain/annotation/ImportAnnotationDataset.java

@@ -0,0 +1,33 @@
+package com.pavis.backend.slim.project.system.domain.annotation;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.experimental.SuperBuilder;
+
+import java.util.List;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description: 标注列表数据获取参数。
+ * @date: 2023-10-26 9:47
+ */
+@SuperBuilder
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class ImportAnnotationDataset {
+    // 图谱ID
+    @ApiModelProperty("图谱ID")
+    private String kgId;
+
+    @ApiModelProperty("导入数据集类型 1 知识库中文档 0 本地文档")
+    private Integer importType;
+
+    // 导入数据集列表。
+    List<ImportDataset> importDatasets;
+}

+ 27 - 0
src/main/java/com/pavis/backend/slim/project/system/domain/annotation/ImportDataset.java

@@ -0,0 +1,27 @@
+package com.pavis.backend.slim.project.system.domain.annotation;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.experimental.SuperBuilder;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description: 标注列表数据获取参数。
+ * @date: 2023-10-26 9:47
+ */
+@SuperBuilder
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class ImportDataset {
+    @ApiModelProperty("文档ID")
+    private String fileId;
+
+    @ApiModelProperty("文件名")
+    private String originalName;
+}

+ 20 - 0
src/main/java/com/pavis/backend/slim/project/system/mapper/AnnotationListMapper.java

@@ -0,0 +1,20 @@
+package com.pavis.backend.slim.project.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pavis.backend.slim.project.system.domain.AnnotationList;
+import com.pavis.backend.slim.project.system.domain.annotation.AnnotationListParam;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description: AnnotationListMapper
+ * @date: 2023-11-06 13:58
+ */
+@Mapper
+public interface AnnotationListMapper extends BaseMapper<AnnotationList> {
+
+    List<AnnotationList> selectAnnotationList(AnnotationListParam annotationListParam);
+}

+ 47 - 0
src/main/java/com/pavis/backend/slim/project/system/service/AnnotationListService.java

@@ -0,0 +1,47 @@
+package com.pavis.backend.slim.project.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.github.pagehelper.PageInfo;
+import com.pavis.backend.slim.project.system.domain.AnnotationList;
+import com.pavis.backend.slim.project.system.domain.annotation.AnnotationListParam;
+import com.pavis.backend.slim.project.system.domain.annotation.ImportAnnotationDataset;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description: AnnotationListService
+ * @date: 2023-11-06 13:58
+ */
+public interface AnnotationListService extends IService<AnnotationList> {
+
+    /**
+     * 获取数据标注列表页。
+     * @param annotationListParam
+     * @return
+     */
+    PageInfo getAnnotationLists(AnnotationListParam annotationListParam);
+
+    /**
+     * 删除标注数据列表。
+     * @param ids
+     * @return
+     */
+    Boolean delAnnotationLists(List<String> ids);
+
+    /**
+     * 导入数据集接口。
+     * @param importAnnotationDataset
+     * @return
+     */
+    Boolean importAnnotationDataset(ImportAnnotationDataset importAnnotationDataset);
+
+    /**
+     * 导入本地数据集接口。
+     * @param file
+     * @return
+     */
+    Boolean importLocalAnnotationDataset(String kgId,MultipartFile file);
+}

+ 11 - 0
src/main/java/com/pavis/backend/slim/project/system/service/SysFileService.java

@@ -107,4 +107,15 @@ public interface SysFileService extends IService<SysFile> {
      * 文档转换成txt:调用算法文档转换txt接口,并保存文本内容。
      */
     void convertToTxt(List<String> fileIds);
+
+    /**
+     * 通用解析算法返回值,即文档转txt。
+     * @param convertToTxtResTmp
+     */
+    void dealAlgTxtRes(String convertToTxtResTmp);
+
+    /**
+     * 知识库上传文档时,调用算法去解析文档内容为txt。
+     */
+    void convertfileToTxtByAlg(SysFile sysFile);
 }

+ 231 - 0
src/main/java/com/pavis/backend/slim/project/system/service/impl/AnnotationListServiceImpl.java

@@ -0,0 +1,231 @@
+package com.pavis.backend.slim.project.system.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.pavis.backend.slim.common.utils.CommonUtils;
+import com.pavis.backend.slim.common.utils.SnowflakeIdWorkerUtils;
+import com.pavis.backend.slim.project.system.client.AlgKgClient;
+import com.pavis.backend.slim.project.system.domain.AnnotationList;
+import com.pavis.backend.slim.project.system.domain.annotation.AnnotationListParam;
+import com.pavis.backend.slim.project.system.domain.annotation.ConvertAlgRes;
+import com.pavis.backend.slim.project.system.domain.annotation.ImportAnnotationDataset;
+import com.pavis.backend.slim.project.system.domain.annotation.ImportDataset;
+import com.pavis.backend.slim.project.system.mapper.AnnotationListMapper;
+import com.pavis.backend.slim.project.system.service.AnnotationListService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @version: java version 1.8
+ * @Author: Guan H.J.
+ * @description: AnnotationListServiceImpl
+ * @date: 2023-11-06 13:58
+ */
+@Slf4j
+@Service
+public class AnnotationListServiceImpl extends ServiceImpl<AnnotationListMapper, AnnotationList> implements AnnotationListService {
+    @Autowired
+    private AlgKgClient algKgClient;
+
+    @Override
+    public PageInfo getAnnotationLists(AnnotationListParam annotationListParam) {
+        List<AnnotationList> annotationLists = new ArrayList<>();
+        annotationLists = baseMapper.selectAnnotationList(annotationListParam);
+        // 获取txt文本内容为空,向算法请求txt文本内容并更新。
+        if (!CollectionUtils.isEmpty(annotationLists)) {
+            // 过滤出textContent为空的数据。
+            toAlgTxt(annotationLists);
+            annotationLists = baseMapper.selectAnnotationList(annotationListParam);
+        }
+        PageHelper.startPage(annotationListParam.getPageNum(), annotationListParam.getPageSize());
+        PageInfo page = new PageInfo(annotationLists);
+        return page;
+    }
+
+    @Override
+    public Boolean delAnnotationLists(List<String> ids) {
+        int delRes = baseMapper.deleteBatchIds(ids);
+        return delRes > 0 ? true : false;
+    }
+
+    @Override
+    public Boolean importAnnotationDataset(ImportAnnotationDataset importAnnotationDataset) {
+        List<Integer> saveResLists = new ArrayList<>();
+        List<ImportDataset> importDatasets = importAnnotationDataset.getImportDatasets();
+        List<AnnotationList> annotationLists = new ArrayList<>();
+        AnnotationList annotationList;
+        for (ImportDataset importDataset : importDatasets) {
+            annotationList = new AnnotationList();
+            BeanUtils.copyProperties(importDataset, annotationList);
+            annotationList.setKgId(importAnnotationDataset.getKgId());
+            // 如果是知识库中的数据集,则默认parseStatus=1 解析完成,调用算法获取txt内容。
+            if (1 == importAnnotationDataset.getImportType()) {
+                annotationList.setParseStatus(1);
+                annotationList.setAnnotationStatus(0);
+                List<AnnotationList> annotations = baseMapper.selectList(new QueryWrapper<AnnotationList>().lambda().eq(AnnotationList::getKgId, importAnnotationDataset.getKgId())
+                        .eq(AnnotationList::getFileId, importDataset.getFileId()));
+                if (!CollectionUtils.isEmpty(annotations)){
+                    annotationList.setId(annotations.get(0).getId());
+                    int upRes = baseMapper.updateById(annotationList);
+                    saveResLists.add(upRes);
+                }else {
+                    int saveRes = baseMapper.insert(annotationList);
+                    saveResLists.add(saveRes);
+                }
+                annotationLists.add(annotationList);
+            }
+        }
+        // 获取算法txt文本内容.
+        toAlgTxt(annotationLists);
+        // 返回数据。
+        log.info("saveResLists:{}",JSON.toJSONString(saveResLists));
+        if (saveResLists.contains(0)) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    @Override
+    public Boolean importLocalAnnotationDataset(String kgId,MultipartFile file) {
+        // todo 文件重复上传。知识库文档重复上传。
+        try {
+            String s = DigestUtils.md5Hex(file.getBytes());
+            log.info("file to MD5:{}",s);
+        }catch (Exception ex){
+
+        }
+        SnowflakeIdWorkerUtils idWorker = new SnowflakeIdWorkerUtils(0, 0);
+        AnnotationList annotationList = new AnnotationList();
+        annotationList.setFileId(String.valueOf(idWorker.nextId()));
+        annotationList.setKgId(kgId);
+        annotationList.setOriginalName(file.getOriginalFilename());
+        annotationList.setAnnotationStatus(0);
+        annotationList.setParseStatus(0);
+        Map<String, Object> algMap = new HashMap<>();
+        algMap.put("file",file);
+        algMap.put("fileId",annotationList.getFileId());
+        String algTxtByFile = algKgClient.getAlgTxtByFile(algMap);
+        log.info("算法algTxtByFile:{}",JSON.toJSONString(algTxtByFile));
+        List<AnnotationList> annotationLists = new ArrayList<>();
+        annotationLists.add(annotationList);
+        try {
+            dealAlgToTxtRes(algTxtByFile,annotationLists,false);
+            return true;
+        }catch (Exception ex){
+            log.info("算法本地文件转txt异常 ex:{}",ex);
+        }
+        return false;
+    }
+
+    /**
+     * 调用算法实时获取txt文本内容。
+     *
+     * @param annotationLists
+     */
+    public void toAlgTxt(List<AnnotationList> annotationLists) {
+        List<AnnotationList> hasNullTexts = annotationLists.stream().filter(wmy -> null == wmy.getTextContent()).collect(Collectors.toList());
+        log.info("hasNullTexts:{}", hasNullTexts.size());
+        List<String> fileIds = hasNullTexts.stream().map(wmy -> wmy.getFileId()).collect(Collectors.toList());
+        // 调用算法获取txt文本内容。
+        Map<String, Object> algMap = new HashMap<>();
+        algMap.put("fileIds", fileIds);
+        log.info("algMap:{}", JSON.toJSONString(algMap));
+        String algTxtTmp = algKgClient.getAlgTxt(JSON.toJSONString(algMap));
+        dealAlgToTxtRes(algTxtTmp, hasNullTexts,true);
+        log.info("实时调用算法获取txt文本内容结束");
+    }
+
+    public void dealAlgToTxtRes(String algTxtTmp, List<AnnotationList> hasNullTexts,Boolean upFlag) {
+        if (null != algTxtTmp && StringUtils.isNotEmpty(algTxtTmp) && CommonUtils.isJsonArray(algTxtTmp)) {
+            // 解析算法返回数据。
+            try {
+                List<ConvertAlgRes> convertAlgRes = JSONArray.parseArray(algTxtTmp, ConvertAlgRes.class);
+                if (!CollectionUtils.isEmpty(convertAlgRes)) {
+                    for (ConvertAlgRes algRes : convertAlgRes) {
+                        if (null != algRes.getErrorCode() && "0".equals(algRes.getErrorCode())) {
+                            // 调用算法接口成功,并且解析txt文件成功,将文本内容更新至sysFile的textContent字段中。
+                            for (AnnotationList hasNullText : hasNullTexts) {
+                                if (algRes.getFileId().equals(hasNullText.getFileId())) {
+                                    hasNullText.setTextContent(algRes.getText());
+                                    if (upFlag){
+                                        // true 更新textContent.
+                                        int updateText = baseMapper.updateById(hasNullText);
+                                        log.info("更新文本内容结果updateText:{}", updateText);
+                                    }else {
+                                        // false 新增textContent
+                                        int saveRes = baseMapper.insert(hasNullText);
+                                        log.info("新增文本内容结果updateText:{}", saveRes);
+                                    }
+                                }
+                            }
+                        } else {
+                            if (null != algRes.getErrorCode() && "-1".equals(algRes.getErrorCode()) && false == upFlag){
+                                for (AnnotationList hasNullText : hasNullTexts) {
+                                    hasNullText.setParseStatus(-1);
+                                    int saveRes = baseMapper.insert(hasNullText);
+                                    log.info("解析出错 新增文本内容结果updateText:{}", saveRes);
+                                }
+                            }
+                            log.info("获取算法解析txt文本内容返回结果 TXT未解析成功:{}", JSON.toJSONString(algRes));
+                        }
+                    }
+                } else {
+                    log.info("获取算法解析txt文本内容返回结果 返回数据为NULL ex convertAlgRes:{}", JSON.toJSONString(convertAlgRes));
+                }
+            } catch (Exception ex) {
+                log.info("获取算法解析txt文本内容返回结果 返回数据异常 NOT JSONArray ex:{}", JSON.toJSONString(algTxtTmp));
+            }
+        } else {
+            log.info("获取算法解析txt文本内容返回结果接口异常 ex convertToTxtResTmp:{}", algTxtTmp);
+        }
+    }
+
+    public void dealAlgToTxtResByLocal(String algTxtTmp, AnnotationList annotationList) {
+        if (null != algTxtTmp && StringUtils.isNotEmpty(algTxtTmp) && CommonUtils.isJsonArray(algTxtTmp)) {
+            // 解析算法返回数据。
+            try {
+                List<ConvertAlgRes> convertAlgRes = JSONArray.parseArray(algTxtTmp, ConvertAlgRes.class);
+                if (!CollectionUtils.isEmpty(convertAlgRes)) {
+                    for (ConvertAlgRes algRes : convertAlgRes) {
+                        if (null != algRes.getErrorCode() && "0".equals(algRes.getErrorCode())) {
+                            // 调用算法接口成功,并且解析txt文件成功,将文本内容更新至sysFile的textContent字段中。
+
+                            // for (AnnotationList hasNullText : hasNullTexts) {
+                            //     if (algRes.getFileId().equals(hasNullText.getFileId())) {
+                            //         hasNullText.setTextContent(algRes.getText());
+                            //         int updateText = baseMapper.updateById(hasNullText);
+                            //         log.info("更新文本内容结果updateText:{}", updateText);
+                            //     }
+                            // }
+                        } else {
+                            log.info("获取算法解析txt文本内容返回结果 TXT未解析成功:{}", JSON.toJSONString(algRes));
+                        }
+                    }
+                } else {
+                    log.info("获取算法解析txt文本内容返回结果 返回数据为NULL ex convertAlgRes:{}", JSON.toJSONString(convertAlgRes));
+                }
+            } catch (Exception ex) {
+                log.info("获取算法解析txt文本内容返回结果 返回数据异常 NOT JSONArray ex:{}", JSON.toJSONString(algTxtTmp));
+            }
+        } else {
+            log.info("获取算法解析txt文本内容返回结果接口异常 ex convertToTxtResTmp:{}", algTxtTmp);
+        }
+    }
+}

+ 52 - 23
src/main/java/com/pavis/backend/slim/project/system/service/impl/SysFileServiceImpl.java

@@ -24,6 +24,7 @@ import com.pavis.backend.slim.project.system.service.SysFileService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StreamUtils;
@@ -314,40 +315,68 @@ public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> impl
                 algMap.put("files", convertDocToTxts);
                 // 调用算法,获取文档转换为txt的文本内容。
                 String convertToTxtResTmp = algKgClient.convertToTxt(JSON.toJSONString(algMap));
-                if (null != convertToTxtResTmp && StringUtils.isNotEmpty(convertToTxtResTmp) && CommonUtils.isJsonArray(convertToTxtResTmp)) {
-                    // 解析算法返回数据。
-                    try {
-                        List<ConvertAlgRes> convertAlgRes = JSONArray.parseArray(convertToTxtResTmp, ConvertAlgRes.class);
-                        if (!CollectionUtils.isEmpty(convertAlgRes)) {
-                            for (ConvertAlgRes algRes : convertAlgRes) {
-                                if (null != algRes.getErrorCode() && "0".equals(algRes.getErrorCode())) {
-                                    // 调用算法接口成功,并且解析txt文件成功,将文本内容更新至sysFile的textContent字段中。
-                                    SysFile sysFile = baseMapper.selectById(algRes.getFileId());
-                                    if (null != sysFile) {
-                                        // 更新文本内容。
-                                        sysFile.setTextContent(algRes.getText());
-                                        int updateText = baseMapper.updateById(sysFile);
-                                        log.info("更新文本内容结果updateText:{}", updateText);
-                                    }
-                                } else {
-                                    log.info("算法文档转换txt接口 TXT未解析成功:{}", JSON.toJSONString(algRes));
-                                }
+                dealAlgTxtRes(convertToTxtResTmp);
+            }
+        } else {
+            log.info("未检索到相关的sysFile。");
+        }
+    }
+
+    @Override
+    public void dealAlgTxtRes(String convertToTxtResTmp) {
+        if (null != convertToTxtResTmp && StringUtils.isNotEmpty(convertToTxtResTmp) && CommonUtils.isJsonArray(convertToTxtResTmp)) {
+            // 解析算法返回数据。
+            try {
+                List<ConvertAlgRes> convertAlgRes = JSONArray.parseArray(convertToTxtResTmp, ConvertAlgRes.class);
+                if (!CollectionUtils.isEmpty(convertAlgRes)) {
+                    for (ConvertAlgRes algRes : convertAlgRes) {
+                        if (null != algRes.getErrorCode() && "0".equals(algRes.getErrorCode())) {
+                            // 调用算法接口成功,并且解析txt文件成功,将文本内容更新至sysFile的textContent字段中。
+                            SysFile sysFile = baseMapper.selectById(algRes.getFileId());
+                            if (null != sysFile) {
+                                // 更新文本内容。
+                                sysFile.setTextContent(algRes.getText());
+                                int updateText = baseMapper.updateById(sysFile);
+                                log.info("更新文本内容结果updateText:{}", updateText);
                             }
                         } else {
-                            log.info("算法文档转换txt接口 返回数据为NULL ex convertAlgRes:{}", JSON.toJSONString(convertAlgRes));
+                            log.info("算法文档转换txt接口 TXT未解析成功:{}", JSON.toJSONString(algRes));
                         }
-                    } catch (Exception ex) {
-                        log.info("算法文档转换txt接口 返回数据异常 NOT JSONArray ex:{}", JSON.toJSONString(convertToTxtResTmp));
                     }
                 } else {
-                    log.info("算法文档转换txt接口异常 ex convertToTxtResTmp:{}", convertToTxtResTmp);
+                    log.info("算法文档转换txt接口 返回数据为NULL ex convertAlgRes:{}", JSON.toJSONString(convertAlgRes));
                 }
+            } catch (Exception ex) {
+                log.info("算法文档转换txt接口 返回数据异常 NOT JSONArray ex:{}", JSON.toJSONString(convertToTxtResTmp));
             }
         } else {
-            log.info("未检索到相关的sysFile。");
+            log.info("算法文档转换txt接口异常 ex convertToTxtResTmp:{}", convertToTxtResTmp);
         }
     }
 
+    @Async
+    @Override
+    public void convertfileToTxtByAlg(SysFile sysFile) {
+        List<ConvertDocToTxt> convertDocToTxts = new ArrayList<>();
+        // 三个条件均不为空时,才调用算法获取文档转换成txt结果。
+        if (null != sysFile && null != sysFile.getObjectKey() && null != sysFile.getIdentifier()) {
+            convertDocToTxts.add(ConvertDocToTxt.builder().fileId(sysFile.getFileId()).objectKey(sysFile.getObjectKey()).identifier(sysFile.getIdentifier()).build());
+        }
+        if (!CollectionUtils.isEmpty(convertDocToTxts)) {
+            Map<String, Object> algMap = new HashMap<>();
+            algMap.put("files", convertDocToTxts);
+            // 调用算法,获取文档转换为txt的文本内容。
+            try {
+                String convertToTxtResTmp = algKgClient.convertToTxt(JSON.toJSONString(algMap));
+                log.info("调用算法获取txt文本内容返回结果convertToTxtResTmp:{}",convertToTxtResTmp);
+            }catch (Exception ex){
+                log.info("调用算法获取txt文本内容返回结果convertToTxtResTmp ex:{}",ex);
+            }
+        }
+    }
+
+
+
     /**
      * 用户编辑的文件上传至minio中。
      *

+ 10 - 2
src/main/java/com/pavis/backend/slim/project/system/service/impl/SysKbFileServiceImpl.java

@@ -1,11 +1,11 @@
 package com.pavis.backend.slim.project.system.service.impl;
 
 import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.pavis.backend.slim.common.constant.Hodgepodge;
 import com.pavis.backend.slim.common.exception.ServiceException;
-import com.pavis.backend.slim.common.utils.FileUtils;
 import com.pavis.backend.slim.common.utils.SecurityUtils;
 import com.pavis.backend.slim.project.system.domain.SysFile;
 import com.pavis.backend.slim.project.system.domain.SysKbFile;
@@ -13,7 +13,7 @@ import com.pavis.backend.slim.project.system.mapper.SysFileMapper;
 import com.pavis.backend.slim.project.system.mapper.SysKbFileMapper;
 import com.pavis.backend.slim.project.system.service.SysFileService;
 import com.pavis.backend.slim.project.system.service.SysKbFileService;
-import org.apache.catalina.security.SecurityUtil;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
@@ -25,6 +25,7 @@ import java.util.List;
  * @create 2023-05-09 11:15
  */
 @Service
+@Slf4j
 public class SysKbFileServiceImpl extends ServiceImpl<SysKbFileMapper, SysKbFile> implements SysKbFileService {
 
     @Autowired
@@ -48,6 +49,12 @@ public class SysKbFileServiceImpl extends ServiceImpl<SysKbFileMapper, SysKbFile
         kbFile.setCreateBy(SecurityUtils.getUsername());
         kbFile.setCreateTime(DateUtil.date());
         baseMapper.insert(kbFile);
+        log.info("知识库文档上传接口sysFile:{}", JSON.toJSONString(sysFile));
+        log.info("知识库文档上传接口kbFile:{}", JSON.toJSONString(kbFile));
+        // todo 为知识库添加文档时,需要调用算法去做文档转换txt。无需关注算法返回。
+        log.info("开始调用算法的【文档转txt】接口");
+        fileService.convertfileToTxtByAlg(sysFile);
+        log.info("结束调用算法的【文档转txt】接口");
         return sysFile;
     }
 
@@ -98,4 +105,5 @@ public class SysKbFileServiceImpl extends ServiceImpl<SysKbFileMapper, SysKbFile
         }
         return bool;
     }
+
 }

+ 2 - 1
src/main/resources/application-ghj.yml

@@ -82,7 +82,8 @@ algorithm:
     url: http://192.168.1.150:8900/data_access
     # 文档转换为txt文本内容接口。
   convert:
-    url: http://192.168.1.127:8068
+#    url: http://192.168.1.127:8068
+    url: http://192.168.1.150:12000
     # 通用图谱调用算法接口。即未创建实体和关系。
   universalGraph:
     url: http://192.168.1.127:8068

+ 41 - 0
src/main/resources/mapper/system/AnnotationListMapper.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pavis.backend.slim.project.system.mapper.AnnotationListMapper">
+
+    <resultMap type="com.pavis.backend.slim.project.system.domain.AnnotationList" id="AnnotationListResult">
+        <id property="id" column="id"/>
+        <id property="kgId" column="kg_id"/>
+        <id property="fileId" column="file_id"/>
+        <result property="originalName" column="original_name"/>
+        <result property="parseStatus" column="parse_status"/>
+        <result property="textContent" column="text_content"/>
+        <result property="annotationStatus" column="annotation_status"/>
+        <result property="createBy" column="create_by"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateBy" column="update_by"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="remark" column="remark"/>
+        <result property="attribute1" column="attribute1"/>
+        <result property="attribute2" column="attribute2"/>
+    </resultMap>
+
+    <select id="selectAnnotationList" resultType="com.pavis.backend.slim.project.system.domain.AnnotationList"
+            parameterType="com.pavis.backend.slim.project.system.domain.annotation.AnnotationListParam">
+        SELECT
+        *
+        FROM
+        annotation_list al
+        WHERE 1=1
+        <if test="kgId!=null and kgId!=''">
+            and al.kg_id = #{kgId}
+        </if>
+        <if test="originalName!=null and originalName!=''">
+            and al.original_name like concat ('%',#{originalName},'%')
+        </if>
+        order by al.create_time desc
+    </select>
+
+
+</mapper>