Jelajahi Sumber

Merge remote-tracking branch 'origin/ScrmStores' into ScrmStores

# Conflicts:
#	fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
#	fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java
#	fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
yjwang 1 Minggu lalu
induk
melakukan
5fbe13292b
24 mengubah file dengan 528 tambahan dan 103 penghapusan
  1. 1 1
      fs-admin/src/main/resources/logback.xml
  2. 0 4
      fs-common/pom.xml
  3. 69 4
      fs-common/src/main/java/com/fs/common/utils/txocr/TxOcrClient.java
  4. 5 0
      fs-company-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java
  5. 5 0
      fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
  6. 3 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
  7. 3 0
      fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java
  8. 5 0
      fs-service/src/main/java/com/fs/his/domain/FsUser.java
  9. 14 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java
  10. 87 87
      fs-service/src/main/java/com/fs/hisStore/listener/FsStoreScrmListener.java
  11. 9 0
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreScrmOcrMapper.java
  12. 2 2
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreScrmInfoParam.java
  13. 2 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  14. 29 1
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java
  15. 4 1
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreScrmServiceImpl.java
  16. 87 0
      fs-service/src/main/java/com/fs/hisStore/service/listener/FsStoreScrmListener.java
  17. 5 1
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  18. 20 0
      fs-service/src/main/resources/mapper/hisStore/FsStoreScrmOcrMapper.xml
  19. 3 0
      fs-service/src/main/resources/mapper/hisStore/FsUserScrmMapper.xml
  20. 4 0
      fs-store/src/main/resources/logback.xml
  21. 40 0
      fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java
  22. 46 2
      fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java
  23. 42 0
      fs-user-app/src/main/java/com/fs/app/controller/WxUserController.java
  24. 43 0
      fs-user-app/src/main/java/com/fs/app/controller/store/WxUserScrmController.java

+ 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  {
 //    }
 
 
-
 }

+ 5 - 0
fs-company-app/src/main/java/com/fs/app/param/FsUserLoginByMpParam.java

@@ -9,4 +9,9 @@ import java.io.Serializable;
 public class FsUserLoginByMpParam implements Serializable {
     @NotBlank(message = "code参数缺失")
     private String code;
+
+    /**
+     * 小程序appId
+     */
+    private String appId;
 }

+ 5 - 0
fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java

