Explorar el Código

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

yjwang hace 1 semana
padre
commit
3666c8fcf9

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

@@ -150,7 +150,7 @@ public class TxOcrClient  {
                 result.setSetDate(resp.getSetDate());
                 return result;
             }
-            if(StringUtils.isNotEmpty(keywords) && StringUtils.isEmpty(business)){
+            if(StringUtils.isNotEmpty(keywords) && StringUtils.isNotEmpty(business)){
                 result.setKeywords(keywords);
                 result.setBusinessStr(business);
                 result.setFlag(business.contains(keywords));
@@ -248,10 +248,9 @@ public class TxOcrClient  {
         return null;
     }
 
-//
-//    public static void main(String[] args) {
-//        ExtractDocBasic("https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/fs/20251125/1c3009ab4a964c12b05b8f7fd8e9f7ce.jpg");
-//    }
+    public static void main(String[] args) {
+        ExtractDocBasic("https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/fs/20251113/1843e1df1e14477cb024a928ef9f151a.jpg");
+    }
 
     /**
      * ClassifyDetectOCR

+ 75 - 30
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -1,16 +1,22 @@
 package com.fs.app.service;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.date.DateUtil;
+import com.fs.common.utils.spring.SpringUtils;
 import com.fs.company.domain.CompanyMiniapp;
 import com.fs.company.service.ICompanyMiniappService;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCourseWatchLog;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.service.IFsCourseWatchLogService;
+import com.fs.his.domain.FsUser;
+import com.fs.his.mapper.FsUserMapper;
 import com.fs.ipad.IpadSendUtils;
 import com.fs.ipad.vo.*;
 import com.fs.qw.domain.QwExternalContact;
@@ -28,11 +34,14 @@ import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.wxwork.dto.*;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -49,44 +58,80 @@ public class IpadSendServer {
     private final IQwUserVideoService qwUserVideoService;
     private final RedisCache redisCache;
     private final ICompanyMiniappService companyMiniappService;
-
+    private final IFsCoursePlaySourceConfigService playSourceConfigService;
+    private final FsUserMapper fsUserMapper;
+    private static final List<String> PROJECT_NAMES = Arrays.asList("济南联志健康", "北京存在文化");
     private void sendMiniProgram(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Map<String, FsCoursePlaySourceConfig> miniMap, Long companyId) {
+        // 发送参数原本的appid
         String appid = content.getMiniprogramAppid();
+        // 判断销售工时ID不为空并且有小程序类型
         if(companyId != null && content.getMiniType() != null){
-            log.error("1.打印企业信息------------------》:{}",companyId);
-            List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId));
-            log.error("2.打印企小程序信息------------------》:{}",companyId);
-            List<CompanyMiniapp> collect = list.stream().filter(e -> e.getType().equals(content.getMiniType())).collect(Collectors.toList());
-            if(!collect.isEmpty() && collect.get(0) != null && StringUtils.isNotEmpty(collect.get(0).getAppId())){
-                appid = collect.get(0).getAppId();
+            // 获取销售公司下面绑定的主备小程序,并且根据当前应该发送的主备类型查询出数据
+            List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId).eq("type", content.getMiniType()));
+            // 判断当前绑定的最新的小程序,并且覆盖以前的值(可以达到实时替换小程序的功能)
+            if(!list.isEmpty() && list.get(0) != null && StringUtils.isNotEmpty(list.get(0).getAppId())){
+                appid = list.get(0).getAppId();
             }
-            if(!vo.isRoom()){
-             try {
-                 log.error("3.打印查询id信息-------------------》{}",vo.getExId());
-                 QwExternalContact qwExternalContact = qwExternalContactMapper.selectOne(new LambdaQueryWrapper<QwExternalContact>().eq(QwExternalContact::getQwUserId,vo.getQwUserId()).eq(QwExternalContact::getExternalUserId,vo.getExId()));
-                 log.error("4.打印外部联系人ID-------------------》{}",qwExternalContact.getId());
-                 LocalDateTime createTime = qwExternalContact.getCreateTime() == null ? LocalDateTime.now() : DateUtil.dateToLocalDateTime(qwExternalContact.getCreateTime());
-                 LocalDateTime lastTime = LocalDateTime.of(2025, 11, 6, 23, 59, 59);
-                 int listIndex = createTime.isAfter(lastTime) ? 1 : 0 ;
-                 List<CompanyMiniapp> collect2 = list.stream().filter(e -> e.getType().equals(listIndex)).collect(Collectors.toList());
-                 if(!collect2.isEmpty() && collect2.get(0) != null && StringUtils.isNotEmpty(collect2.get(0).getAppId())){
-                     appid = collect2.get(0).getAppId();
-                     log.error("5.打印小程序信息2------------------》:{}",appid);
-                 }
-             } catch (Exception e) {
-                 e.printStackTrace();
-                 log.error("6.输出外部联系人ID-------------->{}",vo.getExId());
-                 log.error("7.数据异常----------------------》{}",e.getMessage());
-             }
+            // 获取配置文件里面的项目名称
+            String signProjectName = SpringUtils.getProperty("cloud_host.company_name");
+            //区分新老用户,新用户发送备用小程序,老用户发送主小程序,TODO 需要使用的项目在参数里面加上
+            if(PROJECT_NAMES.contains(signProjectName)){
+                log.info("ID:{}, qwUserId:{},externalId:{},进入区分发小程序逻辑", vo.getId(), vo.getQwUserId(), vo.getExId());
+                // 判断消息是否是群聊,不是群聊再进去,TODO 当权无法判断群聊是否可以发送对应的小程序
+                if(!vo.isRoom()){
+                    log.info("qwUserId:{},externalId:{},不是群聊", vo.getQwUserId(), vo.getExId());
+                    try {
+                        // 获取当前外部联系人
+                        QwExternalContact qwExternalContact = qwExternalContactMapper.selectOne(new LambdaQueryWrapper<QwExternalContact>().eq(QwExternalContact::getQwUserId,vo.getQwUserId()).eq(QwExternalContact::getExternalUserId,vo.getExId()).last(" limit 1"));
+                        // 当前外部联系是否绑定用户数据,如果数据为空则是没看过小程序的新用户,不用去判断小程序,跳过判断
+                        if(qwExternalContact.getFsUserId() != null){
+                            // 根据用户绑定信息去查询用户信息
+                            FsUser fsUser = fsUserMapper.selectFsUserByUserId(qwExternalContact.getFsUserId());
+                            // 判断用户是否有看过其他的小程序多个
+                            if(StringUtils.isNotEmpty(fsUser.getAppId())){
+                                // 获取用户看过的小程序ID集合
+                                List<String> miniAppList = Arrays.asList(fsUser.getAppId().split(","));
+                                // 根据小程序ID查询小程序列表
+                                List<FsCoursePlaySourceConfig> configList = playSourceConfigService.selectByAppIds(miniAppList);
+                                // 筛选出半封禁的小程序数据,得到这个数据然后优先发这个小程序
+                                Optional<FsCoursePlaySourceConfig> optional = configList.stream().filter(e -> e.getStatus() != null && e.getStatus() == 1).findFirst();
+                                // 判断是否找到
+                                if(optional.isPresent()){
+                                    // 找到半封禁并且在appid里面存在证明这个客户是打开过小程序,优先发送这个
+                                    appid = optional.get().getAppid();
+                                }
+                            }else{
+                                // 获取用户的创建时间
+                                LocalDateTime createTime = DateUtil.dateToLocalDateTime(fsUser.getCreateTime());
+                                log.info("ID:{}, qwUserId:{},externalId:{},已绑定小程序,判断时间:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), createTime);
+                                // 这个时间是写死的,目前判断的芳华封禁的时间,可以更具项目调整
+                                LocalDateTime lastTime = LocalDateTime.of(2025, 11, 6, 23, 59, 59);
+                                // 判断客户创建时间是在这个之前还是之后
+                                int listIndex = createTime.isAfter(lastTime) ? 1 : 0 ;
+                                // 获取公司里面的主备小程序,根据用户创建时间来发送主备,如果创建时间大于上看的时间就发送备用小程序,如果小于就发送主要小程序
+                                List<CompanyMiniapp> collect2 = list.stream().filter(e -> e.getType().equals(listIndex)).collect(Collectors.toList());
+                                // 判断是否获取到了配置
+                                if(!collect2.isEmpty() && collect2.get(0) != null && StringUtils.isNotEmpty(collect2.get(0).getAppId())){
+                                    appid = collect2.get(0).getAppId();
+                                    log.info("ID:{}, qwUserId:{},externalId:{},发送小程序:{}", vo.getId(), vo.getQwUserId(), vo.getExId(), appid);
+                                }
+                            }
+                        }else{
+                            log.info("ID:{}, qwUserId:{},externalId:{},未绑定小程序用户", vo.getId(), vo.getQwUserId(), vo.getExId());
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        log.error("6.输出外部联系人ID-------------->{}",vo.getExId());
+                        log.error("7.数据异常----------------------》{}",e.getMessage());
+                    }
+                }
             }
         }
         FsCoursePlaySourceConfig courseMaConfig = miniMap.get(appid);
-        log.error("8.打印小程序配置信息------------------》:{}",1);
         if(courseMaConfig == null){
             List<CompanyMiniapp> list = companyMiniappService.list(new QueryWrapper<CompanyMiniapp>().eq("company_id", companyId).eq("type", 1));
             if(!list.isEmpty() && list.get(0) != null && StringUtils.isNotEmpty(list.get(0).getAppId())){
                 courseMaConfig = miniMap.get(list.get(0).getAppId());
-                log.error("9.打印小程序配置信息--------最终------------------》:{}",courseMaConfig);
             }
         }
         if(courseMaConfig == null){
@@ -322,7 +367,7 @@ public class IpadSendServer {
             return false;
         }
 
-        if (qwSopLogs.getSendType() != 12 && noSop) {
+        if (qwSopLogs.getSendType() != 6 && noSop) {
             // 客户的信息
 //            QwExternalContactHParam contactHParam = new QwExternalContactHParam();
 //            contactHParam.setUserId(qwUser.getQwUserId().trim());
@@ -361,7 +406,7 @@ public class IpadSendServer {
     public void send(QwSopCourseFinishTempSetting.Setting content, QwUser qwUser, QwSopLogs qwSopLogs, Map<String, FsCoursePlaySourceConfig> miniMap, BaseVo parentVo) {
         BaseVo vo = new BaseVo();
         vo.setId(Long.parseLong(qwSopLogs.getId()));
-        vo.setRoom(qwSopLogs.getSendType() == 12);
+        vo.setRoom(qwSopLogs.getSendType() == 6);
         vo.setUuid(qwUser.getUid());
         vo.setExId(qwSopLogs.getExternalUserId());
         vo.setServerId(qwUser.getServerId());
@@ -409,7 +454,7 @@ public class IpadSendServer {
                     break;
             }
         } catch (Exception e) {
-            log.error("ID:" + qwSopLogs.getId() + "-发送失败QW_SOP_ID:" + qwSopLogs.getId(), e);
+            log.error("ID:{}-发送失败QW_SOP_ID:{},content:{},vo:{}", qwSopLogs.getId(), qwSopLogs.getId(), JSON.toJSONString(content), JSON.toJSONString(vo), e);
             content.setSendStatus(2);
             content.setSendRemarks("发送失败:" + e.getMessage());
         }

+ 2 - 0
fs-service/src/main/java/com/fs/course/service/IFsCoursePlaySourceConfigService.java

@@ -13,4 +13,6 @@ public interface IFsCoursePlaySourceConfigService extends IService<FsCoursePlayS
      * 查询点播配置列表
      */
     List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(Map<String, Object> params);
+
+    List<FsCoursePlaySourceConfig> selectByAppIds(List<String> miniAppList);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCoursePlaySourceConfigServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.course.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
@@ -24,4 +25,9 @@ public class FsCoursePlaySourceConfigServiceImpl extends ServiceImpl<FsCoursePla
     public List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(Map<String, Object> params) {
         return baseMapper.selectCoursePlaySourceConfigVOListByMap(params);
     }
+
+    @Override
+    public List<FsCoursePlaySourceConfig> selectByAppIds(List<String> miniAppList) {
+        return baseMapper.selectList(new QueryWrapper<FsCoursePlaySourceConfig>().in("appid", miniAppList));
+    }
 }

+ 6 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -2112,6 +2112,12 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Transactional
     public ResponseResult<FsUser> isAddCompanyUser(FsUserCourseAddCompanyUserParam param) {
         logger.info("\n 【进入个微-判断是否添加客服】,入参:{}",param);
+        if("医健宝".equals(signProjectName)){
+            CompanyTrafficRecord companyTrafficRecord = companyTrafficRecordMapper.selectOne(new QueryWrapper<CompanyTrafficRecord>().eq("company_id", param.getCompanyId()));
+            if(companyTrafficRecord == null || companyTrafficRecord.getBalance() <= 0){
+                return ResponseResult.fail(500, "暂时无法观看,请联系管理员(流量)");
+            }
+        }
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
         boolean oneCompanyCourse = config.isOneCompanyCourse();

+ 22 - 0
fs-service/src/main/java/com/fs/hisStore/service/categoryVal/AbstractHandler.java

@@ -0,0 +1,22 @@
+package com.fs.hisStore.service.categoryVal;
+
+import com.fs.common.utils.txocr.ContainsResult;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/11/28 下午2:19
+ */
+public abstract class AbstractHandler implements InitializingBean {
+
+    /**
+     * 校验
+     * @param cateName 分类名称
+     * @param storeId 店铺id
+     */
+    public ContainsResult check(String cateName, Long storeId){
+        throw new UnsupportedOperationException();
+    }
+
+}

+ 73 - 0
fs-service/src/main/java/com/fs/hisStore/service/categoryVal/CommonCheck.java

@@ -0,0 +1,73 @@
+package com.fs.hisStore.service.categoryVal;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.fs.common.utils.txocr.ContainsResult;
+import com.fs.common.utils.txocr.TxOcrClient;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.domain.FsStoreScrmOcr;
+import com.fs.hisStore.mapper.FsStoreScrmOcrMapper;
+import com.fs.hisStore.service.impl.FsStoreScrmServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description: 非特殊都直接从公共验证中获取
+ * @author: Guos
+ * @time: 2025/11/28 下午3:24
+ */
+@Component
+public class CommonCheck extends AbstractHandler {
+
+    @Lazy
+    @Autowired
+    private FsStoreScrmServiceImpl fsStoreScrmService;
+
+    @Autowired
+    private FsStoreScrmOcrMapper fsStoreScrmOcrMapper;
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        ProductCategoryCheckFactory.register("1101165230", this);
+    }
+
+    /**
+     * 校验
+     *
+     * @param cateName 分类名称
+     * @param storeId  店铺id
+     */
+    public ContainsResult check(String cateName, Long storeId) {
+        FsStoreScrm fsStoreScrm = fsStoreScrmService.selectFsStoreByStoreId(storeId);
+
+        //通过店铺id获取上传的药品经营许可证。
+        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 result;
+    }
+
+}

+ 29 - 0
fs-service/src/main/java/com/fs/hisStore/service/categoryVal/IIIMedicalDeviceCheck.java

@@ -0,0 +1,29 @@
+package com.fs.hisStore.service.categoryVal;
+
+import com.fs.common.utils.txocr.ContainsResult;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/11/28 下午2:21
+ */
+@Component
+public class IIIMedicalDeviceCheck extends AbstractHandler{
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        ProductCategoryCheckFactory.register("233", this);
+    }
+
+    /**
+     * 校验
+     * @param cateName
+     * @param storeId
+     */
+    public ContainsResult check(String cateName, Long storeId){
+        System.out.println("3类器械验证");
+        return null;
+    }
+
+}

