diff --git a/src/main/java/com/youlai/boot/admin/constant/AuditConstants.java b/src/main/java/com/youlai/boot/admin/constant/AuditConstants.java index bb051a7..cdd1006 100644 --- a/src/main/java/com/youlai/boot/admin/constant/AuditConstants.java +++ b/src/main/java/com/youlai/boot/admin/constant/AuditConstants.java @@ -39,4 +39,12 @@ public final class AuditConstants { public static final String TRIGGER_CREATE = "create"; public static final String TRIGGER_REPORT = "report"; + // ======================== 业务审核状态 ======================== + /** 审核通过 (可直接发布/展示) */ + public static final Integer BIZ_AUDIT_STATUS_PASSED = 0; + /** 审核中 */ + public static final Integer BIZ_AUDIT_STATUS_REVIEWING = 1; + /** 审核未通过 */ + public static final Integer BIZ_AUDIT_STATUS_REJECTED = 2; + } diff --git a/src/main/java/com/youlai/boot/admin/service/BizAuditStatusHandler.java b/src/main/java/com/youlai/boot/admin/service/BizAuditStatusHandler.java new file mode 100644 index 0000000..d437644 --- /dev/null +++ b/src/main/java/com/youlai/boot/admin/service/BizAuditStatusHandler.java @@ -0,0 +1,23 @@ +package com.youlai.boot.admin.service; + +/** + * 业务审核状态处理器 —— 审核汇总(MiniContentAudit)状态变更后,同步更新对应业务实体的审核状态。 + */ +public interface BizAuditStatusHandler { + + /** + * 审核通过时回调 + * + * @param moduleCode 业务模块编码 + * @param bizId 业务数据ID + */ + void onAuditPassed(String moduleCode, Long bizId); + + /** + * 审核不通过时回调 + * + * @param moduleCode 业务模块编码 + * @param bizId 业务数据ID + */ + void onAuditRejected(String moduleCode, Long bizId); +} diff --git a/src/main/java/com/youlai/boot/admin/service/impl/BizAuditStatusHandlerImpl.java b/src/main/java/com/youlai/boot/admin/service/impl/BizAuditStatusHandlerImpl.java new file mode 100644 index 0000000..d998c4f --- /dev/null +++ b/src/main/java/com/youlai/boot/admin/service/impl/BizAuditStatusHandlerImpl.java @@ -0,0 +1,138 @@ +package com.youlai.boot.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.youlai.boot.admin.constant.AuditConstants; +import com.youlai.boot.admin.service.BizAuditStatusHandler; +import com.youlai.boot.mini.mapper.*; +import com.youlai.boot.mini.model.entity.*; +import com.youlai.boot.system.mapper.UserMapper; +import com.youlai.boot.system.model.entity.SysUser; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; + +/** + * 业务审核状态处理器实现 —— 审核完成后同步更新业务实体的审核状态。 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class BizAuditStatusHandlerImpl implements BizAuditStatusHandler { + + private final MiniUserPostMapper miniUserPostMapper; + private final MiniStrayAnimalMapper miniStrayAnimalMapper; + private final MiniAdoptionDiaryMapper miniAdoptionDiaryMapper; + private final MiniStrayAnimalNoteCommentMapper strayAnimalNoteCommentMapper; + private final MiniAdoptionDiaryCommentMapper adoptionDiaryCommentMapper; + private final MiniUserPostCommentMapper userPostCommentMapper; + private final UserMapper userMapper; + + @Value("${oss.aliyun.endpoint}") + private String endpoint; + + @Value("${oss.aliyun.bucket-name}") + private String bucketName; + + @Override + @Transactional(rollbackFor = Exception.class) + public void onAuditPassed(String moduleCode, Long bizId) { + log.info("审核通过, moduleCode={}, bizId={}", moduleCode, bizId); + switch (moduleCode) { + case "user_post" -> updateUserPostAuditStatus(bizId, AuditConstants.BIZ_AUDIT_STATUS_PASSED); + case "animal_note" -> updateStrayAnimalAuditStatus(bizId, AuditConstants.BIZ_AUDIT_STATUS_PASSED); + case "adoption_diary" -> updateAdoptionDiaryAuditStatus(bizId, AuditConstants.BIZ_AUDIT_STATUS_PASSED); + // 评论 / 头像 / 昵称 / 简介 通过时无需额外操作 + default -> log.debug("模块 {} 审核通过无需同步业务状态", moduleCode); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void onAuditRejected(String moduleCode, Long bizId) { + log.info("审核不通过, moduleCode={}, bizId={}", moduleCode, bizId); + switch (moduleCode) { + case "user_post" -> updateUserPostAuditStatus(bizId, AuditConstants.BIZ_AUDIT_STATUS_REJECTED); + case "animal_note" -> updateStrayAnimalAuditStatus(bizId, AuditConstants.BIZ_AUDIT_STATUS_REJECTED); + case "adoption_diary" -> updateAdoptionDiaryAuditStatus(bizId, AuditConstants.BIZ_AUDIT_STATUS_REJECTED); + case "note_comment" -> deleteNoteComment(bizId); + case "diary_comment" -> deleteDiaryComment(bizId); + case "post_comment" -> deletePostComment(bizId); + case "user_avatar" -> resetUserAvatarToDefault(bizId); + default -> log.debug("模块 {} 审核不通过无需同步业务状态", moduleCode); + } + } + + private void updateUserPostAuditStatus(Long postId, Integer auditStatus) { + MiniUserPost entity = new MiniUserPost(); + entity.setId(postId); + entity.setAuditStatus(auditStatus); + entity.setUpdateTime(new Date()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + miniUserPostMapper.updateById(entity); + log.info("用户作品审核状态已更新, postId={}, auditStatus={}", postId, auditStatus); + } + + private void updateStrayAnimalAuditStatus(Long animalId, Integer auditStatus) { + MiniStrayAnimal entity = new MiniStrayAnimal(); + entity.setId(animalId); + entity.setAuditStatus(auditStatus); + entity.setUpdateTime(new Date()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + miniStrayAnimalMapper.updateById(entity); + log.info("流浪动物审核状态已更新, animalId={}, auditStatus={}", animalId, auditStatus); + } + + private void updateAdoptionDiaryAuditStatus(Long diaryId, Integer auditStatus) { + MiniAdoptionDiary entity = new MiniAdoptionDiary(); + entity.setId(diaryId); + entity.setAuditStatus(auditStatus); + entity.setUpdateTime(new Date()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + miniAdoptionDiaryMapper.updateById(entity); + log.info("领养日记审核状态已更新, diaryId={}, auditStatus={}", diaryId, auditStatus); + } + + private void deleteNoteComment(Long commentId) { + MiniStrayAnimalNoteComment entity = new MiniStrayAnimalNoteComment(); + entity.setId(commentId); + entity.setDeleted(true); + entity.setUpdateTime(new Date()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + strayAnimalNoteCommentMapper.updateById(entity); + log.info("流浪动物笔记评论审核不通过已删除, commentId={}", commentId); + } + + private void deleteDiaryComment(Long commentId) { + MiniAdoptionDiaryComment entity = new MiniAdoptionDiaryComment(); + entity.setId(commentId); + entity.setDeleted(true); + entity.setUpdateTime(new Date()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + adoptionDiaryCommentMapper.updateById(entity); + log.info("领养日记评论审核不通过已删除, commentId={}", commentId); + } + + private void deletePostComment(Long commentId) { + MiniUserPostComment entity = new MiniUserPostComment(); + entity.setId(commentId); + entity.setDeleted(true); + entity.setUpdateTime(new Date()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + userPostCommentMapper.updateById(entity); + log.info("用户作品评论审核不通过已删除, commentId={}", commentId); + } + + private void resetUserAvatarToDefault(Long userId) { + String defaultAvatar = "https://" + bucketName + "." + endpoint + "/default_avatar.png"; + userMapper.update(null, + new LambdaUpdateWrapper() + .eq(SysUser::getId, userId) + .set(SysUser::getAvatar, defaultAvatar) + ); + log.info("用户头像审核不通过已重置为默认头像, userId={}", userId); + } +} diff --git a/src/main/java/com/youlai/boot/admin/service/impl/ContentAuditServiceImpl.java b/src/main/java/com/youlai/boot/admin/service/impl/ContentAuditServiceImpl.java index 1a09721..65edbae 100644 --- a/src/main/java/com/youlai/boot/admin/service/impl/ContentAuditServiceImpl.java +++ b/src/main/java/com/youlai/boot/admin/service/impl/ContentAuditServiceImpl.java @@ -6,15 +6,24 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.youlai.boot.admin.constant.AuditConstants; import com.youlai.boot.admin.mapper.MiniContentAuditMapper; import com.youlai.boot.admin.model.entity.MiniContentAudit; +import com.youlai.boot.admin.service.BizAuditStatusHandler; import com.youlai.boot.admin.service.ContentAuditService; import com.youlai.boot.framework.security.util.SecurityUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.Date; +@Slf4j @Service public class ContentAuditServiceImpl extends ServiceImpl implements ContentAuditService { + private final BizAuditStatusHandler bizAuditStatusHandler; + + public ContentAuditServiceImpl(BizAuditStatusHandler bizAuditStatusHandler) { + this.bizAuditStatusHandler = bizAuditStatusHandler; + } + @Override public MiniContentAudit createAudit(String moduleCode, Long bizId, String auditType, String triggerType) { MiniContentAudit entity = new MiniContentAudit(); @@ -40,6 +49,22 @@ public class ContentAuditServiceImpl extends ServiceImpl() + .eq(MiniContentAuditConfig::getModuleCode, moduleCode) + .eq(MiniContentAuditConfig::getDeleted, false) + .last("LIMIT 1") + ); + return config != null && !Boolean.TRUE.equals(config.getAuditEnable()); + } + @Override @Transactional(rollbackFor = Exception.class) public String saveUserPost(UserPostForm formData) { long currentTimestamp = System.currentTimeMillis(); Long userId = SecurityUtils.getUserId(); + // 查询审核配置,决定初始审核状态 + boolean auditEnabled = isAuditEnabled("user_post"); + Integer initAuditStatus = auditEnabled + ? AuditConstants.BIZ_AUDIT_STATUS_REVIEWING + : AuditConstants.BIZ_AUDIT_STATUS_PASSED; + // 1. 保存用户作品基本信息 MiniUserPost post = new MiniUserPost(); post.setUuid(UUID.randomUUID().toString()); @@ -208,6 +230,7 @@ public class UserPostServiceImpl extends ServiceImpl auditResult = auditExecutorService.executeAudit("user_post", postId, auditContent, AuditConstants.TRIGGER_CREATE); + if (auditResult != null) { + log.info("用户作品编辑审核任务已创建, postId={}, auditResult={}", postId, auditResult); + } + } catch (Exception e) { + log.error("创建用户作品编辑审核任务失败, 降级为人工审核, postId={}", postId, e); + createManualReviewFallback(postId, formData); + } } @Override @@ -373,6 +416,9 @@ public class UserPostServiceImpl extends ServiceImpl newImageUrls = new ArrayList<>(); + List newVideoUrls = new ArrayList<>(); + // 处理图片 if (CollUtil.isNotEmpty(images)) { for (MultipartFile image : images) { @@ -396,6 +442,7 @@ public class UserPostServiceImpl extends ServiceImpl auditResult = auditExecutorService.executeAudit("user_post", postId, auditContent, AuditConstants.TRIGGER_CREATE); + if (auditResult != null) { + log.info("用户作品补充媒体审核任务已创建, postId={}, auditResult={}", postId, auditResult); + } + } catch (Exception e) { + log.error("创建用户作品补充媒体审核任务失败, 降级为人工审核, postId={}", postId, e); + AuditContentDTO fallbackContent = new AuditContentDTO(); + fallbackContent.setImages(newImageUrls); + fallbackContent.setVideos(newVideoUrls); + createManualReviewFallback(postId, fallbackContent); + } + } } @Override