@@ -96,6 +96,11 @@ public class FsCoursePlaySourceConfig {
      */
     private Integer isMall;
 
+    /**
+     * 小程序状态:0正常,1半封禁,2封禁
+     */
+    private Integer status;
+
     /**
      * 查看数据权限
      * **/

+ 3 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java

@@ -47,6 +47,9 @@ public class FsCoursePlaySourceConfigEditParam {
     private Integer isMall;
     private Long createDeptId;
 
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
+
     /**
      * 查看数据权限范围
      * **/

+ 3 - 0
fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java

@@ -55,4 +55,7 @@ public class FsCoursePlaySourceConfigVO {
      */
     private Integer isMall;
     private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
 }

+ 5 - 0
fs-service/src/main/java/com/fs/his/domain/FsUser.java

@@ -154,6 +154,11 @@ public class FsUser extends BaseEntity
      * 企微销售ID
      * **/
     private Long qwUserId;
+
+    /**
+     * 小程序appId,多个用逗号分隔
+     */
+    private String appId;
     public void setNickName(String nickname)
     {
         if(StringUtils.isNotEmpty(nickname)){

+ 14 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java

@@ -7,6 +7,7 @@ import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 import com.vdurmont.emoji.EmojiParser;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 import org.apache.commons.lang3.StringUtils;
 
 import java.math.BigDecimal;
@@ -178,6 +179,19 @@ public class FsUserScrm extends BaseEntity
      * **/
     private Long qwUserId;
 
+    /**
+     * 小程序appId,多个用逗号分隔
+     */
+    private String appId;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
     public void setNickName(String nickname)
     {
         if(StringUtils.isNotEmpty(nickname)){

+ 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);
+
 
 }

+ 2 - 2
fs-service/src/main/java/com/fs/hisStore/param/FsStoreScrmInfoParam.java

@@ -111,8 +111,8 @@ public class FsStoreScrmInfoParam extends BaseEntity
 //    /** 统一社会信用代码失效日期 */
 //    private String unifiedSocialCreditCodeExpireEnd;
 //
-//    /** 经营范围 */
-//    private String businessScope;
+    /** 经营范围 */
+    private String businessScope;
 
     /**
      *营业执照是否长期有效(1长期有效、0非长期有效)

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -4119,6 +4119,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 user.setStatus(1);
                 user.setMaOpenId(session.getOpenid());
                 user.setUnionId(session.getUnionid());
+                user.setAppId(properties.getConfigs().get(0).getAppid());
                 user.setIsWeixinAuth(0);
                 user.setLastIp(ip);
                 user.setCreateTime(new Date());
@@ -4237,6 +4238,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 user.setStatus(1);
                 user.setMaOpenId(session.getOpenid());
                 user.setUnionId(session.getUnionid());
+                user.setAppId(properties.getConfigs().get(0).getAppid());
                 user.setIsWeixinAuth(0);
                 user.setLastIp(ip);
                 user.setCreateTime(new Date());

+ 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");
+    }
+
+}

+ 5 - 1
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -48,10 +48,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="courseMaOpenId"    column="course_ma_open_id"    />
         <result property="qwExtId"    column="qw_ext_id"    />
         <result property="qwUserId"    column="qw_user_id"    />
+        <result property="appId"    column="app_id"    />
     </resultMap>
 
     <sql id="selectFsUserVo">
-        select user_id,qw_ext_id,sex,is_buy,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,company_id,company_user_id from fs_user
+        select user_id,qw_ext_id,sex,is_buy,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,company_id,company_user_id,app_id from fs_user
     </sql>
 
     <select id="selectFsUserList" parameterType="FsUser" resultMap="FsUserResult">
@@ -557,6 +558,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderCount != null">order_count,</if>
             <if test="companyId != null">company_id,</if>
             <if test="companyUserId != null">company_user_id,</if>
+            <if test="appId != null">app_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="nickName != null">#{nickName},</if>
@@ -600,6 +602,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderCount != null">#{orderCount},</if>
             <if test="companyId != null">#{companyId},</if>
             <if test="companyUserId != null">#{companyUserId},</if>
+            <if test="appId != null">#{appId},</if>
          </trim>
     </insert>
 
@@ -648,6 +651,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">company_id = #{companyId},</if>
             <if test="orderCount != null">order_count = #{orderCount},</if>
             <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="appId != null">app_id = #{appId},</if>
         </trim>
         where user_id = #{userId}
     </update>

+ 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>

+ 3 - 0
fs-service/src/main/resources/mapper/hisStore/FsUserScrmMapper.xml

@@ -446,6 +446,7 @@
             <if test="rank != null">rank,</if>
             <if test="react != null">react,</if>
             <if test="orderCount != null">order_count,</if>
+            <if test="appId != null">app_id,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="username != null">#{username},</if>
@@ -512,6 +513,7 @@
             <if test="rank != null">#{rank},</if>
             <if test="react != null">#{react},</if>
             <if test="orderCount != null">#{orderCount},</if>
+            <if test="appId != null">#{appId},</if>
         </trim>
     </insert>
 
@@ -560,6 +562,7 @@
             <if test="qwExtId != null">qw_ext_id = #{qwExtId},</if>
             <if test="companyId != null">company_id = #{companyId},</if>
             <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="appId != null">app_id = #{appId},</if>
         </trim>
         where user_id = #{userId}
     </update>

+ 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" />

+ 40 - 0
fs-user-app/src/main/java/com/fs/app/controller/AppLoginController.java

@@ -177,6 +177,7 @@ public class AppLoginController extends AppBaseController{
                     user.setSex(sex);
                 }
                 user.setUnionId(unionid);
+                user.setAppId(openProperties.getAppId());
                 user.setCreateTime(new Date());
                 user.setStatus(1);
                 if (StringUtils.isNotEmpty(param.getJpushId())) {
@@ -187,6 +188,15 @@ public class AppLoginController extends AppBaseController{
                 map.put("unionid",unionid);
                 return R.ok(map);
             } else {
+                // 老用户 - 检查并添加appId(不重复添加)
+                String updatedAppId = addAppIdIfNotExists(user.getAppId(), openProperties.getAppId());
+                if (!updatedAppId.equals(user.getAppId())) {
+                    FsUser userMap = new FsUser();
+                    userMap.setUserId(user.getUserId());
+                    userMap.setAppId(updatedAppId);
+                    userService.updateFsUser(userMap);
+                }
+
                 if (StringUtils.isNotEmpty(param.getJpushId())) {
                     updateExistingUserJpushId(user, param.getJpushId());
                 }
@@ -424,4 +434,34 @@ public class AppLoginController extends AppBaseController{
             return R.error("用户不存在!");
         }
     }
+
+    /**
+     * 添加appId到用户的appId列表中(如果不存在)
+     * @param currentAppIds 当前用户已有的appId列表(逗号分隔)
+     * @param newAppId 新的appId
+     * @return 更新后的appId列表
+     */
+    private String addAppIdIfNotExists(String currentAppIds, String newAppId) {
+        // 如果新appId为空,返回原值
+        if (StringUtils.isEmpty(newAppId)) {
+            return currentAppIds == null ? "" : currentAppIds;
+        }
+
+        // 如果当前appId为空,直接返回新appId
+        if (StringUtils.isEmpty(currentAppIds)) {
+            return newAppId;
+        }
+
+        // 检查是否已存在
+        String[] appIdArray = currentAppIds.split(",");
+        for (String appId : appIdArray) {
+            if (appId.trim().equals(newAppId.trim())) {
+                // 已存在,不需要添加
+                return currentAppIds;
+            }
+        }
+
+        // 不存在,追加到末尾
+        return currentAppIds + "," + newAppId;
+    }
 }

+ 46 - 2
fs-user-app/src/main/java/com/fs/app/controller/WxH5MpController.java

@@ -166,7 +166,7 @@ public class WxH5MpController {
             }
 
             // 处理用户信息
-            FsUser user = processUserInfoByCourseLoginByMp(wxMpUser);
+            FsUser user = processUserInfoByCourseLoginByMp(wxMpUser, param);
 
             // 生成token并返回结果
             return generateLoginResult(user);
@@ -189,6 +189,11 @@ public class WxH5MpController {
             userUpdate.setUpdateTime(new DateTime());
             userUpdate.setNickName(wxMpUser.getNickname());
             userUpdate.setAvatar(wxMpUser.getHeadImgUrl());
+            // 老用户 - 检查并添加 appId(不重复添加)
+            String updatedAppId = addAppIdIfNotExists(user.getAppId(), param.getAppId());
+            if (!updatedAppId.equals(user.getAppId())) {
+                userUpdate.setAppId(updatedAppId);
+            }
             userService.updateFsUser(userUpdate);
             return userUpdate;
         } else {
@@ -203,13 +208,15 @@ public class WxH5MpController {
             newUser.setUnionId(wxMpUser.getUnionId());
             newUser.setCreateTime(new Date());
             newUser.setStatus(company != null && company.getFsUserIsDefaultBlack() == 1 ? 0 : 1);
+            // 新用户 - 添加 appId
+            newUser.setAppId(param.getAppId());
             userService.insertFsUser(newUser);
 
             return newUser;
         }
     }
 
-    private FsUser processUserInfoByCourseLoginByMp(WxOAuth2UserInfo wxMpUser) {
+    private FsUser processUserInfoByCourseLoginByMp(WxOAuth2UserInfo wxMpUser, FsUserLoginByCourseMpParam param) {
         FsUser user = userService.selectFsUserByUnionId(wxMpUser.getUnionId());
 
         if (user != null) {
@@ -221,6 +228,11 @@ public class WxH5MpController {
             userUpdate.setUpdateTime(new DateTime());
             userUpdate.setNickName(wxMpUser.getNickname());
             userUpdate.setAvatar(wxMpUser.getHeadImgUrl());
+            // 老用户 - 检查并添加 appId(不重复添加)
+            String updatedAppId = addAppIdIfNotExists(user.getAppId(), param.getAppId());
+            if (!updatedAppId.equals(user.getAppId())) {
+                userUpdate.setAppId(updatedAppId);
+            }
             userService.updateFsUser(userUpdate);
             return userUpdate;
         } else {
@@ -234,6 +246,8 @@ public class WxH5MpController {
 //            newUser.setCompanyUserId(companyUser.getUserId());
             newUser.setUnionId(wxMpUser.getUnionId());
             newUser.setCreateTime(new Date());
+            // 新用户 - 添加 appId
+            newUser.setAppId(param.getAppId());
             userService.insertFsUser(newUser);
             return newUser;
         }
@@ -254,6 +268,36 @@ public class WxH5MpController {
         }
     }
 
+    /**
+     * 添加appId到用户的appId列表中(如果不存在)
+     * @param currentAppIds 当前用户已有的appId列表(逗号分隔)
+     * @param newAppId 新的appId
+     * @return 更新后的appId列表
+     */
+    private String addAppIdIfNotExists(String currentAppIds, String newAppId) {
+        // 如果新appId为空,返回原值
+        if (StringUtils.isEmpty(newAppId)) {
+            return currentAppIds == null ? "" : currentAppIds;
+        }
+
+        // 如果当前appId为空,直接返回新appId
+        if (StringUtils.isEmpty(currentAppIds)) {
+            return newAppId;
+        }
+
+        // 检查是否已存在
+        String[] appIdArray = currentAppIds.split(",");
+        for (String appId : appIdArray) {
+            if (appId.trim().equals(newAppId.trim())) {
+                // 已存在,不需要添加
+                return currentAppIds;
+            }
+        }
+
+        // 不存在,追加到末尾
+        return currentAppIds + "," + newAppId;
+    }
+
     private R generateLoginResult(FsUser user) {
         String token = jwtUtils.generateToken(user.getUserId());
         redisCache.setCacheObject("token:" + user.getUserId(), token, 604800, TimeUnit.SECONDS);

+ 42 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxUserController.java

@@ -156,6 +156,7 @@ public class WxUserController extends AppBaseController{
                     user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                     user.setStatus(1);
                     user.setMaOpenId(session.getOpenid());
+                    user.setAppId(appId);
                     user.setCreateTime(new Date());
                     if(session.getUnionid()!=null){
                         user.setUnionId(session.getUnionid());
@@ -176,6 +177,11 @@ public class WxUserController extends AppBaseController{
                 userMap.setMaOpenId(session.getOpenid());
                 userMap.setPhone(phoneNoInfo.getPhoneNumber());
                 userMap.setUpdateTime(new DateTime());
+                // 老用户 - 检查并添加appId(不重复添加)
+                String updatedAppId = addAppIdIfNotExists(user.getAppId(), appId);
+                if (!updatedAppId.equals(user.getAppId())) {
+                    userMap.setAppId(updatedAppId);
+                }
                 userService.updateFsUser(userMap);
             }
             String token = jwtUtils.generateToken(user.getUserId());
@@ -268,6 +274,7 @@ public class WxUserController extends AppBaseController{
                     user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                     user.setStatus(1);
                     user.setCourseMaOpenId(session.getOpenid());
+                    user.setAppId(appid);
                     user.setCreateTime(new Date());
                     if(session.getUnionid()!=null){
                         user.setUnionId(session.getUnionid());
@@ -288,6 +295,11 @@ public class WxUserController extends AppBaseController{
                 userMap.setCourseMaOpenId(session.getOpenid());
                 userMap.setPhone(phoneNoInfo.getPhoneNumber());
                 userMap.setUpdateTime(new DateTime());
+                // 老用户 - 检查并添加appId(不重复添加)
+                String updatedAppId = addAppIdIfNotExists(user.getAppId(), appid);
+                if (!updatedAppId.equals(user.getAppId())) {
+                    userMap.setAppId(updatedAppId);
+                }
                 userService.updateFsUser(userMap);
             }
             String token = jwtUtils.generateToken(user.getUserId());
@@ -416,4 +428,34 @@ public class WxUserController extends AppBaseController{
 
     }
 
+    /**
+     * 添加appId到用户的appId列表中(如果不存在)
+     * @param currentAppIds 当前用户已有的appId列表(逗号分隔)
+     * @param newAppId 新的appId
+     * @return 更新后的appId列表
+     */
+    private String addAppIdIfNotExists(String currentAppIds, String newAppId) {
+        // 如果新appId为空,返回原值
+        if (StringUtils.isEmpty(newAppId)) {
+            return currentAppIds == null ? "" : currentAppIds;
+        }
+
+        // 如果当前appId为空,直接返回新appId
+        if (StringUtils.isEmpty(currentAppIds)) {
+            return newAppId;
+        }
+
+        // 检查是否已存在
+        String[] appIdArray = currentAppIds.split(",");
+        for (String appId : appIdArray) {
+            if (appId.trim().equals(newAppId.trim())) {
+                // 已存在,不需要添加
+                return currentAppIds;
+            }
+        }
+
+        // 不存在,追加到末尾
+        return currentAppIds + "," + newAppId;
+    }
+
 }

+ 43 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/WxUserScrmController.java

@@ -258,6 +258,8 @@ public class WxUserScrmController extends AppBaseController {
     @PostMapping("/loginByMiniApp")
     @Synchronized
     public R loginByMiniApp( @RequestBody LoginMpWxParam param) {
+            logger.info("小程序登录 参数 {}",param);
+
         if (StringUtils.isBlank(param.getCode())) {
             return R.error("code不存在");
         }
@@ -310,6 +312,11 @@ public class WxUserScrmController extends AppBaseController {
                     if(session.getUnionid()!=null){
                         userMap.setUnionId(session.getUnionid());
                     }
+                    // 检查并添加appId(不重复添加)
+                    String updatedAppId = addAppIdIfNotExists(checkPhone.getAppId(), param.getAppId());
+                    if (!updatedAppId.equals(checkPhone.getAppId())) {
+                        userMap.setAppId(updatedAppId);
+                    }
                     userService.updateFsUser(userMap);
                 }
                 else{
@@ -320,6 +327,7 @@ public class WxUserScrmController extends AppBaseController {
                     user.setAvatar("https://hos-1309931967.cos.ap-chongqing.myqcloud.com/fs/20230725/a848605591384ec29d49773dd58d9345.jpg");
                     user.setStatus(1);
                     user.setMaOpenId(session.getOpenid());
+                    user.setAppId(param.getAppId());
                     user.setCreateTime(new Date());
                     if(session.getUnionid()!=null){
                         user.setUnionId(session.getUnionid());
@@ -340,6 +348,11 @@ public class WxUserScrmController extends AppBaseController {
                 userMap.setMaOpenId(session.getOpenid());
                 userMap.setPhone(phoneNoInfo.getPhoneNumber());
                 userMap.setUpdateTime(new DateTime());
+                // 检查并添加appId(不重复添加)
+                String updatedAppId = addAppIdIfNotExists(user.getAppId(), param.getAppId());
+                if (!updatedAppId.equals(user.getAppId())) {
+                    userMap.setAppId(updatedAppId);
+                }
                 userService.updateFsUser(userMap);
             }
             String token = jwtUtils.generateToken(user.getUserId());
@@ -493,4 +506,34 @@ public class WxUserScrmController extends AppBaseController {
 
     }
 
+    /**
+     * 添加appId到用户的appId列表中(如果不存在)
+     * @param currentAppIds 当前用户已有的appId列表(逗号分隔)
+     * @param newAppId 新的appId
+     * @return 更新后的appId列表
+     */
+    private String addAppIdIfNotExists(String currentAppIds, String newAppId) {
+        // 如果新appId为空,返回原值
+        if (StringUtils.isEmpty(newAppId)) {
+            return currentAppIds == null ? "" : currentAppIds;
+        }
+
+        // 如果当前appId为空,直接返回新appId
+        if (StringUtils.isEmpty(currentAppIds)) {
+            return newAppId;
+        }
+
+        // 检查是否已存在
+        String[] appIdArray = currentAppIds.split(",");
+        for (String appId : appIdArray) {
+            if (appId.trim().equals(newAppId.trim())) {
+                // 已存在,不需要添加
+                return currentAppIds;
+            }
+        }
+
+        // 不存在,追加到末尾
+        return currentAppIds + "," + newAppId;
+    }
+
 }