+ 29 - 0
fs-service/src/main/java/com/fs/hisStore/service/categoryVal/IIMedicalDeviceCheck.java

@@ -0,0 +1,29 @@
+package com.fs.hisStore.service.categoryVal;
+
+import com.fs.common.utils.txocr.ContainsResult;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/11/28 下午2:21
+ */
+@Component
+public class IIMedicalDeviceCheck extends AbstractHandler{
+
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        ProductCategoryCheckFactory.register("232", this);
+    }
+
+    /**
+     * 校验
+     * @param cateName
+     * @param storeId
+     */
+    public ContainsResult check(String cateName, Long storeId){
+        System.out.println("2类器械验证");
+        return null;
+    }
+}

+ 62 - 0
fs-service/src/main/java/com/fs/hisStore/service/categoryVal/IMedicalDeviceCheck.java

@@ -0,0 +1,62 @@
+package com.fs.hisStore.service.categoryVal;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.fs.common.utils.txocr.ContainsResult;
+import com.fs.common.utils.txocr.TxOcrClient;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.domain.FsStoreScrmOcr;
+import com.fs.hisStore.mapper.FsStoreScrmOcrMapper;
+import com.fs.hisStore.service.impl.FsStoreScrmServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description: 1类器械验证 1类需要验证的时间是经营许可证是否有“第一类医疗器械销售”
+ * @author: Guos
+ * @time: 2025/11/28 下午2:21
+ */
+@Slf4j
+@Component
+public class IMedicalDeviceCheck extends AbstractHandler{
+
+    @Autowired
+    private FsStoreScrmOcrMapper fsStoreScrmOcrMapper;
+
+    @Lazy
+    @Autowired
+    private FsStoreScrmServiceImpl fsStoreScrmService;
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        ProductCategoryCheckFactory.register("202", this);
+    }
+
+    private static final String I_MEDICAL_DEVICE = "第一类医疗器械销售";
+
+    /**
+     * 校验
+     * @param cateName
+     * @param storeId
+     */
+    public ContainsResult check(String cateName, Long storeId){
+        FsStoreScrmOcr fsStoreScrmOcr = fsStoreScrmOcrMapper.selectById(storeId);
+        if (ObjectUtil.isEmpty(fsStoreScrmOcr)) {
+            FsStoreScrm fsStoreScrm = fsStoreScrmService.selectFsStoreByStoreId(storeId);
+            //没有就直接去查询,然后调用识别
+            String businessLicense = fsStoreScrm.getBusinessLicense();
+            return TxOcrClient.isContains(businessLicense, I_MEDICAL_DEVICE);
+        }else{
+            String businessLicenseTxt = fsStoreScrmOcr.getBusinessLicenseTxt();
+            boolean containsFlag = businessLicenseTxt.contains(I_MEDICAL_DEVICE);
+            ContainsResult result = new ContainsResult();
+            result.setKeywords(cateName);
+            result.setFlag(containsFlag);
+            result.setMessage(containsFlag?"识别成功,包含所属!":"对比失败,不包含你所选类目");
+            result.setBusinessStr(businessLicenseTxt);
+            return result;
+        }
+    }
+
+}

