|
|
@@ -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);
|