2 Commits a9fda3c00e ... 337016d3f0

Author SHA1 Message Date
  Guos 337016d3f0 Merge remote-tracking branch 'origin/ScrmStores' into ScrmStores 2 days ago
  Guos 71101b3afc 重新对药品成分检查,加入分词器,对比药品成分是否禁售 2 days ago

+ 4 - 4
fs-admin/src/main/java/com/fs/hisStore/controller/FsStoreProductScrmController.java

@@ -74,16 +74,16 @@ public class FsStoreProductScrmController extends BaseController {
      * @param keyWords
      * @return
      */
-    @Log(title = "商品管理", businessType = BusinessType.AUDIT, isStoreLog = true, logParam = {"商品", "商品关键字检查"})
     @GetMapping("/selectForbiddenKeywords/{keyWords}")
     public R selectForbiddenKeywords(@PathVariable("keyWords")String keyWords) {
         if(org.apache.commons.lang3.StringUtils.isEmpty(keyWords))return R.ok().put("data", true);
-        List<ForbiddenOnlineMedicine> list = fsStoreProductService.selectForbiddenKeywords(keyWords);
-        if(CollectionUtils.isEmpty(list)){
+        SelectForbiddenKeywordsVo selectForbiddenKeywordsVo = fsStoreProductService.selectForbiddenKeywords(keyWords);
+        if(ObjectUtils.isEmpty(selectForbiddenKeywordsVo)){
             return R.ok().put("data", true);
         }else{
-            return R.ok().put("data", false).put("msg", list.get(0).getModule());
+            return R.ok().put("data", false).put("msg", selectForbiddenKeywordsVo.getMsg());
         }
+
     }
 
     /**

+ 8 - 0
fs-service/pom.xml

@@ -297,6 +297,14 @@
             <artifactId>itextpdf</artifactId>
             <version>5.5.13.3</version>
         </dependency>
+
+        <!-- 结巴分词 Java 版 -->
+        <dependency>
+            <groupId>com.huaban</groupId>
+            <artifactId>jieba-analysis</artifactId>
+            <version>1.0.2</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 1 - 3
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreProductScrmMapper.java

@@ -646,11 +646,9 @@ public interface FsStoreProductScrmMapper
 
     /**
      * 商品关键字检查
-     * 只要商品关键字在数据库中存在,就不允许添加商品。
-     * @param keyword
      * @return
      */
-    List<ForbiddenOnlineMedicine> selectForbiddenKeywords(@Param("keyword") String keyword);
+    List<ForbiddenOnlineMedicine> selectForbiddenKeywords();
 
     @Select({"<script> " +
 //            "select p.* from fs_store_product_scrm p  " +

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/service/IFsStoreProductScrmService.java

@@ -37,7 +37,7 @@ public interface IFsStoreProductScrmService
      * @param keyWords
      * @return
      */
-    List<ForbiddenOnlineMedicine> selectForbiddenKeywords(String keyWords);
+    SelectForbiddenKeywordsVo selectForbiddenKeywords(String keyWords);
 
     /**
      * 查询商品

+ 15 - 3
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java

@@ -42,6 +42,7 @@ 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.DrugComponentAnalyzer;
 import com.fs.hisStore.util.ForbiddenDrugListManager;
 import com.fs.hisStore.utils.StoreAuditLogUtil;
 import com.fs.hisStore.util.BusinessScopeProductTypeUtil;
@@ -137,14 +138,25 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
 
 
     /**
-     * 商品关键字检查
+     * 商品关键字检查,这里需要用一些关键字匹配
      * 只要商品关键字在数据库中存在,就不允许添加商品。
      * @param keyWords
      * @return
      */
     @Override
-    public List<ForbiddenOnlineMedicine> selectForbiddenKeywords(String keyWords){
-       return fsStoreProductMapper.selectForbiddenKeywords(keyWords);
+    public SelectForbiddenKeywordsVo selectForbiddenKeywords(String keyWords){
+        List<ForbiddenOnlineMedicine> forbiddenOnlineMedicines = fsStoreProductMapper.selectForbiddenKeywords();
+//        将forbiddenOnlineMedicines转换为set
+        Set<String> forbiddenKeywords = forbiddenOnlineMedicines.stream().map(ForbiddenOnlineMedicine::getForbiddenKeywords).collect(Collectors.toSet());
+        DrugComponentAnalyzer.CheckResult checkResult = DrugComponentAnalyzer.checkForbiddenComponents(forbiddenKeywords, keyWords);
+        boolean forbidden = checkResult.isForbidden();
+        if(!forbidden){
+            return null;
+        }
+        SelectForbiddenKeywordsVo result = new SelectForbiddenKeywordsVo();
+        result.setFlag(forbidden);
+        result.setMsg(checkResult.getForbiddenComponents()+"法律命令禁止销售包含该成分产品!");
+        return result;
     }
 
 

+ 108 - 0
fs-service/src/main/java/com/fs/hisStore/util/DrugComponentAnalyzer.java

@@ -0,0 +1,108 @@
+package com.fs.hisStore.util;
+
+import com.huaban.analysis.jieba.JiebaSegmenter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/12/5 下午3:07
+ */
+public class DrugComponentAnalyzer {
+
+    // 禁售成分库(可从数据库/配置文件加载)
+    private static final Set<String> FORBIDDEN_COMPONENTS = new HashSet<>(Arrays.asList(
+            "罂粟壳", "吗啡", "海洛因", "可卡因", "芬太尼"
+    ));
+    // 停用词集合
+    private static Set<String> STOP_WORDS;
+
+    // 复用分词器实例(注意:Jieba非线程安全,多线程需每个线程new实例)
+    private static final JiebaSegmenter SEGMENTER = new JiebaSegmenter();
+
+
+
+    /**
+     * 拆分药品成分(过滤停用词,仅保留有效成分)
+     */
+    private static List<String> splitDrugComponents(String text) {
+        // 第一步:Jieba精确分词
+        List<String> rawWords = SEGMENTER.sentenceProcess(text);
+        // 第二步:过滤停用词、空字符串、纯数字/单位
+        return rawWords.stream()
+                .map(String::trim)
+                .filter(word -> !word.isEmpty())
+                .filter(word -> !isNumberOrUnit(word)) // 过滤剂量/单位(如0.5g、mg)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 检查是否包含禁售成分
+     */
+    public static CheckResult checkForbiddenComponents(Set<String> ForbiddenComponents, String text) {
+        List<String> components = splitDrugComponents(text);
+        // 匹配禁售成分
+        Set<String> forbiddenMatches = components.stream()
+                .filter(ForbiddenComponents::contains)
+                .collect(Collectors.toSet());
+        // 返回检查结果
+        return new CheckResult(
+                components, // 所有有效成分
+                forbiddenMatches, // 命中的禁售成分
+                !forbiddenMatches.isEmpty() // 是否禁售
+        );
+    }
+
+    /**
+     * 辅助方法:判断是否为数字/单位(如0.5g、2mg、10ml)
+     */
+    private static boolean isNumberOrUnit(String word) {
+        // 匹配数字+单位的组合,或纯单位/纯数字
+        return word.matches("[0-9.]+[gmgml毫克克毫升]+")
+                || word.matches("[0-9.]+")
+                || Arrays.asList("g", "mg", "ml", "毫克", "克", "毫升").contains(word);
+    }
+
+    // 检查结果封装类
+    public static class CheckResult {
+        private List<String> allComponents; // 所有拆分出的成分
+        private Set<String> forbiddenComponents; // 命中的禁售成分
+        private boolean isForbidden; // 是否禁售
+
+        // 构造器、getter/setter
+        public CheckResult(List<String> allComponents, Set<String> forbiddenComponents, boolean isForbidden) {
+            this.allComponents = allComponents;
+            this.forbiddenComponents = forbiddenComponents;
+            this.isForbidden = isForbidden;
+        }
+
+        // getter/setter 省略,可自行生成
+        public List<String> getAllComponents() { return allComponents; }
+        public Set<String> getForbiddenComponents() { return forbiddenComponents; }
+        public boolean isForbidden() { return isForbidden; }
+    }
+
+    public static void main(String[] args) {
+        // 测试文本1:含禁售成分
+        String text1 = "本品含对乙酰氨基酚0.5g、罂粟2mg,辅料为淀粉";
+        CheckResult result1 = checkForbiddenComponents(FORBIDDEN_COMPONENTS, text1);
+        System.out.println("文本1拆分成分:" + result1.getAllComponents());
+        System.out.println("文本1禁售成分:" + result1.getForbiddenComponents());
+        System.out.println("文本1是否禁售:" + result1.isForbidden());
+        // 输出:
+        // 文本1拆分成分:[对乙酰氨基酚, 罂粟壳, 淀粉]
+        // 文本1禁售成分:[罂粟壳]
+        // 文本1是否禁售:true
+
+        // 测试文本2:无禁售成分
+        String text2 = "阿莫西林克拉维酸钾分散片,辅料为硬脂酸镁";
+        CheckResult result2 = checkForbiddenComponents(FORBIDDEN_COMPONENTS, text2);
+        System.out.println("\n文本2拆分成分:" + result2.getAllComponents());
+        System.out.println("文本2是否禁售:" + result2.isForbidden());
+        // 输出:
+        // 文本2拆分成分:[阿莫西林克拉维酸钾, 硬脂酸镁]
+        // 文本2是否禁售:false
+    }
+
+}

+ 17 - 0
fs-service/src/main/java/com/fs/hisStore/vo/SelectForbiddenKeywordsVo.java

@@ -0,0 +1,17 @@
+package com.fs.hisStore.vo;
+
+import lombok.Data;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/12/5 下午2:20
+ */
+@Data
+public class SelectForbiddenKeywordsVo {
+
+    private boolean flag;
+
+    private String msg;
+
+}

+ 1 - 42
fs-service/src/main/resources/mapper/hisStore/FsStoreProductScrmMapper.xml

@@ -786,7 +786,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         WHERE p.product_id IN <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">#{item}</foreach>
     </select>
 
-    <select id="selectForbiddenKeywords" parameterType="String" resultType="com.fs.hisStore.domain.ForbiddenOnlineMedicine">
+    <select id="selectForbiddenKeywords" resultType="com.fs.hisStore.domain.ForbiddenOnlineMedicine">
         SELECT
             id,
             module,
@@ -798,47 +798,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             exception,
             remarks
         FROM forbidden_online_medicines
-        <where>
-            <if test="keyword == null or keyword.trim() == ''">
-                1 = 0
-            </if>
-            <if test="keyword != null and keyword.trim() != ''">
-                AND (
-                (medicine_ingredient IS NOT NULL
-                AND medicine_ingredient != ''
-                AND medicine_ingredient LIKE CONCAT('%', #{keyword}, '%')
-                )
-                OR
-                (forbidden_keywords IS NOT NULL
-                AND forbidden_keywords != ''
-                AND forbidden_keywords LIKE CONCAT('%', #{keyword}, '%')
-                )
-                OR
-                (medicine_ingredient IS NOT NULL
-                AND medicine_ingredient != ''
-                AND REPLACE(medicine_ingredient, ' ', '') != ''
-                AND REPLACE(medicine_ingredient, ' ', '') LIKE CONCAT('%', #{keyword}, '%')
-                )
-                OR
-                (forbidden_keywords IS NOT NULL
-                AND forbidden_keywords != ''
-                AND REPLACE(forbidden_keywords, ' ', '') != ''
-                AND REPLACE(forbidden_keywords, ' ', '') LIKE CONCAT('%', #{keyword}, '%')
-                )
-                )
-            </if>
-        </where>
-        <if test="keyword != null and keyword.trim() != ''">
-            ORDER BY
-            CASE
-            WHEN medicine_ingredient = #{keyword} THEN 1
-            WHEN forbidden_keywords = #{keyword} THEN 1
-            WHEN medicine_ingredient LIKE CONCAT(#{keyword}, '%') THEN 2
-            WHEN forbidden_keywords LIKE CONCAT(#{keyword}, '%') THEN 2
-            ELSE 3
-            END,
-            module, category, serial_number
-        </if>
     </select>
 
     <select id="selectFsStoreProductGoodListList" resultType="com.fs.hisStore.vo.FsStoreProductListQueryVO">

+ 4 - 11
fs-store/src/main/java/com/fs/hisStore/controller/store/FsStoreProductScrmController.java

@@ -1,6 +1,5 @@
 package com.fs.hisStore.controller.store;
 
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -11,9 +10,7 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.framework.service.TokenServiceScrm;
-import com.fs.his.param.FsStoreProductListSParam;
 import com.fs.his.vo.FsStoreProductExcelVO;
-import com.fs.his.vo.FsStoreProductListSVO;
 import com.fs.his.vo.OptionsVO;
 import com.fs.hisStore.domain.*;
 import com.fs.hisStore.param.FsStoreProductAddEditParam;
@@ -22,13 +19,13 @@ import com.fs.hisStore.service.IFsStoreProductScrmService;
 import com.fs.hisStore.utils.StoreAuditLogUtil;
 import com.fs.hisStore.utils.UserUtil;
 import com.fs.hisStore.vo.FsStoreProductListVO;
+import com.fs.hisStore.vo.SelectForbiddenKeywordsVo;
 import com.fs.store.vo.FsStoreProductStoreExcelVO;
 import com.mysql.cj.util.StringUtils;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -63,15 +60,14 @@ public class FsStoreProductScrmController extends BaseController
      * @param keyWords
      * @return
      */
-    @Log(title = "商品管理", businessType = BusinessType.AUDIT, isStoreLog = true, logParam = {"商品", "商品关键字检查"})
     @GetMapping("/selectForbiddenKeywords/{keyWords}")
     public R selectForbiddenKeywords(@PathVariable("keyWords")String keyWords) {
         if(org.apache.commons.lang3.StringUtils.isEmpty(keyWords))return R.ok().put("data", true);
-        List<ForbiddenOnlineMedicine> list = fsStoreProductService.selectForbiddenKeywords(keyWords);
-        if(CollectionUtils.isEmpty(list)){
+        SelectForbiddenKeywordsVo selectForbiddenKeywordsVo = fsStoreProductService.selectForbiddenKeywords(keyWords);
+        if(ObjectUtils.isEmpty(selectForbiddenKeywordsVo)){
             return R.ok().put("data", true);
         }else{
-            return R.ok().put("data", false).put("msg", list.get(0).getModule());
+            return R.ok().put("data", false).put("msg", selectForbiddenKeywordsVo.getMsg());
         }
     }
 
@@ -182,7 +178,6 @@ public class FsStoreProductScrmController extends BaseController
 	@DeleteMapping("/{productIds}")
     public R remove(@PathVariable Long[] productIds)
     {
-
         return fsStoreProductService.deleteFsStoreProductByIds(productIds);
     }
 
@@ -210,7 +205,6 @@ public class FsStoreProductScrmController extends BaseController
     @GetMapping(value = "/{productId}")
     public R getInfo(@PathVariable("productId") Long productId)
     {
-
         FsStoreProductScrm product = fsStoreProductService.selectFsStoreProductByProductId(productId);
         List<FsStoreProductAttrScrm> attrs=attrService.selectFsStoreProductAttrByProductId(productId);
         return R.ok().put("data",product).put("attrs", attrs);
@@ -220,7 +214,6 @@ public class FsStoreProductScrmController extends BaseController
     @GetMapping("/getAllStoreProductRule")
     public R getAllList()
     {
-
         List<FsStoreProductRuleScrm> list = fsStoreProductService.selectFsStoreProductRuleList();
         return R.ok().put("data",list);
     }