From 2879916e97ab0dffda7450e6cab4109473d2e614 Mon Sep 17 00:00:00 2001
From: xueqingkun <xueqingkun@126.com>
Date: Wed, 4 Sep 2024 17:09:12 +0800
Subject: [PATCH] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0=E8=AF=81=E6=8D=AEocr?=
 =?UTF-8?q?=E8=AF=86=E5=88=AB=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../constant/EvidencePropertyName.java        |  51 ++++++
 .../controller/OCREvidenceController.java     |  36 ++++
 .../police/domain/EvidenceFile.java           |   7 +
 ...roperty.java => FileEvidenceProperty.java} |  22 ++-
 .../police/dto/EvidenceFileOCRDTO.java        |  60 +++++++
 .../police/dto/OCREvidencePropertyDTO.java    |  24 +++
 .../police/dto/RetrieveReqDTO.java            |  20 +++
 .../police/dto/RetrieveResDTO.java            |  17 ++
 .../police/mapper/EvidencePropertyMapper.java |  18 --
 .../mapper/FileEvidencePropertyMapper.java    |  22 +++
 .../service/EvidencePropertyService.java      |  13 --
 .../service/FileEvidencePropertyService.java  |  19 ++
 .../police/service/FileOcrProcessService.java |   9 +-
 .../police/service/OCREvidenceService.java    |  29 +++
 .../police/service/OCRService.java            |  15 ++
 .../impl/EvidencePropertyServiceImpl.java     |  22 ---
 .../impl/FileEvidencePropertyServiceImpl.java |  40 +++++
 .../impl/FileOcrProcessServiceImpl.java       |  33 ++--
 .../service/impl/OCREvidenceServiceImpl.java  | 170 ++++++++++++++++++
 .../service/impl/OCRRecordServiceImpl.java    |   8 +-
 ...per.xml => FileEvidencePropertyMapper.xml} |  25 ++-
 .../demo/FuHsiApplicationTests.java           |  13 ++
 22 files changed, 592 insertions(+), 81 deletions(-)
 create mode 100644 src/main/java/com/supervision/constant/EvidencePropertyName.java
 create mode 100644 src/main/java/com/supervision/police/controller/OCREvidenceController.java
 rename src/main/java/com/supervision/police/domain/{EvidenceProperty.java => FileEvidenceProperty.java} (64%)
 create mode 100644 src/main/java/com/supervision/police/dto/EvidenceFileOCRDTO.java
 create mode 100644 src/main/java/com/supervision/police/dto/OCREvidencePropertyDTO.java
 create mode 100644 src/main/java/com/supervision/police/dto/RetrieveReqDTO.java
 create mode 100644 src/main/java/com/supervision/police/dto/RetrieveResDTO.java
 delete mode 100644 src/main/java/com/supervision/police/mapper/EvidencePropertyMapper.java
 create mode 100644 src/main/java/com/supervision/police/mapper/FileEvidencePropertyMapper.java
 delete mode 100644 src/main/java/com/supervision/police/service/EvidencePropertyService.java
 create mode 100644 src/main/java/com/supervision/police/service/FileEvidencePropertyService.java
 create mode 100644 src/main/java/com/supervision/police/service/OCREvidenceService.java
 delete mode 100644 src/main/java/com/supervision/police/service/impl/EvidencePropertyServiceImpl.java
 create mode 100644 src/main/java/com/supervision/police/service/impl/FileEvidencePropertyServiceImpl.java
 create mode 100644 src/main/java/com/supervision/police/service/impl/OCREvidenceServiceImpl.java
 rename src/main/resources/mapper/{EvidencePropertyMapper.xml => FileEvidencePropertyMapper.xml} (51%)

