瀏覽代碼

add:门店装修动态审核(视频为同步审核) TODO:视频审核变为异步审核

刘云鑫 3 月之前
父節點
當前提交
e23320bdfd

+ 86 - 6
alien-store/src/main/java/shop/alien/store/service/impl/StoreRenovationRequirementServiceImpl.java

@@ -17,13 +17,11 @@ import shop.alien.entity.store.dto.StoreRenovationRequirementDto;
 import shop.alien.mapper.StoreInfoMapper;
 import shop.alien.mapper.StoreRenovationRequirementMapper;
 import shop.alien.store.service.StoreRenovationRequirementService;
+import shop.alien.store.util.ai.AiContentModerationUtil;
+import shop.alien.store.util.ai.AiVideoModerationUtil;
 import shop.alien.util.common.JwtUtil;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -40,6 +38,18 @@ public class StoreRenovationRequirementServiceImpl extends ServiceImpl<StoreReno
 
     private final StoreInfoMapper storeInfoMapper;
 
+    private final AiContentModerationUtil aiContentModerationUtil;
+    private final AiVideoModerationUtil aiVideoModerationUtil;
+    // 定义图片后缀常量(不可修改,保证线程安全)
+    private static final Set<String> IMAGE_SUFFIXES = Collections.unmodifiableSet(
+            new HashSet<>(Arrays.asList(".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"))
+    );
+
+    // 定义视频后缀常量
+    private static final Set<String> VIDEO_SUFFIXES = Collections.unmodifiableSet(
+            new HashSet<>(Arrays.asList(".mp4", ".avi", ".mov", ".flv", ".mkv", ".wmv", ".mpeg"))
+    );
+
     @Override
     public boolean saveOrUpdateRequirement(StoreRenovationRequirementDto dto) {
         log.info("StoreRenovationRequirementServiceImpl.saveOrUpdateRequirement?dto={}", dto);
@@ -85,7 +95,23 @@ public class StoreRenovationRequirementServiceImpl extends ServiceImpl<StoreReno
                 requirement.setUpdatedUserId(currentUserId);
                 requirement.setUpdatedTime(new Date());
             }
-
+            // TODO 审核文本和图片内容是否违规
+            // 一次遍历完成分类,避免多次流式处理
+            Map<String, List<String>> urlCategoryMap = classifyUrls(dto.getAttachmentUrls());
+            // 1.调用文本+图片审核接口 ai为同步接口
+            AiContentModerationUtil.AuditResult auditResult = aiContentModerationUtil.auditContent(requirement.getDetailedRequirement(), urlCategoryMap.get("image"));
+            if (!auditResult.isPassed()) {
+                requirement.setAuditStatus(2);
+                requirement.setAuditReason(auditResult.getFailureReason());
+            } else {
+                // 2.调用视频审核接口
+                AiVideoModerationUtil.VideoAuditResult videoAuditResult = aiVideoModerationUtil.auditVideos(urlCategoryMap.get("video"));
+                if (!videoAuditResult.isPassed()) {
+                    requirement.setAuditStatus(2);
+                    requirement.setAuditReason(videoAuditResult.getFailureReason());
+                }
+                requirement.setAuditStatus(1);
+            }
             return this.saveOrUpdate(requirement);
         } catch (Exception e) {
             log.error("保存装修需求失败: {}", e.getMessage(), e);
@@ -93,6 +119,60 @@ public class StoreRenovationRequirementServiceImpl extends ServiceImpl<StoreReno
         }
     }
 
+    /**
+     * 对URL列表进行分类(图片/视频/其他)
+     * @param attachmentUrls 原始URL列表
+     * @return 分类后的Map
+     */
+    private static Map<String, List<String>> classifyUrls(List<String> attachmentUrls) {
+        // 初始化分类容器
+        List<String> imageUrls = new ArrayList<>();
+        List<String> videoUrls = new ArrayList<>();
+        List<String> otherUrls = new ArrayList<>();
+
+        if (Objects.isNull(attachmentUrls) || attachmentUrls.isEmpty()) {
+            return buildResultMap(imageUrls, videoUrls, otherUrls);
+        }
+
+        for (String url : attachmentUrls) {
+            // 空URL直接归为其他
+            if (url == null || url.trim().isEmpty()) {
+                otherUrls.add(url);
+                continue;
+            }
+
+            String lowerUrl = url.toLowerCase().trim();
+            // 优先判断图片(避免URL中同时包含图片+视频后缀的极端情况)
+            boolean isImage = IMAGE_SUFFIXES.stream().anyMatch(lowerUrl::contains);
+            if (isImage) {
+                imageUrls.add(url); // 保留原始URL,而非小写后的
+                continue;
+            }
+
+            // 判断是否为视频
+            boolean isVideo = VIDEO_SUFFIXES.stream().anyMatch(lowerUrl::contains);
+            if (isVideo) {
+                videoUrls.add(url);
+            } else {
+                otherUrls.add(url);
+            }
+        }
+
+        return buildResultMap(imageUrls, videoUrls, otherUrls);
+    }
+
+    /**
+     * 构建分类结果Map
+     */
+    private static Map<String, List<String>> buildResultMap(List<String> imageUrls, List<String> videoUrls, List<String> otherUrls) {
+        Map<String, List<String>> resultMap = new HashMap<>(3);
+        resultMap.put("image", Collections.unmodifiableList(imageUrls)); // 返回不可修改列表,避免外部篡改
+        resultMap.put("video", Collections.unmodifiableList(videoUrls));
+        resultMap.put("other", Collections.unmodifiableList(otherUrls));
+        return resultMap;
+    }
+
+
     @Override
     public StoreRenovationRequirementDto getRequirementDetail(Integer id) {
         log.info("StoreRenovationRequirementServiceImpl.getRequirementDetail?id={}", id);