+ 30 - 0
fs-service/src/main/java/com/fs/hisStore/service/categoryVal/ProductCategoryCheckFactory.java

@@ -0,0 +1,30 @@
+package com.fs.hisStore.service.categoryVal;
+
+import com.fs.common.utils.StringUtils;
+import com.google.common.collect.Maps;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.util.Map;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/11/28 下午2:14
+ */
+public class ProductCategoryCheckFactory {
+
+    private static Map<String, AbstractHandler> strategyMap = Maps.newHashMap();
+
+    public static AbstractHandler getInvokeStrategy(String key){
+        return strategyMap.get(key);
+    }
+
+    public static void register(String key, AbstractHandler handler){
+        if(StringUtils.isEmpty(key) || ObjectUtils.isEmpty(handler)){
+            return;
+        }
+        strategyMap.put(key, handler);
+    }
+
+
+}

+ 43 - 0
fs-service/src/main/java/com/fs/hisStore/service/categoryVal/WellnessFoodCheck.java

@@ -0,0 +1,43 @@
+package com.fs.hisStore.service.categoryVal;
+
+import com.fs.common.utils.txocr.ContainsResult;
+import com.fs.hisStore.domain.FsStoreScrm;
+import com.fs.hisStore.service.impl.FsStoreScrmServiceImpl;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description: 保健食品
+ * @author: Guos
+ * @time: 2025/11/28 下午3:06
+ */
+@Component
+public class WellnessFoodCheck extends AbstractHandler{
+
+    @Lazy
+    @Autowired
+    private FsStoreScrmServiceImpl fsStoreScrmService;
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        ProductCategoryCheckFactory.register("201", this);
+    }
+
+    /**
+     * 校验
+     * @param cateName 分类名称
+     * @param storeId 店铺id
+     */
+    public ContainsResult check(String cateName, Long storeId){
+        FsStoreScrm fsStoreScrm = fsStoreScrmService.selectFsStoreByStoreId(storeId);
+        ContainsResult result = new ContainsResult();
+        boolean flag = StringUtils.isNotEmpty(fsStoreScrm.getFoodLicense());
+        result.setFlag(flag);
+        result.setMessage(flag ? "已上传健康食品经营许可证" : "未上传健康食品经营许可证");
+        //目前没有办法通过文档抽取保健食品中前面的打勾,只能判断是否上传,当然可以重写TxOcrClient.ExtractDocBasic方法。
+        return result;
+    }
+
+}