diff --git a/src/main/java/com/supervision/constant/EvidencePropertyName.java b/src/main/java/com/supervision/constant/EvidencePropertyName.java
new file mode 100644
index 0000000..b524825
--- /dev/null
+++ b/src/main/java/com/supervision/constant/EvidencePropertyName.java
@@ -0,0 +1,51 @@
+package com.supervision.constant;
+
+import cn.hutool.core.collection.CollUtil;
+import lombok.Getter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Getter
+public enum EvidencePropertyName {
+
+    TITLE("title", "标题", "String");
+
+    private final String name;
+
+    private final String description;
+
+    private final String type;
+
+    EvidencePropertyName(String name, String description, String type) {
+        this.name = name;
+        this.description = description;
+        this.type = type;
+    }
+
+    public static List<EvidencePropertyName> getByNames(Map<String,String> propertyMap){
+        ArrayList<EvidencePropertyName> evidencePropertyNames = new ArrayList<>();
+        if (CollUtil.isEmpty(propertyMap)){
+            return evidencePropertyNames;
+        }
+
+        for (String key : propertyMap.keySet()) {
+            EvidencePropertyName evidencePropertyName = getByName(key);
+            if (evidencePropertyName != null){
+                evidencePropertyNames.add(evidencePropertyName);
+            }
+        }
+
+        return evidencePropertyNames;
+    }
+
+    public static EvidencePropertyName getByName(String name){
+        for (EvidencePropertyName value : values()) {
+            if (value.getName().equals(name)){
+                return value;
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/com/supervision/police/controller/OCREvidenceController.java b/src/main/java/com/supervision/police/controller/OCREvidenceController.java
new file mode 100644
index 0000000..2267f63
--- /dev/null
+++ b/src/main/java/com/supervision/police/controller/OCREvidenceController.java
@@ -0,0 +1,36 @@
+package com.supervision.police.controller;
+
+import com.supervision.common.domain.R;
+import com.supervision.police.dto.EvidenceFileOCRDTO;
+import com.supervision.police.service.OCREvidenceService;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * ocr证据接口
+ */
+@RestController
+@Slf4j
+@RequestMapping("/ocr/evidence")
+@ApiOperation(value = "OCR笔录接口")
+@RequiredArgsConstructor
+public class OCREvidenceController {
+
+    private final OCREvidenceService ocrEvidenceService;
+    @GetMapping("/submitOrcTask")
+    public R<Boolean> submitOrcTask(@RequestParam("fileId") String fileId) {
+        Boolean success =  ocrEvidenceService.submitOrcTask(fileId);
+        return R.ok(success);
+    }
+
+
+    @PostMapping("/preview")
+    public R<List<EvidenceFileOCRDTO>> preview(@RequestBody List<String> fileIdList) {
+        List<EvidenceFileOCRDTO> evidenceFileOCRDTOList =  ocrEvidenceService.previewEvidence(fileIdList);
+        return R.ok(evidenceFileOCRDTOList);
+    }
+}
diff --git a/src/main/java/com/supervision/police/domain/EvidenceFile.java b/src/main/java/com/supervision/police/domain/EvidenceFile.java
index f7f37ea..fa855ae 100644
--- a/src/main/java/com/supervision/police/domain/EvidenceFile.java
+++ b/src/main/java/com/supervision/police/domain/EvidenceFile.java
@@ -61,4 +61,11 @@ public class EvidenceFile implements Serializable {
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
 
+    public EvidenceFile() {
+    }
+
+    public EvidenceFile(String evidenceId, String fileId) {
+        this.evidenceId = evidenceId;
+        this.fileId = fileId;
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/supervision/police/domain/EvidenceProperty.java b/src/main/java/com/supervision/police/domain/FileEvidenceProperty.java
similarity index 64%
rename from src/main/java/com/supervision/police/domain/EvidenceProperty.java
rename to src/main/java/com/supervision/police/domain/FileEvidenceProperty.java
index be985ff..84c5d9f 100644
--- a/src/main/java/com/supervision/police/domain/EvidenceProperty.java
+++ b/src/main/java/com/supervision/police/domain/FileEvidenceProperty.java
@@ -1,6 +1,5 @@
 package com.supervision.police.domain;
 
-import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -10,11 +9,11 @@ import lombok.Data;
 
 /**
  * 
- * @TableName evidence_property
+ * @TableName file_evidence_property
  */
-@TableName(value ="evidence_property")
+@TableName(value ="file_evidence_property")
 @Data
-public class EvidenceProperty implements Serializable {
+public class FileEvidenceProperty implements Serializable {
     /**
      * 主键
      */
@@ -26,6 +25,11 @@ public class EvidenceProperty implements Serializable {
      */
     private String evidenceId;
 
+    /**
+     * 文件id
+     */
+    private String fileId;
+
     /**
      * 属性名
      */
@@ -58,4 +62,14 @@ public class EvidenceProperty implements Serializable {
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    public FileEvidenceProperty() {
+    }
+
+    public FileEvidenceProperty(String evidenceId, String fileId, String propertyName, String propertyValue) {
+        this.evidenceId = evidenceId;
+        this.fileId = fileId;
+        this.propertyName = propertyName;
+        this.propertyValue = propertyValue;
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/supervision/police/dto/EvidenceFileOCRDTO.java b/src/main/java/com/supervision/police/dto/EvidenceFileOCRDTO.java
new file mode 100644
index 0000000..40b6b52
--- /dev/null
+++ b/src/main/java/com/supervision/police/dto/EvidenceFileOCRDTO.java
@@ -0,0 +1,60 @@
+package com.supervision.police.dto;
+
+import cn.hutool.core.collection.CollUtil;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class EvidenceFileOCRDTO {
+
+    @Schema(description = "案件证据id")
+    private String evidenceId;
+
+    @Schema(description = "案件id")
+    private String caseId;
+
+    @Schema(description = "案件证据名称")
+    private String evidenceName;
+
+    @Schema(description = "案件证据类型")
+    private String evidenceType;
+
+    @Schema(description = "文件id")
+    private String fileId;
+
+    @Schema(description = "文件预览图id")
+    private String drawImgId;
+
+    @Schema(description = "文件识别内容")
+    private String ocrText;
+
+    @Schema(description = "文件属性")
+    private Map<String,String> property= new HashMap<>();
+
+    public EvidenceFileOCRDTO() {
+    }
+
+    public EvidenceFileOCRDTO(List<OCREvidencePropertyDTO> properties) {
+        if (CollUtil.isEmpty(properties)){
+            return;
+        }
+        OCREvidencePropertyDTO first = CollUtil.getFirst(properties);
+        this.evidenceId = first.getEvidenceId();
+        this.fileId = first.getFileId();
+        this.drawImgId = first.getDrawImgId();
+        properties.forEach(propertyDTO ->
+                this.property.put(propertyDTO.getPropertyName(),propertyDTO.getPropertyValue()));
+    }
+
+    public CaseEvidenceDTO toCaseEvidenceDTO(){
+        CaseEvidenceDTO caseEvidenceDTO = new CaseEvidenceDTO();
+        caseEvidenceDTO.setCaseId(this.caseId);
+        caseEvidenceDTO.setEvidenceName(this.evidenceName);
+        caseEvidenceDTO.setEvidenceType(this.evidenceType);
+        caseEvidenceDTO.setId(this.evidenceId);
+        return caseEvidenceDTO;
+    }
+}
diff --git a/src/main/java/com/supervision/police/dto/OCREvidencePropertyDTO.java b/src/main/java/com/supervision/police/dto/OCREvidencePropertyDTO.java
new file mode 100644
index 0000000..0157caa
--- /dev/null
+++ b/src/main/java/com/supervision/police/dto/OCREvidencePropertyDTO.java
@@ -0,0 +1,24 @@
+package com.supervision.police.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class OCREvidencePropertyDTO {
+
+    @Schema(description = "案件证据id")
+    private String evidenceId;
+
+    @Schema(description = "文件id")
+    private String fileId;
+
+    @Schema(description = "属性名称")
+    private String propertyName;
+
+    @Schema(description = "属性值")
+    private String propertyValue;
+
+    @Schema(description = "预览图id")
+    private String drawImgId;
+
+}
diff --git a/src/main/java/com/supervision/police/dto/RetrieveReqDTO.java b/src/main/java/com/supervision/police/dto/RetrieveReqDTO.java
new file mode 100644
index 0000000..59c0ada
--- /dev/null
+++ b/src/main/java/com/supervision/police/dto/RetrieveReqDTO.java
@@ -0,0 +1,20 @@
+package com.supervision.police.dto;
+
+import lombok.Data;
+
+@Data
+public class RetrieveReqDTO {
+
+    /**
+     * 要从中提取标题的文本
+     */
+    private String text;
+
+    public RetrieveReqDTO() {
+    }
+
+    public RetrieveReqDTO(String text) {
+        this.text = text;
+
+    }
+}
diff --git a/src/main/java/com/supervision/police/dto/RetrieveResDTO.java b/src/main/java/com/supervision/police/dto/RetrieveResDTO.java
new file mode 100644
index 0000000..30f4ca2
--- /dev/null
+++ b/src/main/java/com/supervision/police/dto/RetrieveResDTO.java
@@ -0,0 +1,17 @@
+package com.supervision.police.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class RetrieveResDTO {
+
+    @Schema(description = "标题")
+    private String title;
+
+    @Schema(description = "状态码 0:成功 2:失败")
+    private int status;
+
+    @Schema(description = "错误信息")
+    private String error_msg;
+}
diff --git a/src/main/java/com/supervision/police/mapper/EvidencePropertyMapper.java b/src/main/java/com/supervision/police/mapper/EvidencePropertyMapper.java
deleted file mode 100644
index c4254df..0000000
--- a/src/main/java/com/supervision/police/mapper/EvidencePropertyMapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.supervision.police.mapper;
-
-import com.supervision.police.domain.EvidenceProperty;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
-* @author Administrator
-* @description 针对表【evidence_property】的数据库操作Mapper
-* @createDate 2024-09-04 11:20:37
-* @Entity com.supervision.police.domain.EvidenceProperty
-*/
-public interface EvidencePropertyMapper extends BaseMapper<EvidenceProperty> {
-
-}
-
-
-
-
diff --git a/src/main/java/com/supervision/police/mapper/FileEvidencePropertyMapper.java b/src/main/java/com/supervision/police/mapper/FileEvidencePropertyMapper.java
new file mode 100644
index 0000000..c4094fb
--- /dev/null
+++ b/src/main/java/com/supervision/police/mapper/FileEvidencePropertyMapper.java
@@ -0,0 +1,22 @@
+package com.supervision.police.mapper;
+
+import com.supervision.police.domain.FileEvidenceProperty;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.supervision.police.dto.OCREvidencePropertyDTO;
+
+import java.util.List;
+
+/**
+* @author Administrator
+* @description 针对表【file_evidence_property】的数据库操作Mapper
+* @createDate 2024-09-04 15:10:13
+* @Entity com.supervision.police.domain.EvidenceProperty
+*/
+public interface FileEvidencePropertyMapper extends BaseMapper<FileEvidenceProperty> {
+
+    List<OCREvidencePropertyDTO> listPrewByFileIdList(List<String> fileIdList);
+}
+
+
+
+
diff --git a/src/main/java/com/supervision/police/service/EvidencePropertyService.java b/src/main/java/com/supervision/police/service/EvidencePropertyService.java
deleted file mode 100644
index 3f4b905..0000000
--- a/src/main/java/com/supervision/police/service/EvidencePropertyService.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.supervision.police.service;
-
-import com.supervision.police.domain.EvidenceProperty;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
-* @author Administrator
-* @description 针对表【evidence_property】的数据库操作Service
-* @createDate 2024-09-04 11:20:37
-*/
-public interface EvidencePropertyService extends IService<EvidenceProperty> {
-
-}
diff --git a/src/main/java/com/supervision/police/service/FileEvidencePropertyService.java b/src/main/java/com/supervision/police/service/FileEvidencePropertyService.java
new file mode 100644
index 0000000..2e4cabf
--- /dev/null
+++ b/src/main/java/com/supervision/police/service/FileEvidencePropertyService.java
@@ -0,0 +1,19 @@
+package com.supervision.police.service;
+
+import com.supervision.police.domain.FileEvidenceProperty;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.supervision.police.dto.OCREvidencePropertyDTO;
+
+import java.util.List;
+
+/**
+* @author Administrator
+* @description 针对表【file_evidence_property】的数据库操作Service
+* @createDate 2024-09-04 15:10:13
+*/
+public interface FileEvidencePropertyService extends IService<FileEvidenceProperty> {
+
+    List<OCREvidencePropertyDTO> listPrewByFileIdList(List<String> fileIdList);
+
+    void removeByEvidenceAndFileId(String evidenceId, String fileId);
+}
diff --git a/src/main/java/com/supervision/police/service/FileOcrProcessService.java b/src/main/java/com/supervision/police/service/FileOcrProcessService.java
index 6426b89..900450a 100644
--- a/src/main/java/com/supervision/police/service/FileOcrProcessService.java
+++ b/src/main/java/com/supervision/police/service/FileOcrProcessService.java
@@ -1,8 +1,8 @@
 package com.supervision.police.service;
 
+import com.supervision.listener.OCRTaskListener;
 import com.supervision.police.domain.FileOcrProcess;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.supervision.police.dto.OCRReqDTO;
 import com.supervision.police.dto.OCRResDTO;
 import com.supervision.police.dto.RecordFileDTO;
 
@@ -15,11 +15,16 @@ import java.util.List;
 */
 public interface FileOcrProcessService extends IService<FileOcrProcess> {
 
-    List<FileOcrProcess> submitOCR(List<String> fileIdList);
+    List<FileOcrProcess> asyncSubmitOCR(List<String> fileIdList);
+
+    List<FileOcrProcess> syncSubmitOCR(List<String> fileIdList);
 
 
     void doOCRTask(List<FileOcrProcess> fileOcrProcesses);
 
+    //异步调用
+    void asyncDoOCRTask(List<FileOcrProcess> fileOcrProcesses);
+
 
     void doAllOCRTask();
 
diff --git a/src/main/java/com/supervision/police/service/OCREvidenceService.java b/src/main/java/com/supervision/police/service/OCREvidenceService.java
new file mode 100644
index 0000000..ce62804
--- /dev/null
+++ b/src/main/java/com/supervision/police/service/OCREvidenceService.java
@@ -0,0 +1,29 @@
+package com.supervision.police.service;
+
+import com.supervision.police.domain.FileEvidenceProperty;
+import com.supervision.police.dto.EvidenceFileOCRDTO;
+
+import java.util.List;
+import java.util.Map;
+
+public interface OCREvidenceService {
+    Boolean submitOrcTask(String fileId);
+
+    List<FileEvidenceProperty> doOrcTask(String evidenceId,String fileId);
+
+    void asyncDoOrcTask(String evidenceId,String fileId);
+
+
+    /**
+     * 保存证据属性统一入口
+     * @param evidenceId 证据id
+     * @param fileId 文件id
+     * @param propertyMap 属性map
+     * @return
+     */
+    List<FileEvidenceProperty> saveEvidenceProperty(String evidenceId, String fileId, Map<String,String> propertyMap);
+
+    List<EvidenceFileOCRDTO> previewEvidence(List<String> fileIdList);
+
+    String saveEvidence(EvidenceFileOCRDTO evidenceFileOCRDTO);
+}
diff --git a/src/main/java/com/supervision/police/service/OCRService.java b/src/main/java/com/supervision/police/service/OCRService.java
index c308b76..5930f4e 100644
--- a/src/main/java/com/supervision/police/service/OCRService.java
+++ b/src/main/java/com/supervision/police/service/OCRService.java
@@ -2,6 +2,8 @@ package com.supervision.police.service;
 
 import com.supervision.police.dto.OCRReqDTO;
 import com.supervision.police.dto.OCRResDTO;
+import com.supervision.police.dto.RetrieveReqDTO;
+import com.supervision.police.dto.RetrieveResDTO;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.service.annotation.HttpExchange;
@@ -12,6 +14,19 @@ import java.util.List;
 @HttpExchange
 public interface OCRService {
 
+    /**
+     * ocr识别
+     * @param ocrReqDTO
+     * @return
+     */
     @PostExchange(url = "/ocr", contentType = MediaType.APPLICATION_JSON_VALUE)
     List<OCRResDTO> ocr(@RequestBody OCRReqDTO ocrReqDTO);
+
+    /**
+     * 提取文本属性
+     * @param retrieveReqDTO
+     * @return
+     */
+    @PostExchange(url = "/retrieve", contentType = MediaType.APPLICATION_JSON_VALUE)
+    RetrieveResDTO retrieve(@RequestBody RetrieveReqDTO retrieveReqDTO);
 }
diff --git a/src/main/java/com/supervision/police/service/impl/EvidencePropertyServiceImpl.java b/src/main/java/com/supervision/police/service/impl/EvidencePropertyServiceImpl.java
deleted file mode 100644
index 7259f58..0000000
--- a/src/main/java/com/supervision/police/service/impl/EvidencePropertyServiceImpl.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.supervision.police.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.supervision.police.domain.EvidenceProperty;
-import com.supervision.police.service.EvidencePropertyService;
-import com.supervision.police.mapper.EvidencePropertyMapper;
-import org.springframework.stereotype.Service;
-
-/**
-* @author Administrator
-* @description 针对表【evidence_property】的数据库操作Service实现
-* @createDate 2024-09-04 11:20:37
-*/
-@Service
-public class EvidencePropertyServiceImpl extends ServiceImpl<EvidencePropertyMapper, EvidenceProperty>
-    implements EvidencePropertyService{
-
-}
-
-
-
-
diff --git a/src/main/java/com/supervision/police/service/impl/FileEvidencePropertyServiceImpl.java b/src/main/java/com/supervision/police/service/impl/FileEvidencePropertyServiceImpl.java
new file mode 100644
index 0000000..e7eef66
--- /dev/null
+++ b/src/main/java/com/supervision/police/service/impl/FileEvidencePropertyServiceImpl.java
@@ -0,0 +1,40 @@
+package com.supervision.police.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.supervision.police.domain.FileEvidenceProperty;
+import com.supervision.police.dto.OCREvidencePropertyDTO;
+import com.supervision.police.service.FileEvidencePropertyService;
+import com.supervision.police.mapper.FileEvidencePropertyMapper;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+* @author Administrator
+* @description 针对表【file_evidence_property】的数据库操作Service实现
+* @createDate 2024-09-04 15:10:13
+*/
+@Service
+public class FileEvidencePropertyServiceImpl extends ServiceImpl<FileEvidencePropertyMapper, FileEvidenceProperty>
+    implements FileEvidencePropertyService {
+
+    @Override
+    public List<OCREvidencePropertyDTO> listPrewByFileIdList(List<String> fileIdList) {
+        return super.getBaseMapper().listPrewByFileIdList(fileIdList);
+    }
+
+    @Override
+    public void removeByEvidenceAndFileId(String evidenceId, String fileId) {
+        Assert.isFalse(StrUtil.isAllEmpty(evidenceId,fileId), "案件id和文件id不能全为空");
+
+        super.lambdaUpdate().eq(StrUtil.isNotEmpty(evidenceId),FileEvidenceProperty::getEvidenceId, evidenceId)
+            .eq(StrUtil.isNotEmpty(fileId),FileEvidenceProperty::getFileId, fileId).remove();
+    }
+}
+
+
+
+
diff --git a/src/main/java/com/supervision/police/service/impl/FileOcrProcessServiceImpl.java b/src/main/java/com/supervision/police/service/impl/FileOcrProcessServiceImpl.java
index 76df1fb..a9030f0 100644
--- a/src/main/java/com/supervision/police/service/impl/FileOcrProcessServiceImpl.java
+++ b/src/main/java/com/supervision/police/service/impl/FileOcrProcessServiceImpl.java
@@ -23,10 +23,8 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 /**
@@ -38,7 +36,7 @@ import java.util.stream.Collectors;
 @Service
 @RequiredArgsConstructor
 public class FileOcrProcessServiceImpl extends ServiceImpl<FileOcrProcessMapper, FileOcrProcess>
-    implements FileOcrProcessService{
+    implements FileOcrProcessService {
 
     @Value("${ocr.pool.max-size:20}")
     private Integer poolMaxSize;
@@ -51,8 +49,18 @@ public class FileOcrProcessServiceImpl extends ServiceImpl<FileOcrProcessMapper,
 
     @Override
     @Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
-    public List<FileOcrProcess> submitOCR(List<String> fileIdList) {
+    public List<FileOcrProcess> asyncSubmitOCR(List<String> fileIdList) {
 
+        return submitOCR(fileIdList, this::asyncDoOCRTask);
+    }
+
+    @Override
+    public List<FileOcrProcess> syncSubmitOCR(List<String> fileIdList) {
+        return submitOCR(fileIdList, this::doOCRTask);
+    }
+
+
+    private List<FileOcrProcess> submitOCR(List<String> fileIdList, Consumer<List<FileOcrProcess>> consumer){
         if (CollUtil.isEmpty(fileIdList)){
             log.info("submitOCR:fileIds为空。提交ocr任务...");
             return new ArrayList<>(1);
@@ -64,15 +72,13 @@ public class FileOcrProcessServiceImpl extends ServiceImpl<FileOcrProcessMapper,
             processList.add(fileOcrProcess);
         }
 
-        doOCRTask(processList);
+        consumer.accept(processList);
         return processList;
     }
 
-    @Async
     @Override
     public synchronized void doOCRTask(List<FileOcrProcess> fileOcrProcesses) {
 
-
         if (CollUtil.isEmpty(fileOcrProcesses)){
             log.info("asyncOcr:当前暂无识别的任务,结束...");
             return;
@@ -85,7 +91,6 @@ public class FileOcrProcessServiceImpl extends ServiceImpl<FileOcrProcessMapper,
             for (OCRReqDTO ocrReqDTO : ocrReqDTOS) {
                 log.info("ocr:开始识别文件:{}", JSONUtil.toJsonStr(ocrReqDTO));
                 this.updateOCrStatus(ocrReqDTO.getFile_ids(),0);
-
                 try {
                     List<OCRResDTO> ocrRes = ocrService.ocr(ocrReqDTO);
                     log.info("ocr:识别结果:{}", JSONUtil.toJsonStr(ocrRes));
@@ -106,6 +111,13 @@ public class FileOcrProcessServiceImpl extends ServiceImpl<FileOcrProcessMapper,
         }
     }
 
+    @Async
+    @Override
+    public void asyncDoOCRTask(List<FileOcrProcess> fileOcrProcesses) {
+
+        doOCRTask(fileOcrProcesses);
+    }
+
     @Override
     public void doAllOCRTask() {
         List<FileOcrProcess> allFileOcrProcesses = pageListByStatus(-1, 99999);
@@ -166,7 +178,6 @@ public class FileOcrProcessServiceImpl extends ServiceImpl<FileOcrProcessMapper,
                 .collect(Collectors.toList());
 
     }
-
 }
 
 
diff --git a/src/main/java/com/supervision/police/service/impl/OCREvidenceServiceImpl.java b/src/main/java/com/supervision/police/service/impl/OCREvidenceServiceImpl.java
new file mode 100644
index 0000000..9695be5
--- /dev/null
+++ b/src/main/java/com/supervision/police/service/impl/OCREvidenceServiceImpl.java
@@ -0,0 +1,170 @@
+package com.supervision.police.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import com.supervision.constant.EvidencePropertyName;
+import com.supervision.police.domain.EvidenceFile;
+import com.supervision.police.domain.FileEvidenceProperty;
+import com.supervision.police.domain.FileOcrProcess;
+import com.supervision.police.dto.*;
+import com.supervision.police.service.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class OCREvidenceServiceImpl implements OCREvidenceService {
+
+    private final FileOcrProcessService ocrProcessService;
+
+    private final OCRService ocrService;
+
+    private final FileEvidencePropertyService fileEvidencePropertyService;
+
+    private final EvidenceFileService evidenceFileService;
+
+    private final CaseEvidenceService caseEvidenceService;
+    @Override
+    public Boolean submitOrcTask(String fileId) {
+        Assert.notEmpty(fileId, "文件id不能为空");
+
+        asyncDoOrcTask(null, fileId);
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class,transactionManager = "dataSourceTransactionManager")
+    public List<FileEvidenceProperty> doOrcTask(String evidenceId,String fileId) {
+
+        List<FileEvidenceProperty> evidencePropertyList = new ArrayList<>();
+        // 识别文件信息
+        List<FileOcrProcess> fileOcrProcesses = ocrProcessService.syncSubmitOCR(CollUtil.newArrayList(fileId));
+
+        if (CollUtil.isEmpty(fileOcrProcesses)){
+            log.warn("subOrcTask:文件id:{} 识别失败", fileId);
+            return evidencePropertyList;
+        }
+
+        for (FileOcrProcess fileOcrProcess : fileOcrProcesses) {
+
+            // 调用提取属性接口
+            log.info("subOrcTask:文件id:{} 识别结果:{}", fileId, JSONUtil.toJsonStr(fileOcrProcess));
+            RetrieveResDTO retrieve = ocrService.retrieve(new RetrieveReqDTO(fileOcrProcess.getOcrText()));
+            log.info("subOrcTask:文件id:{} 识别结果:{}", fileId, JSONUtil.toJsonStr(retrieve));
+
+            if (Integer.valueOf(0).equals(retrieve.getStatus())){
+                // 保存属性信息
+                String title = retrieve.getTitle();
+                if (StrUtil.isNotEmpty(title)){
+
+                    evidencePropertyList.addAll(this.saveEvidenceProperty(evidenceId, fileId,
+                            Map.of(EvidencePropertyName.TITLE.getName(), retrieve.getTitle())));
+
+                    if (StrUtil.isNotEmpty(evidenceId)){
+                        evidenceFileService.save(new EvidenceFile(evidenceId,fileId));
+                    }
+
+                }
+            }
+        }
+
+        return evidencePropertyList;
+    }
+
+    @Async
+    @Override
+    public void asyncDoOrcTask(String evidenceId, String fileId) {
+        doOrcTask(evidenceId, fileId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class,transactionManager = "dataSourceTransactionManager")
+    public List<FileEvidenceProperty> saveEvidenceProperty(String evidenceId,String fileId ,Map<String, String> propertyMap) {
+
+        // 先清空数据
+        fileEvidencePropertyService.removeByEvidenceAndFileId(evidenceId,fileId);
+
+        List<FileEvidenceProperty> fileEvidence = toFileEvidence(evidenceId, fileId, propertyMap);
+        fileEvidencePropertyService.saveBatch(fileEvidence);
+
+        return fileEvidence;
+    }
+
+    @Override
+    public List<EvidenceFileOCRDTO> previewEvidence(List<String> fileIdList) {
+
+        if (CollUtil.isEmpty(fileIdList)){
+            return new ArrayList<>(1);
+        }
+        List<OCREvidencePropertyDTO> ocrEvidencePropertyDTOS = fileEvidencePropertyService.listPrewByFileIdList(fileIdList);
+
+        List<EvidenceFileOCRDTO> collect = ocrEvidencePropertyDTOS.stream()
+                .collect(Collectors.groupingBy(OCREvidencePropertyDTO::getFileId))
+                .values().stream()
+                .map(EvidenceFileOCRDTO::new)
+                .collect(Collectors.toList());
+
+        return sortByIdOrder(fileIdList, collect);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class,transactionManager = "dataSourceTransactionManager")
+    public String saveEvidence(EvidenceFileOCRDTO evidenceFileOCRDTO) {
+        Assert.notEmpty(evidenceFileOCRDTO.getFileId(), "文件id不能为空");
+        Assert.notEmpty(evidenceFileOCRDTO.getCaseId(), "案件id不能为空");
+        Assert.notEmpty(evidenceFileOCRDTO.getEvidenceName(), "案件证据名称不能为空");
+        Assert.notEmpty(evidenceFileOCRDTO.getEvidenceType(), "案件证据类型不能为空");
+
+        //保存证据信息
+        String evidenceId = caseEvidenceService.saveEvidence(evidenceFileOCRDTO.toCaseEvidenceDTO());
+
+        //保存证据文件关联信息
+        evidenceFileService.save(new EvidenceFile(evidenceId, evidenceFileOCRDTO.getFileId()));
+
+        // 保存证据属性
+        List<FileEvidenceProperty> evidencePropertyList = saveEvidenceProperty(evidenceFileOCRDTO.getEvidenceId(),
+                evidenceFileOCRDTO.getFileId(), evidenceFileOCRDTO.getProperty());
+
+        if (CollUtil.isEmpty(evidencePropertyList)){
+            return null;
+        }
+        return CollUtil.getFirst(evidencePropertyList).getEvidenceId();
+    }
+
+
+    private List<EvidenceFileOCRDTO> sortByIdOrder(List<String> fileIdList, List<EvidenceFileOCRDTO> evidenceFileOCRDTOS){
+
+        if (CollUtil.size(fileIdList) < 2 || CollUtil.size(evidenceFileOCRDTOS) < 2) {
+            return evidenceFileOCRDTOS;
+        }
+
+        Map<String, EvidenceFileOCRDTO> fileOCRDTOMap = evidenceFileOCRDTOS.stream()
+                .collect(Collectors.toMap(EvidenceFileOCRDTO::getFileId, recordFileDTO -> recordFileDTO, (k1, k2) -> k1));
+        return fileIdList.stream().map(fileOCRDTOMap::get).filter(Objects::nonNull).collect(Collectors.toList());
+    }
+
+    private List<FileEvidenceProperty> toFileEvidence(String evidenceId,String fileId ,Map<String, String> propertyMap){
+
+        if (StrUtil.isAllEmpty(evidenceId,fileId) || CollUtil.isEmpty(propertyMap)){
+            log.warn("saveEvidenceProperty:参数为空");
+            return new ArrayList<>(1);
+        }
+
+        return EvidencePropertyName.getByNames(propertyMap)
+                .stream().map(evidence ->
+                        new FileEvidenceProperty(evidenceId, fileId, evidence.getName(), propertyMap.get(evidence.getName())))
+                .toList();
+
+    }
+}
diff --git a/src/main/java/com/supervision/police/service/impl/OCRRecordServiceImpl.java b/src/main/java/com/supervision/police/service/impl/OCRRecordServiceImpl.java
index a7e9f50..e6f21b4 100644
--- a/src/main/java/com/supervision/police/service/impl/OCRRecordServiceImpl.java
+++ b/src/main/java/com/supervision/police/service/impl/OCRRecordServiceImpl.java
@@ -4,20 +4,16 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.StrUtil;
 import com.supervision.demo.dto.QARecordNodeDTO;
-import com.supervision.minio.domain.MinioFile;
-import com.supervision.minio.service.MinioService;
 import com.supervision.police.domain.FileOcrProcess;
 import com.supervision.police.domain.ModelRecordType;
 import com.supervision.police.domain.NoteRecord;
 import com.supervision.police.domain.NoteRecordSplit;
 import com.supervision.police.dto.NoteRecordDTO;
-import com.supervision.police.dto.OCRReqDTO;
 import com.supervision.police.dto.OCRTextDTO;
 import com.supervision.police.dto.RecordFileDTO;
 import com.supervision.police.service.*;
 import com.supervision.police.vo.NoteRecordReqVO;
 import com.supervision.utils.RecordRegexUtil;
-import com.supervision.utils.WordReadUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -52,7 +48,7 @@ public class OCRRecordServiceImpl implements OCRRecordService {
             return recordId;
         }
         // 识别文件信息
-        fileOcrProcessService.submitOCR(noteRecordReqVO.getFileIdList());
+        fileOcrProcessService.asyncSubmitOCR(noteRecordReqVO.getFileIdList());
         return recordId;
     }
 
@@ -113,7 +109,7 @@ public class OCRRecordServiceImpl implements OCRRecordService {
         FileOcrProcess fileOcrProcess = fileOcrProcessService.getById(ocrId);
         Assert.notNull(fileOcrProcess, "ocrId:{}对应的ocr信息不存在", ocrId);
 
-        fileOcrProcessService.doOCRTask(CollUtil.newArrayList(fileOcrProcess));
+        fileOcrProcessService.asyncDoOCRTask(CollUtil.newArrayList(fileOcrProcess));
         return null;
     }
 
diff --git a/src/main/resources/mapper/EvidencePropertyMapper.xml b/src/main/resources/mapper/FileEvidencePropertyMapper.xml
similarity index 51%
rename from src/main/resources/mapper/EvidencePropertyMapper.xml
rename to src/main/resources/mapper/FileEvidencePropertyMapper.xml
index ab33e4d..94f0a28 100644
--- a/src/main/resources/mapper/EvidencePropertyMapper.xml
+++ b/src/main/resources/mapper/FileEvidencePropertyMapper.xml
@@ -2,11 +2,12 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.supervision.police.mapper.EvidencePropertyMapper">
+<mapper namespace="com.supervision.police.mapper.FileEvidencePropertyMapper">
 
-    <resultMap id="BaseResultMap" type="com.supervision.police.domain.EvidenceProperty">
+    <resultMap id="BaseResultMap" type="com.supervision.police.domain.FileEvidenceProperty">
             <id property="id" column="id" jdbcType="VARCHAR"/>
             <result property="evidenceId" column="evidence_id" jdbcType="VARCHAR"/>
+            <result property="fileId" column="file_id" jdbcType="VARCHAR"/>
             <result property="propertyName" column="property_name" jdbcType="VARCHAR"/>
             <result property="propertyValue" column="property_value" jdbcType="VARCHAR"/>
             <result property="createUserId" column="create_user_id" jdbcType="VARCHAR"/>
@@ -16,8 +17,22 @@
     </resultMap>
 
     <sql id="Base_Column_List">
-        id,evidence_id,property_name,
-        property_value,create_user_id,create_time,
-        update_user_id,update_time
+        id,evidence_id,file_id,
+        property_name,property_value,create_user_id,
+        create_time,update_user_id,update_time
     </sql>
+    <select id="listPrewByFileIdList" resultType="com.supervision.police.dto.OCREvidencePropertyDTO">
+        select
+            ep.evidence_id as evidenceId,
+            op.file_id as fileId,
+            op.draw_img_id as drawImgId,
+            ep.property_name as propertyName,
+            ep.property_value as propertyValue
+        from file_evidence_property ep
+        left join file_ocr_process op on ep.file_id = op.file_id
+        where ep.file_id in
+        <foreach collection="fileIdList" item="fileId" open="(" separator="," close=")">
+            #{fileId}
+        </foreach>
+    </select>
 </mapper>
diff --git a/src/test/java/com/supervision/demo/FuHsiApplicationTests.java b/src/test/java/com/supervision/demo/FuHsiApplicationTests.java
index bb73086..91cf9c4 100644
--- a/src/test/java/com/supervision/demo/FuHsiApplicationTests.java
+++ b/src/test/java/com/supervision/demo/FuHsiApplicationTests.java
@@ -9,8 +9,11 @@ import com.supervision.neo4j.domain.CaseNode;
 import com.supervision.demo.controller.ExampleChatController;
 import com.supervision.police.domain.ModelRecordType;
 import com.supervision.police.domain.NoteRecordSplit;
+import com.supervision.police.dto.RetrieveReqDTO;
+import com.supervision.police.dto.RetrieveResDTO;
 import com.supervision.police.service.ModelRecordTypeService;
 import com.supervision.police.service.NoteRecordSplitService;
+import com.supervision.police.service.OCRService;
 import com.supervision.police.service.RecordSplitClassifyService;
 import com.supervision.thread.RecordSplitClassifyTask;
 import lombok.extern.slf4j.Slf4j;
@@ -165,4 +168,14 @@ public class FuHsiApplicationTests {
         recordSplitClassifyService.classify(typeList,noteRecordSplits);
         log.info("分类结果:{}",noteRecordSplits);
     }
+
+    @Autowired
+    private OCRService ocrService;
+    @Test
+    public void test1() {
+        String question = "银川市公安局金凤区分局\\r\\n拘留通知书\\r\\n(副本)\\r\\n银金公(经侦)拘通字[2024]10017号\\r\\n梁玉峰家属\\r\\n根据《中华人民共和国刑事诉讼法》第八十二条第(一)项之规定\\r\\n罪\\r\\n将涉嫌合同诈骗\\r\\n我局已于2024年01月16日10时\\r\\n银川市看守所\\r\\n的\\r\\n梁玉峰\\r\\n刑事拘留,现羁押在\\r\\n市\\r\\n二0二\\r\\n年名\\r\\n本通知书已收到。\\r\\n年月\\r\\n日时\\r\\n被拘留人家属:\\r\\n如未在拘留后24小时内通知被拘留人家属,注明原因:办集民警\\r\\n当天拔打梁天峰亲属果无辉毛话,对方电生无法接通\\r\\n办案人:\\r\\n2024年1月16日1时\\r\\n此联附卷";
+        RetrieveResDTO retrieve = ocrService.retrieve(new RetrieveReqDTO(question));
+
+        System.out.println(retrieve);
+    }
 }