Browse Source

增加审核后更新业务状态

glx_phase2
glx 5 days ago
parent
commit
1d7928e7fb
  1. 8
      src/main/java/com/youlai/boot/admin/constant/AuditConstants.java
  2. 23
      src/main/java/com/youlai/boot/admin/service/BizAuditStatusHandler.java
  3. 138
      src/main/java/com/youlai/boot/admin/service/impl/BizAuditStatusHandlerImpl.java
  4. 25
      src/main/java/com/youlai/boot/admin/service/impl/ContentAuditServiceImpl.java
  5. 4
      src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiary.java
  6. 4
      src/main/java/com/youlai/boot/mini/model/entity/MiniUserPost.java
  7. 79
      src/main/java/com/youlai/boot/mini/service/impl/UserPostServiceImpl.java

8
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;
}

23
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);
}

138
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<SysUser>()
.eq(SysUser::getId, userId)
.set(SysUser::getAvatar, defaultAvatar)
);
log.info("用户头像审核不通过已重置为默认头像, userId={}", userId);
}
}

25
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<MiniContentAuditMapper, MiniContentAudit> 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<MiniContentAuditMapper,
entity.setUpdateTime(new Date());
entity.setUpdateTimestamp(System.currentTimeMillis());
this.updateById(entity);
// 审核完成(通过/不通过)时回调业务处理器,同步更新业务实体的审核状态
if (AuditConstants.STATUS_PASSED.equals(status) || AuditConstants.STATUS_REJECTED.equals(status)) {
try {
MiniContentAudit audit = this.getById(auditId);
if (audit != null) {
if (AuditConstants.STATUS_PASSED.equals(status)) {
bizAuditStatusHandler.onAuditPassed(audit.getModuleCode(), audit.getBizId());
} else {
bizAuditStatusHandler.onAuditRejected(audit.getModuleCode(), audit.getBizId());
}
}
} catch (Exception e) {
log.error("回调业务审核状态处理器失败, auditId={}, status={}", auditId, status, e);
}
}
}
@Override

4
src/main/java/com/youlai/boot/mini/model/entity/MiniAdoptionDiary.java

@ -94,5 +94,9 @@ public class MiniAdoptionDiary implements Serializable {
@Schema(description = "逻辑删除标识(0-未删除 1-已删除)")
private Boolean deleted;
@TableField("audit_status")
@Schema(description = "审核状态:0-通过,1-审核中,2-审核未通过")
private Integer auditStatus;
}

4
src/main/java/com/youlai/boot/mini/model/entity/MiniUserPost.java

@ -90,5 +90,9 @@ public class MiniUserPost implements Serializable {
@Schema(description = "逻辑删除标识(0-未删除 1-已删除)")
private Boolean deleted;
@TableField("audit_status")
@Schema(description = "审核状态:0-通过,1-审核中,2-审核未通过")
private Integer auditStatus;
}

79
src/main/java/com/youlai/boot/mini/service/impl/UserPostServiceImpl.java

