|
|
@@ -240,12 +240,8 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
return false;
|
|
|
}
|
|
|
goods = secondGoodsMapper.selectById(savedGoodsId);
|
|
|
- // 执行内容审核(图片和文本)
|
|
|
- if (!performContentReviews(goods, goodsDTO)) {
|
|
|
- // 审核不通过,记录操作历史
|
|
|
- recordGoodsOperation(goods);
|
|
|
- return true; // 审核不通过时已设置状态,返回成功但标记为审核失败
|
|
|
- }
|
|
|
+ // 审核不通过时已设置状态,返回成功但标记为审核失败
|
|
|
+ performContentReview(goodsDTO, goods);
|
|
|
|
|
|
return true;
|
|
|
} catch (Exception e) {
|
|
|
@@ -254,6 +250,167 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行内容审核
|
|
|
+ * @param goodsDTO 商品信息
|
|
|
+ * @param goods 商品实体
|
|
|
+ */
|
|
|
+ private void performContentReview(SecondGoodsVo goodsDTO, SecondGoods goods) throws Exception {
|
|
|
+ // 图片审核
|
|
|
+ boolean imageAuditResult = performImageReviews(goods, goodsDTO);
|
|
|
+ /* 添加截断,避免审核结果过多,三个顺序执行,第一个失败后直接返回,以此类推 */
|
|
|
+
|
|
|
+ // 审核失败。直接返回
|
|
|
+ if (!imageAuditResult) {
|
|
|
+ // 图片审核不通过,记录操作历史
|
|
|
+// recordGoodsOperation(goods);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 文本审核
|
|
|
+ boolean textAuditResult = performTextReview(goods, goodsDTO);
|
|
|
+ // 审核失败。直接返回
|
|
|
+ if (!textAuditResult) {
|
|
|
+ // 文本审核不通过,记录操作历史
|
|
|
+// recordGoodsOperation(goods);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 视频审核
|
|
|
+ List<String> taskIds = performVideoReviews(goods, goodsDTO);
|
|
|
+
|
|
|
+ // 如果成功提交了视频审核任务,设置商品状态为审核中
|
|
|
+ if (!taskIds.isEmpty()) {
|
|
|
+ goods.setGoodsStatus(SecondGoodsStatusEnum.UNDER_REVIEW.getCode()); // 审核中
|
|
|
+ goods.setVideoTaskId(taskIds.get(0)); // 保存第一个任务ID到商品表
|
|
|
+ goods.setFailedReason("");
|
|
|
+ updateById(goods);
|
|
|
+ // 审核中审核记录
|
|
|
+ createGoodsAudit(goods, "", Constants.AuditStatus.UNDER_REVIEW);
|
|
|
+ // 审核中,记录操作历史
|
|
|
+// recordGoodsOperation(goods);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 审核通过后上架商品
|
|
|
+ approveAndListGoods(goods);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建商品审核记录
|
|
|
+ * @param goods 商品信息
|
|
|
+ */
|
|
|
+ private void approveAndListGoods(SecondGoods goods) {
|
|
|
+ // 如果所有审核都通过,设置为上架状态
|
|
|
+ goods.setGoodsStatus(SecondGoodsStatusEnum.LISTED.getCode()); // 上架
|
|
|
+ goods.setFailedReason("");
|
|
|
+ goods.setReleaseTime(new Date()); // 上架时间
|
|
|
+ updateById(goods);
|
|
|
+ // 插入审核记录
|
|
|
+ createGoodsAudit(goods, "", Constants.AuditStatus.PASSED);
|
|
|
+ // 发送审核成功消息
|
|
|
+ sendMessage(goods);
|
|
|
+ // 上架 记录商品操作历史
|
|
|
+ recordGoodsOperation(goods);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行视频审核
|
|
|
+ * @param goods 商品信息
|
|
|
+ * @param goodsDTO 商品DTO信息
|
|
|
+ * @return 审核结果
|
|
|
+ */
|
|
|
+ private List<String> performVideoReviews(SecondGoods goods, SecondGoodsVo goodsDTO) {
|
|
|
+ List<String> videoUrls = extractVideoUrls(goodsDTO.getImgUrl());
|
|
|
+ List<String> taskIds = new ArrayList<>();
|
|
|
+ // 视频审核
|
|
|
+ if (videoModerationEnabled) {
|
|
|
+ if (!videoUrls.isEmpty()) {
|
|
|
+ // 提交视频审核任务
|
|
|
+ for (String videoUrl : videoUrls) {
|
|
|
+ try {
|
|
|
+ String taskId = videoModerationService.submitVideoModerationTask(videoUrl);
|
|
|
+ taskIds.add(taskId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("提交视频审核任务失败,视频URL: {}", videoUrl, e);
|
|
|
+ if (videoModerationBlockOnFailure) {
|
|
|
+ // 视频审核提交失败,设置为审核失败状态
|
|
|
+ goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode());
|
|
|
+ goods.setFailedReason("视频审核提交失败: " + e.getMessage());
|
|
|
+ createGoodsAudit(goods, "视频审核提交失败", Constants.AuditStatus.FAILED);
|
|
|
+ sendFailedMsg(goods);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return taskIds;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行文本审核
|
|
|
+ * @param goods 商品信息
|
|
|
+ * @param goodsDTO 商品DTO信息
|
|
|
+ * @return 审核结果
|
|
|
+ */
|
|
|
+ private boolean performTextReview(SecondGoods goods, SecondGoodsVo goodsDTO) throws Exception {
|
|
|
+ List<String> servicesList = Lists.newArrayList();
|
|
|
+ servicesList.add(TextReviewServiceEnum.AD_COMPLIANCE_DETECTION_PRO.getService());
|
|
|
+ servicesList.add(TextReviewServiceEnum.LLM_QUERY_MODERATION.getService());
|
|
|
+ // 使用商品发布场景的审核服务
|
|
|
+ String test = goodsDTO.getDescription() + goodsDTO.getTitle() + goods.getLabel() + goods.getTopic();
|
|
|
+ TextModerationResultVO textCheckResult = textModerationUtil.invokeFunction(test, servicesList);
|
|
|
+
|
|
|
+ if ("high".equals(textCheckResult.getRiskLevel())) {
|
|
|
+ // 文本审核不通过或存在高风险
|
|
|
+ goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode()); // 审核失败
|
|
|
+ goods.setFailedReason("文本审核不通过:" + (textCheckResult.getRiskWords() != null ? textCheckResult.getRiskWords() : "存在高风险内容"));
|
|
|
+ // 插入审核记录
|
|
|
+ createGoodsAudit(goods, textCheckResult.getRiskWords(), Constants.AuditStatus.FAILED);
|
|
|
+ // 发送审核失败消息
|
|
|
+ sendFailedMsg(goods);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行图片审核
|
|
|
+ * @param goods 商品信息
|
|
|
+ * @param goodsDTO 商品DTO信息
|
|
|
+ * @return 审核结果
|
|
|
+ */
|
|
|
+ private boolean performImageReviews(SecondGoods goods, SecondGoodsVo goodsDTO) throws Exception {
|
|
|
+ // 图片审核(循环处理)
|
|
|
+ List<String> imageUrls = goodsDTO.getImgUrl();
|
|
|
+ // 根据imageUrls 过滤不是图片的url
|
|
|
+ imageUrls = imageUrls.stream().filter(url -> url.toLowerCase().endsWith(".jpg") || url.toLowerCase().endsWith(".png") || url.toLowerCase().endsWith(".jpeg") || url.toLowerCase().endsWith(".gif")).collect(Collectors.toList());
|
|
|
+ // 图片审核
|
|
|
+ if (imageUrls != null && !imageUrls.isEmpty()) {
|
|
|
+ StringBuilder failReasonBuilder = new StringBuilder();
|
|
|
+ for (String imageUrl : imageUrls) {
|
|
|
+ List<String> imgServicesList = Lists.newArrayList();
|
|
|
+ // 内容治理检测 + AIGC图片风险检测
|
|
|
+ imgServicesList.add(ImageReviewServiceEnum.TONALITY_IMPROVE.getService());
|
|
|
+ imgServicesList.add(ImageReviewServiceEnum.AIGC_CHECK.getService());
|
|
|
+// imgServicesList.add(ImageReviewServiceEnum.IMG_QUERY_SECURITY_CHECK.getService());
|
|
|
+ ImageModerationResultVO response = imageModerationUtil.productPublishCheck(imageUrl,imgServicesList);
|
|
|
+ if ("high".equals(response.getRiskLevel())) {
|
|
|
+ // 图片审核不通过或存在高风险
|
|
|
+ goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode()); // 审核失败
|
|
|
+ goods.setFailedReason("图片审核不通过:图片中包含" + (response.getDescriptions() != null ? response.getDescriptions() : "高风险内容"));
|
|
|
+ // 插入审核记录
|
|
|
+ createGoodsAudit(goods, response.getDescriptions(), Constants.AuditStatus.FAILED);
|
|
|
+ // 发送审核失败消息
|
|
|
+ sendFailedMsg(goods);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 执行内容审核(图片、文本和视频)
|
|
|
* @param goods 商品信息
|
|
|
@@ -624,6 +781,66 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 查询搜索结果
|
|
|
+ * @param page 分页参数
|
|
|
+ * @param secondGoodsVo 查询参数
|
|
|
+ * @param shieldedGoodsIds 屏蔽商品id
|
|
|
+ * @param userIdList 屏蔽用户id
|
|
|
+ * @return IPage<SecondGoodsVo> 搜索结果
|
|
|
+ */
|
|
|
+ private IPage<SecondGoodsVo> getSecondGoodsVoIPage(IPage<SecondGoodsVo> page, SecondGoodsVo secondGoodsVo, List<Integer> shieldedGoodsIds, List<Integer> userIdList) {
|
|
|
+ QueryWrapper<SecondGoodsVo> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.notIn(CollectionUtil.isNotEmpty(shieldedGoodsIds), "sg.id", shieldedGoodsIds)
|
|
|
+ .notIn(CollectionUtil.isNotEmpty(userIdList), "sg.user_id", userIdList)
|
|
|
+ .eq("sg.goods_status", SecondGoodsStatusEnum.LISTED.getCode())// 3-上架
|
|
|
+ .eq("sg.delete_flag", Constants.DeleteFlag.NOT_DELETED);
|
|
|
+ // 添加对 searchData 的模糊查询
|
|
|
+ if (!StringUtils.isEmpty(secondGoodsVo.getSearchData())) {
|
|
|
+ String searchData = "%" + secondGoodsVo.getSearchData() + "%";
|
|
|
+ queryWrapper.and(wrapper -> wrapper
|
|
|
+ .like("sg.label", searchData)
|
|
|
+ .or()
|
|
|
+ .like("sg.title", searchData)
|
|
|
+ .or()
|
|
|
+ .like("sg.description", searchData)
|
|
|
+ .or()
|
|
|
+ .like("sgc1.category_name", searchData)
|
|
|
+ .or()
|
|
|
+ .like("sgc2.category_name", searchData)
|
|
|
+ .or()
|
|
|
+ .like("sg.topic", searchData)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // 添加对 orderData 的排序 若不为空
|
|
|
+ if (!StringUtils.isEmpty(secondGoodsVo.getOrderData()) && !StringUtils.isEmpty(secondGoodsVo.getOrderType())) {
|
|
|
+ // 正序
|
|
|
+ if (secondGoodsVo.getOrderType() == 1){
|
|
|
+ queryWrapper.orderByAsc(secondGoodsVo.getOrderData())
|
|
|
+ .orderByAsc("distance");
|
|
|
+ }
|
|
|
+ // 倒序
|
|
|
+ if (secondGoodsVo.getOrderType() == 2){
|
|
|
+ queryWrapper.orderByDesc(secondGoodsVo.getOrderData())
|
|
|
+ .orderByAsc("distance");
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ queryWrapper.orderByAsc("distance");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加对 releaseTime 的查询
|
|
|
+ if (secondGoodsVo.getReleaseTime() != null) {
|
|
|
+ queryWrapper.eq("sg.release_time", secondGoodsVo.getReleaseTime());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回分页结果
|
|
|
+ IPage<SecondGoodsVo> searchGoodsList = secondGoodsMapper.searchGoodsList(page, secondGoodsVo.getCurrentLatitude(), secondGoodsVo.getCurrentLongitude() ,queryWrapper);
|
|
|
+ searchGoodsList.getRecords().forEach(secondGoods -> {
|
|
|
+ secondGoods.setPosition(secondGoods.getSearchData());
|
|
|
+ });
|
|
|
+ return searchGoodsList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 批量设置收藏状态
|
|
|
* @param searchGoodsList 搜索结果列表
|
|
|
* @param userId 用户ID(登录用户)
|
|
|
@@ -915,6 +1132,8 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
|
|
|
// 发送审核成功消息
|
|
|
sendMessage(goods);
|
|
|
+ // 审核成功,记录操作历史
|
|
|
+ recordGoodsOperation(goods);
|
|
|
} else {
|
|
|
// 审核不通过
|
|
|
goods.setGoodsStatus(SecondGoodsStatusEnum.REVIEW_FAILED.getCode());
|
|
|
@@ -1001,61 +1220,6 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 查询搜索结果
|
|
|
- * @param page 分页参数
|
|
|
- * @param secondGoodsVo 查询参数
|
|
|
- * @param shieldedGoodsIds 屏蔽商品id
|
|
|
- * @param userIdList 屏蔽用户id
|
|
|
- * @return IPage<SecondGoodsVo> 搜索结果
|
|
|
- */
|
|
|
- private IPage<SecondGoodsVo> getSecondGoodsVoIPage(IPage<SecondGoodsVo> page, SecondGoodsVo secondGoodsVo, List<Integer> shieldedGoodsIds, List<Integer> userIdList) {
|
|
|
- QueryWrapper<SecondGoodsVo> queryWrapper = new QueryWrapper<>();
|
|
|
- queryWrapper.notIn(CollectionUtil.isNotEmpty(shieldedGoodsIds), "sg.id", shieldedGoodsIds)
|
|
|
- .notIn(CollectionUtil.isNotEmpty(userIdList), "sg.user_id", userIdList)
|
|
|
- .eq("sg.goods_status", SecondGoodsStatusEnum.LISTED.getCode())// 3-上架
|
|
|
- .eq("sg.delete_flag", Constants.DeleteFlag.NOT_DELETED);
|
|
|
- // 添加对 searchData 的模糊查询
|
|
|
- if (!StringUtils.isEmpty(secondGoodsVo.getSearchData())) {
|
|
|
- String searchData = "%" + secondGoodsVo.getSearchData() + "%";
|
|
|
- queryWrapper.and(wrapper -> wrapper
|
|
|
- .like("sg.label", searchData)
|
|
|
- .or()
|
|
|
- .like("sg.title", searchData)
|
|
|
- .or()
|
|
|
- .like("sg.description", searchData)
|
|
|
- .or()
|
|
|
- .like("sgc1.category_name", searchData)
|
|
|
- .or()
|
|
|
- .like("sgc2.category_name", searchData)
|
|
|
- .or()
|
|
|
- .like("sg.topic", searchData)
|
|
|
- );
|
|
|
- }
|
|
|
- // 添加对 orderData 的排序 若不为空
|
|
|
- if (!StringUtils.isEmpty(secondGoodsVo.getOrderData()) && !StringUtils.isEmpty(secondGoodsVo.getOrderType())) {
|
|
|
- // 正序
|
|
|
- if (secondGoodsVo.getOrderType() == 1){
|
|
|
- queryWrapper.orderByAsc(secondGoodsVo.getOrderData())
|
|
|
- .orderByAsc("distance");
|
|
|
- }
|
|
|
- // 倒序
|
|
|
- if (secondGoodsVo.getOrderType() == 2){
|
|
|
- queryWrapper.orderByDesc(secondGoodsVo.getOrderData())
|
|
|
- .orderByAsc("distance");
|
|
|
- }
|
|
|
- }else {
|
|
|
- queryWrapper.orderByAsc("distance");
|
|
|
- }
|
|
|
-
|
|
|
- // 返回分页结果
|
|
|
- IPage<SecondGoodsVo> searchGoodsList = secondGoodsMapper.searchGoodsList(page, secondGoodsVo.getCurrentLatitude(), secondGoodsVo.getCurrentLongitude() ,queryWrapper);
|
|
|
- searchGoodsList.getRecords().forEach(secondGoods -> {
|
|
|
- secondGoods.setPosition(secondGoods.getSearchData());
|
|
|
- });
|
|
|
- return searchGoodsList;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
* 批量设置用户信息(用于SecondGoodsVo列表)
|
|
|
* @param searchGoodsList 搜索结果
|
|
|
*/
|