+ 11 - 92
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java

@@ -40,6 +40,8 @@ import com.fs.hisStore.dto.FsStoreProductScrmInfoDTO;
 import com.fs.hisStore.mapper.*;
 import com.fs.hisStore.param.FsStoreCartCountParam;
 import com.fs.hisStore.service.IFsStoreProductCategoryScrmService;
+import com.fs.hisStore.service.categoryVal.AbstractHandler;
+import com.fs.hisStore.service.categoryVal.ProductCategoryCheckFactory;
 import com.fs.hisStore.util.ForbiddenDrugListManager;
 import com.fs.hisStore.utils.StoreAuditLogUtil;
 import com.fs.hisStore.util.BusinessScopeProductTypeUtil;
@@ -488,19 +490,6 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
         product.setBusinessLink(param.getBusinessLink());
         product.setCreateTime(new Date());
 
-        // 根据经营范围校验商品类型
-//        if (store != null && com.fs.common.utils.StringUtils.isNotEmpty(store.getSelectableProductTypes())) {
-//            String productTypeName = getProductTypeName(product.getCateId());
-//            if (com.fs.common.utils.StringUtils.isNotEmpty(productTypeName)) {
-//                // 直接使用工具类方法校验
-//                //boolean isAllowed = BusinessScopeProductTypeUtil.isProductTypeAllowed(store.getSelectableProductTypes(), productTypeName);
-//                boolean isAllowed = validateShopBusinessScope(store.getBusinessScope(), productTypeName);
-//                if (!isAllowed) {
-//                    return R.error("该商品类型[" + productTypeName + "]不在店铺经营范围允许的商品类型内,请联系管理员核实经营范围");
-//                }
-//            }
-//        }
-
         //判断是否是纯正堂非药品商品不审核
         if(CZT.equals(cloudHostProper.getCompanyName()) || param.getIsDrug() != 1){
             product.setIsAudit("1");
@@ -571,57 +560,6 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
         }
     }
 
