Selaa lähdekoodia

优化ocr识别问题,对商品类目检查逻辑优化

Guos 1 viikko sitten
vanhempi
commit
4f285232e4

+ 1 - 1
fs-admin/src/main/resources/logback.xml

@@ -77,7 +77,7 @@
 	<logger name="org.springframework" level="warn" />
 
     <!-- log4j2.xml -->
-    <Logger name="com.fs.his.mapper" level="debug"/>
+    <Logger name="com.fs.hisStore.mapper" level="debug"/>
     <Logger name="org.apache.ibatis" level="debug"/>
 
 

+ 0 - 4
fs-common/pom.xml

@@ -154,16 +154,12 @@
             <scope>compile</scope>
         </dependency>
 
-
         <dependency>
             <groupId>com.nuonuo</groupId>
             <artifactId>open-sdk</artifactId>
             <version>1.0.5.2</version>
         </dependency>
 
-
-
-
         <dependency>
             <groupId>net.coobird</groupId>
             <artifactId>thumbnailator</artifactId>

+ 69 - 4
fs-common/src/main/java/com/fs/common/utils/txocr/TxOcrClient.java

@@ -1,6 +1,9 @@
 package com.fs.common.utils.txocr;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.tencentcloudapi.common.AbstractModel;
+import com.tencentcloudapi.common.CommonClient;
 import com.tencentcloudapi.common.Credential;
 import com.tencentcloudapi.common.exception.TencentCloudSDKException;
 import com.tencentcloudapi.common.profile.ClientProfile;