@ -12,8 +12,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.boot.admin.constant.AuditConstants;
import com.youlai.boot.admin.model.dto.AuditContentDTO;
import com.youlai.boot.admin.model.entity.MiniContentAudit;
import com.youlai.boot.admin.model.entity.MiniContentAuditConfig;
import com.youlai.boot.admin.model.entity.MiniContentAuditTask;
import com.youlai.boot.admin.service.AuditExecutorService;
import com.youlai.boot.admin.service.ContentAuditConfigService;
import com.youlai.boot.admin.service.ContentAuditService;
import com.youlai.boot.admin.service.ContentAuditTaskService;
import com.youlai.boot.common.exception.MsgException;
@ -78,6 +80,7 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
private final MiniUserPostViewMapper miniUserPostViewMapper;
private final UserMapper userMapper;
private final RedissonClient redissonClient;
private final ContentAuditConfigService contentAuditConfigService;
private final AuditExecutorService auditExecutorService;
private final ContentAuditService contentAuditService;
private final ContentAuditTaskService contentAuditTaskService;
@ -191,12 +194,31 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
return urlList;
}
/**
* 判断指定模块的审核是否已开启
*/
private boolean isAuditEnabled(String moduleCode) {
MiniContentAuditConfig config = contentAuditConfigService.getOne(
new LambdaQueryWrapper<MiniContentAuditConfig>()
.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<MiniUserPostMapper, MiniUse
post.setLikeCount(0);
post.setCommentCount(0);
post.setCollectCount(0);
post.setAuditStatus(initAuditStatus);
post.setCreateBy(userId);
post.setCreateTime(new Date(currentTimestamp));
post.setCreateTimestamp(currentTimestamp);
@ -276,6 +299,13 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
* 审核异常降级直接创建人工审核记录及对应任务确保不丢审
*/
private void createManualReviewFallback(Long postId, UserPostForm formData) {
createManualReviewFallback(postId, buildAuditContent(formData));
}
/**
* 审核异常降级通用版根据已构建的审核内容直接创建人工审核记录
*/
private void createManualReviewFallback(Long postId, AuditContentDTO auditContent) {
try {
MiniContentAudit audit = new MiniContentAudit();
audit.setUuid(UUID.randomUUID().toString());
@ -288,7 +318,6 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
audit.setCreateTimestamp(System.currentTimeMillis());
contentAuditService.save(audit);
AuditContentDTO auditContent = buildAuditContent(formData);
contentAuditTaskService.batchCreateTasks(audit.getId(), "manual",
auditContent.getTexts(), auditContent.getImages(), auditContent.getVideos());
@ -315,10 +344,24 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
post.setTitle(formData.getTitle());
post.setContent(formData.getContent());
post.setVisibility(formData.getVisibility());
post.setAuditStatus(AuditConstants.BIZ_AUDIT_STATUS_REVIEWING); // 编辑后重新审核
post.setUpdateBy(SecurityUtils.getUserId());
post.setUpdateTime(new Date(currentTimestamp));
post.setUpdateTimestamp(currentTimestamp);
updateById(post);
// 编辑后重新审核(失败或异常降级为人工审核,不阻塞主流程)
Long postId = post.getId();
try {
AuditContentDTO auditContent = buildAuditContent(formData);
Map<String, Object> 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<MiniUserPostMapper, MiniUse
}
long currentTimestamp = System.currentTimeMillis();
List<String> newImageUrls = new ArrayList<>();
List<String> newVideoUrls = new ArrayList<>();
// 处理图片
if (CollUtil.isNotEmpty(images)) {
for (MultipartFile image : images) {
@ -396,6 +442,7 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
media.setCreateTime(new Date(currentTimestamp));
media.setCreateBy(SecurityUtils.getUserId());
miniUserPostMediaMapper.insert(media);
newImageUrls.add(url);
} catch (Exception e) {
log.error("用户作品补充图片上传失败", e);
}
@ -439,12 +486,42 @@ public class UserPostServiceImpl extends ServiceImpl<MiniUserPostMapper, MiniUse
media.setThumbnailUrl(thumbnailUrl);
miniUserPostMediaMapper.insert(media);
newVideoUrls.add(url);
FileUtils.delete(videoPath);
} catch (Exception e) {
log.error("用户作品补充视频上传失败", e);
}
}
}
// 补充媒体后重新审核(失败或异常降级为人工审核,不阻塞主流程)
if (!newImageUrls.isEmpty() || !newVideoUrls.isEmpty()) {
Long postId = post.getId();
// 标记为审核中
MiniUserPost updateStatus = new MiniUserPost();
updateStatus.setId(postId);
updateStatus.setAuditStatus(AuditConstants.BIZ_AUDIT_STATUS_REVIEWING);
updateStatus.setUpdateTime(new Date());
updateStatus.setUpdateTimestamp(System.currentTimeMillis());
updateById(updateStatus);
try {
AuditContentDTO auditContent = new AuditContentDTO();
auditContent.setImages(newImageUrls);
auditContent.setVideos(newVideoUrls);
Map<String, Object> 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

Loading…
Cancel
Save