-    /**
-     * 校验店铺添加药品是否含有祥光资质
-     * @param businessScope
-     * @param productTypeName
-     * @return
-     */
-    public Boolean validateShopBusinessScope(String businessScope, String productTypeName) {
-        Set<String> judgmentSet = new HashSet<>();
-        Boolean res = Boolean.FALSE;
-        switch (productTypeName) {
-            case "中成药":
-                judgmentSet.add("中成药");
-                break;
-            case "处方药":
-                judgmentSet.add("处方药");
-                judgmentSet.add("化学药制剂");
-                break;
-            case "中药饮片":
-                judgmentSet.add("中药饮片");
-                break;
-            case "保健食品":
-                judgmentSet.add("保健食品销售");
-                break;
-            case "I类器械":
-                judgmentSet.add("第一类医疗器械销售");
-                break;
-            case "II类器械":
-                judgmentSet.add("第二类医疗器械销售");
-                break;
-            case "III类器械":
-                judgmentSet.add("第三类医疗器械经营");
-                break;
-            case "甲类非处方":
-                judgmentSet.add("化学药制剂");
-                judgmentSet.add("甲类非处方药");
-                break;
-            case "乙类非处方":
-                judgmentSet.add("化学药制剂");
-                judgmentSet.add("乙类非处方药");
-                break;
-        }
-
-        if(null != judgmentSet && !judgmentSet.isEmpty()){
-           for(String item:judgmentSet){
-               res = businessScope.contains(item);
-               if(res) break;
-           }
-        }
-        return res;
-    }
-
     private void addProductAttr(Long productId, List<ProductArrtDTO> items, List<FsStoreProductAttrValueScrm> values,Long storeId){
         //清空attr
         fsStoreProductAttrMapper.clear(productId);
@@ -1495,7 +1433,7 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
     }
 
     /**
-     * 判断该药店的经营许可证是否允许上架该商品
+     * 判断该药店的经营许可证是否允许上架该商品(店铺和总后端都用到了)
      * @param storeId 店铺Id
      * @param cateId 分类id
      */
@@ -1505,34 +1443,15 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
         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;
+        //这里需要区别一下,什么情况下需要识别营业执照,什么情况下识别经营许可证,什么情况下两个都需要,甚至包含食品的证
+        //新增分类校验就去 categoryVal 包下面去新加
+        try{
+            AbstractHandler invokeStrategy = ProductCategoryCheckFactory.getInvokeStrategy(String.valueOf(cateId));
+            return invokeStrategy.check(cateName, storeId);
+        }catch (NullPointerException e){
+            AbstractHandler invokeStrategy = ProductCategoryCheckFactory.getInvokeStrategy(String.valueOf("1101165230"));
+            return invokeStrategy.check(cateName, storeId);
         }
-        //调用对比,看经营范围是否包含这个类别
-        return result;
     }
 
     @Override

+ 1 - 0
fs-service/src/main/resources/mapper/hisStore/FsStoreProductCategoryScrmMapper.xml

@@ -34,6 +34,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isDrug != null "> and is_drug = #{isDrug}</if>
             <if test="storeId != null "> and store_id = #{storeId}</if>
         </where>
+        ORDER BY sort asc
     </select>
 
     <select id="selectFsStoreProductCategoryById" parameterType="Long" resultMap="FsStoreProductCategoryResult">