@@ -51,7 +54,31 @@ public class TxOcrClient  {
 
 
     /**
-     * 药品经营许可证识别
+     * 文档抽取
+     * @param imageUrl
+     * @return
+     */
+    public static String ExtractDocBasic(String imageUrl){
+        try {
+            Credential cred = new Credential("AKIDviPyMZbRp24udCcpqjQxHOK4cx88ze6N", "97tVwEJE81sY0StDPPGukQ2ZvkU3QceY");
+            HttpProfile httpProfile = new HttpProfile();
+            httpProfile.setEndpoint("ocr.tencentcloudapi.com");
+            ClientProfile clientProfile = new ClientProfile();
+            clientProfile.setHttpProfile(httpProfile);
+            CommonClient client = new CommonClient("ocr", "2018-11-19", cred, "", clientProfile);
+            String params = "{\"ImageUrl\":\"" + imageUrl + "\"}";
+            String resp = client.call("ExtractDocBasic", params);
+            log.info("文档抽取成功!结果:{}", resp);
+            String ocrStr = extractBusinessScope(resp);
+            return ocrStr;
+        } catch (TencentCloudSDKException e) {
+            log.info("文档抽取失败:{}", e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 药品经营许可证识别(有概率识别不准)
      * @param imageUrl
      * @return
      */
@@ -136,7 +163,7 @@ public class TxOcrClient  {
                 return result;
             }
         } catch (TencentCloudSDKException e) {
-            log.info("营业执照OCR请求发生异常!异常信息是:{}",e.toString());
+            log.error("营业执照OCR请求发生异常!异常信息是:{}",e.toString());
             result.setFlag(false);
             result.setMessage(e.getMessage());
             return result;
@@ -180,13 +207,52 @@ public class TxOcrClient  {
             log.info("许可证书OCR请求识别成功!结果是:{}",AbstractModel.toJsonString(resp));
             return result;
         } catch (TencentCloudSDKException e) {
-            log.info("证书识别失败!异常信息是:{}",e.toString());
+            log.error("证书识别失败!异常信息是:{}",e.toString());
             result.setFlag(false);
             result.setMessage(e.getMessage());
             return result;
         }
     }
 
+    /**
+     * 从OCR结果中提取经营范围字符串
+     * @param jsonResponse OCR返回的JSON字符串
+     * @return 经营范围内容
+     */
+    public static String extractBusinessScope(String jsonResponse) {
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode rootNode = mapper.readTree(jsonResponse);
+            JsonNode structuralList = rootNode.path("Response").path("StructuralList");
+
+            // 遍历所有结构化文本块
+            for (JsonNode block : structuralList) {
+                JsonNode groups = block.path("Groups");
+                for (JsonNode group : groups) {
+                    JsonNode lines = group.path("Lines");
+                    for (JsonNode line : lines) {
+                        JsonNode key = line.path("Key");
+                        String keyName = key.path("AutoName").asText();
+
+                        // 查找"经营范围"相关的键
+                        if ("经营范围".equals(keyName)) {
+                            JsonNode value = line.path("Value");
+                            return value.path("AutoContent").asText();
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+//
+//    public static void main(String[] args) {
+//        ExtractDocBasic("https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/fs/20251125/1c3009ab4a964c12b05b8f7fd8e9f7ce.jpg");
+//    }
+
     /**
      * ClassifyDetectOCR
      * 支持身份证、护照、名片、银行卡、行驶证、驾驶证、港澳台通行证、户口本、港澳台来往内地通行证、港澳台居住证、不动产证、营业执照的智能分类。
@@ -219,5 +285,4 @@ public class TxOcrClient  {
 //    }
 
 
-
 }

+ 87 - 87
fs-service/src/main/java/com/fs/hisStore/listener/FsStoreScrmListener.java

@@ -1,87 +1,87 @@
-package com.fs.hisStore.listener;
-
-import com.fs.common.utils.txocr.TxOcrClient;
-import com.fs.hisStore.domain.FsStoreScrm;
-import com.fs.hisStore.domain.FsStoreScrmOcr;
-import com.fs.hisStore.mapper.FsStoreScrmMapper;
-import com.fs.hisStore.mapper.FsStoreScrmOcrMapper;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.ObjectUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.util.Date;
-
-/**
- * @description:
- * @author: Guos
- * @time: 2025/11/21 上午9:44
- */
-@Slf4j
-@Component
-public class FsStoreScrmListener {
-
-    @Resource
-    private FsStoreScrmOcrMapper fsStoreScrmOcrMapper;
-
-    @Autowired
-    private FsStoreScrmMapper fsStoreMapper;
-
-
-    @EventListener
-    public void StoreScrmOcrListener(FsStoreScrm fsStore){
-        log.info("StoreScrmOcrListener start");
-        //先查ocr的表中是否存在,
-        // 1.店铺存在,url不一致 调用识别并更新
-        // 2.店铺存在,url一致,不重新调用识别
-        // 3.店铺不存在,说明是新增,新增直接识别别插入
-        FsStoreScrmOcr fsStoreScrmOcr = new FsStoreScrmOcr();
-        Boolean oldBusinessLicenseFlag = false;
-        Boolean oldDrugLicenseFlag = false;
-        FsStoreScrmOcr OldFsStoreScrmOcr = null;
-        if(null == fsStore.getStoreId()){
-            log.info("新增店铺id为空!");
-            //如果是新增id是自增的,这时候可以先用StoreSeq,或者account以及storeName这种具有唯一性的字段进行反查StoreId
-            String storeSeq = fsStore.getStoreSeq();//这个是必须会生成的,所以我们这直接去查询
-            FsStoreScrm fsStoreScrm = fsStoreMapper.selectFsStoreByStoreSeq(storeSeq);
-            fsStoreScrmOcr.setStoreId(fsStoreScrm.getStoreId());
-        }else{
-            fsStoreScrmOcr.setStoreId(fsStore.getStoreId());
-            OldFsStoreScrmOcr = fsStoreScrmOcrMapper.selectById(fsStore.getStoreId());
-            if(!ObjectUtils.isEmpty(OldFsStoreScrmOcr)){
-                fsStoreScrmOcr.setStoreId(OldFsStoreScrmOcr.getStoreId());
-                String OldBusinessLicense = OldFsStoreScrmOcr.getBusinessLicense();
-                String OldDrugLicense = OldFsStoreScrmOcr.getDrugLicense();
-                oldDrugLicenseFlag = OldDrugLicense.equals(fsStore.getDrugLicense());
-                oldBusinessLicenseFlag = OldBusinessLicense.equals(fsStore.getBusinessLicense());
-            }
-        }
-        //不一致才会去更新
-        if(!oldBusinessLicenseFlag){
-            fsStoreScrmOcr.setBusinessLicense(fsStore.getBusinessLicense());
-            String result = TxOcrClient.bizLicenseOCR(fsStoreScrmOcr.getBusinessLicense());
-            if(!result.isEmpty()){
-                fsStoreScrmOcr.setBusinessLicenseTxt(result);
-            }
-        }
-        if(!oldDrugLicenseFlag){
-            fsStoreScrmOcr.setDrugLicense(fsStore.getDrugLicense());
-            String result = TxOcrClient.enterpriseLicenseOCR(fsStore.getDrugLicense());
-            if(!result.isEmpty()){
-                fsStoreScrmOcr.setDrugLicenseTxt(result);
-            }
-        }
-        fsStoreScrmOcr.setUpdateTime(LocalDateTime.now());
-        if(ObjectUtils.isEmpty(OldFsStoreScrmOcr)){
-            fsStoreScrmOcr.setCreateTime(LocalDateTime.now());
-            fsStoreScrmOcrMapper.insert(fsStoreScrmOcr);
-        }else{
-            fsStoreScrmOcrMapper.updateById(fsStoreScrmOcr);
-        }
-        log.info("StoreScrmOcrListener end");
-    }
-
-}
+//package com.fs.hisStore.listener;
+//
+//import com.fs.common.utils.txocr.TxOcrClient;
+//import com.fs.hisStore.domain.FsStoreScrm;
+//import com.fs.hisStore.domain.FsStoreScrmOcr;
+//import com.fs.hisStore.mapper.FsStoreScrmMapper;
+//import com.fs.hisStore.mapper.FsStoreScrmOcrMapper;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.lang3.ObjectUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.context.event.EventListener;
+//import org.springframework.stereotype.Component;
+//
+//import javax.annotation.Resource;
+//import java.time.LocalDateTime;
+//import java.util.Date;
+//
+///**
+// * @description:
+// * @author: Guos
+// * @time: 2025/11/21 上午9:44
+// */
+//@Slf4j
+//@Component
+//public class FsStoreScrmListener {
+//
+//    @Resource
+//    private FsStoreScrmOcrMapper fsStoreScrmOcrMapper;
+//
+//    @Autowired
+//    private FsStoreScrmMapper fsStoreMapper;
+//
+//
+//    @EventListener
+//    public void StoreScrmOcrListener(FsStoreScrm fsStore){
+//        log.info("StoreScrmOcrListener start");
+//        //先查ocr的表中是否存在,
+//        // 1.店铺存在,url不一致 调用识别并更新
+//        // 2.店铺存在,url一致,不重新调用识别
+//        // 3.店铺不存在,说明是新增,新增直接识别别插入
+//        FsStoreScrmOcr fsStoreScrmOcr = new FsStoreScrmOcr();
+//        Boolean oldBusinessLicenseFlag = false;
+//        Boolean oldDrugLicenseFlag = false;
+//        FsStoreScrmOcr OldFsStoreScrmOcr = null;
+//        if(null == fsStore.getStoreId()){
+//            log.info("新增店铺id为空!");
+//            //如果是新增id是自增的,这时候可以先用StoreSeq,或者account以及storeName这种具有唯一性的字段进行反查StoreId
+//            String storeSeq = fsStore.getStoreSeq();//这个是必须会生成的,所以我们这直接去查询
+//            FsStoreScrm fsStoreScrm = fsStoreMapper.selectFsStoreByStoreSeq(storeSeq);
+//            fsStoreScrmOcr.setStoreId(fsStoreScrm.getStoreId());
+//        }else{
+//            fsStoreScrmOcr.setStoreId(fsStore.getStoreId());
+//            OldFsStoreScrmOcr = fsStoreScrmOcrMapper.selectById(fsStore.getStoreId());
+//            if(!ObjectUtils.isEmpty(OldFsStoreScrmOcr)){
+//                fsStoreScrmOcr.setStoreId(OldFsStoreScrmOcr.getStoreId());
+//                String OldBusinessLicense = OldFsStoreScrmOcr.getBusinessLicense();
+//                String OldDrugLicense = OldFsStoreScrmOcr.getDrugLicense();
+//                oldDrugLicenseFlag = OldDrugLicense.equals(fsStore.getDrugLicense());
+//                oldBusinessLicenseFlag = OldBusinessLicense.equals(fsStore.getBusinessLicense());
+//            }
+//        }
+//        //不一致才会去更新
+//        if(!oldBusinessLicenseFlag){
+//            fsStoreScrmOcr.setBusinessLicense(fsStore.getBusinessLicense());
+//            String result = TxOcrClient.bizLicenseOCR(fsStoreScrmOcr.getBusinessLicense());
+//            if(!result.isEmpty()){
+//                fsStoreScrmOcr.setBusinessLicenseTxt(result);
+//            }
+//        }
+//        if(!oldDrugLicenseFlag){
+//            fsStoreScrmOcr.setDrugLicense(fsStore.getDrugLicense());
+//            String result = TxOcrClient.ExtractDocBasic(fsStore.getDrugLicense());
+//            if(!result.isEmpty()){
+//                fsStoreScrmOcr.setDrugLicenseTxt(result);
+//            }
+//        }
+//        fsStoreScrmOcr.setUpdateTime(LocalDateTime.now());
+//        if(ObjectUtils.isEmpty(OldFsStoreScrmOcr)){
+//            fsStoreScrmOcr.setCreateTime(LocalDateTime.now());
+//            fsStoreScrmOcrMapper.insert(fsStoreScrmOcr);
+//        }else{
+//            fsStoreScrmOcrMapper.updateById(fsStoreScrmOcr);
+//        }
+//        log.info("StoreScrmOcrListener end");
+//    }
+//
+//}

+ 9 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreScrmOcrMapper.java

@@ -28,5 +28,14 @@ public interface FsStoreScrmOcrMapper {
      */
     int updateById(FsStoreScrmOcr fsStoreScrmOcr);
 
+    /**
+     * 根据店铺ID和药品经营许可证经营范围图片URL查询店铺OCR信息记录
+     * @param storeId 店铺ID
+     * @param drugLicenseUrl 经营许可证图片URL
+     * @param businessUrl 营业执照图片URL
+     * @return 店铺OCR信息实体对象
+     */
+    FsStoreScrmOcr selectByIdAndUrl(@Param("storeId") Long storeId, @Param("drugLicenseUrl")String drugLicenseUrl, @Param("businessUrl")String businessUrl);
+
 
 }

+ 29 - 1
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java

@@ -121,6 +121,10 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
     @Autowired
     private IFsStoreProductCategoryScrmService fsStoreProductCategoryService;
 
+    @Autowired
+    private FsStoreScrmOcrMapper fsStoreScrmOcrMapper;
+
+
     private ForbiddenDrugListManager forbiddenListManager = new ForbiddenDrugListManager();
 
     public void init() {
@@ -1500,11 +1504,35 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
         //先通过分类id获取具体的分类名称
         FsStoreProductCategoryScrm fsStoreProductCategoryScrm = fsStoreProductCategoryService.selectFsStoreProductCategoryById(cateId);
         String cateName = fsStoreProductCategoryScrm.getCateName();//分类名称
+        //拿到分类名称,直接调用之前店铺编辑和新增接口中调用识别存到识别表的结果。
         //通过店铺id获取上传的药品经营许可证。
         FsStoreScrm fsStoreScrm = fsStoreScrmService.selectFsStoreByStoreId(storeId);
         String drugLicenseUrl = fsStoreScrm.getDrugLicense();
+        FsStoreScrmOcr fsStoreScrmOcr = fsStoreScrmOcrMapper.selectByIdAndUrl(storeId, drugLicenseUrl, null);
+        //没有搜索到就调用一次识别
+        ContainsResult result = new ContainsResult();
+        result.setKeywords(cateName);
+
+        if(ObjectUtil.isEmpty(fsStoreScrmOcr)){
+            String ocrResult = TxOcrClient.ExtractDocBasic(drugLicenseUrl);
+            if(null != ocrResult){
+                boolean equalsR = ocrResult.contains(cateName);
+                result.setFlag(equalsR);
+                result.setMessage(equalsR?"识别成功,包含所属!":"对比失败,不包含你所选类目");
+                result.setBusinessStr(ocrResult);
+            }else{
+                result.setFlag(false);
+                result.setMessage("请上传正确药品经营许可证!");
+            }
+        }else{
+            result.setBusinessStr(fsStoreScrmOcr.getDrugLicenseTxt());
+            boolean equalsR = fsStoreScrmOcr.getDrugLicenseTxt().contains(cateName);
+            result.setFlag(equalsR);
+            result.setMessage(equalsR?"识别成功,包含所属!":"对比失败,不包含你所选类目");
+            return result;
+        }
         //调用对比,看经营范围是否包含这个类别
-        return TxOcrClient.enterpriseLicenseOCR(drugLicenseUrl, cateName);
+        return result;
     }
 
     @Override

+ 4 - 1
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreScrmServiceImpl.java

@@ -471,7 +471,10 @@ public class FsStoreScrmServiceImpl implements IFsStoreScrmService {
         FsStoreScrm updateStore = new FsStoreScrm();
         BeanUtils.copyProperties(fsStore, updateStore);
         updateStore.setUpdateTime(DateUtils.getNowDate());
-        return fsStoreMapper.updateFsStore(updateStore);
+        int updateRowNum = fsStoreMapper.updateFsStore(updateStore);
+        //信息发布
+        applicationEventPublisher.publishEvent(fsStore);
+        return updateRowNum;
     }
 
     @Override

+ 87 - 0
fs-service/src/main/java/com/fs/hisStore/service/listener/FsStoreScrmListener.java

@@ -0,0 +1,87 @@
+package com.fs.hisStore.service.listener;
+
+import com.fs.common.utils.txocr.TxOcrClient;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.domain.FsStoreScrmOcr;
+import com.fs.hisStore.mapper.FsStoreScrmMapper;
+import com.fs.hisStore.mapper.FsStoreScrmOcrMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/11/21 上午9:44
+ */
+@Slf4j
+@Service
+public class FsStoreScrmListener {
+
+    @Resource
+    private FsStoreScrmOcrMapper fsStoreScrmOcrMapper;
+
+    @Autowired
+    private FsStoreScrmMapper fsStoreMapper;
+
+
+    @EventListener
+    public void StoreScrmOcrListener(FsStoreScrm fsStore){
+        log.info("StoreScrmOcrListener start");
+        //先查ocr的表中是否存在,
+        // 1.店铺存在,url不一致 调用识别并更新
+        // 2.店铺存在,url一致,不重新调用识别
+        // 3.店铺不存在,说明是新增,新增直接识别别插入
+        FsStoreScrmOcr fsStoreScrmOcr = new FsStoreScrmOcr();
+        Boolean oldBusinessLicenseFlag = false;
+        Boolean oldDrugLicenseFlag = false;
+        FsStoreScrmOcr OldFsStoreScrmOcr = null;
+        if(null == fsStore.getStoreId()){
+            log.info("新增店铺id为空!");
+            //如果是新增id是自增的,这时候可以先用StoreSeq,或者account以及storeName这种具有唯一性的字段进行反查StoreId
+            String storeSeq = fsStore.getStoreSeq();//这个是必须会生成的,所以我们这直接去查询
+            FsStoreScrm fsStoreScrm = fsStoreMapper.selectFsStoreByStoreSeq(storeSeq);
+            fsStoreScrmOcr.setStoreId(fsStoreScrm.getStoreId());
+        }else{
+            fsStoreScrmOcr.setStoreId(fsStore.getStoreId());
+            OldFsStoreScrmOcr = fsStoreScrmOcrMapper.selectById(fsStore.getStoreId());
+            if(!ObjectUtils.isEmpty(OldFsStoreScrmOcr)){
+                fsStoreScrmOcr.setStoreId(OldFsStoreScrmOcr.getStoreId());
+                String OldBusinessLicense = OldFsStoreScrmOcr.getBusinessLicense();
+                String OldDrugLicense = OldFsStoreScrmOcr.getDrugLicense();
+                oldDrugLicenseFlag = OldDrugLicense.equals(fsStore.getDrugLicense());
+                oldBusinessLicenseFlag = OldBusinessLicense.equals(fsStore.getBusinessLicense());
+            }
+        }
+        //不一致才会去更新
+        if(!oldBusinessLicenseFlag){
+            fsStoreScrmOcr.setBusinessLicense(fsStore.getBusinessLicense());
+            String result = TxOcrClient.bizLicenseOCR(fsStoreScrmOcr.getBusinessLicense());
+            if(!result.isEmpty()){
+                fsStoreScrmOcr.setBusinessLicenseTxt(result);
+            }
+        }
+        if(!oldDrugLicenseFlag){
+            fsStoreScrmOcr.setDrugLicense(fsStore.getDrugLicense());
+            String result = TxOcrClient.ExtractDocBasic(fsStore.getDrugLicense());
+            if(!result.isEmpty()){
+                fsStoreScrmOcr.setDrugLicenseTxt(result);
+            }
+        }
+        fsStoreScrmOcr.setUpdateTime(LocalDateTime.now());
+        if(ObjectUtils.isEmpty(OldFsStoreScrmOcr)){
+            fsStoreScrmOcr.setCreateTime(LocalDateTime.now());
+            fsStoreScrmOcrMapper.insert(fsStoreScrmOcr);
+        }else{
+            fsStoreScrmOcrMapper.updateById(fsStoreScrmOcr);
+        }
+        log.info("StoreScrmOcrListener end");
+    }
+
+}

+ 20 - 0
fs-service/src/main/resources/mapper/hisStore/FsStoreScrmOcrMapper.xml

@@ -72,6 +72,26 @@
         where store_id= #{storeId}
     </select>
 
+    <select id="selectByIdAndUrl" resultType="com.fs.hisStore.domain.FsStoreScrmOcr">
+        select
+            store_id,
+            business_license,
+            drug_license,
+            business_license_txt,
+            drug_license_txt,
+            business_license_ocr_result,
+            drug_license_ocr_result,
+            create_time,
+            update_time
+        from fs_store_scrm_ocr
+        where store_id= #{storeId}
+        <if test="businessUrl != null">
+            and business_license = #{businessUrl}
+        </if>
+        <if test="drugLicenseUrl != null" >
+            and drug_license = #{drugLicenseUrl}
+        </if>
+    </select>
 
 
 </mapper>

+ 4 - 0
fs-store/src/main/resources/logback.xml

@@ -80,6 +80,10 @@
 		<appender-ref ref="console" />
 	</root>
 
+    <!-- log4j2.xml -->
+    <Logger name="com.fs.hisStore.mapper" level="debug"/>
+    <Logger name="org.apache.ibatis" level="debug"/>
+
 	<!--系统操作日志-->
     <root level="info">
         <appender-ref ref="file_info" />