|
|
|
@ -10,6 +10,15 @@ import com.baomidou.mybatisplus.core.metadata.IPage; |
|
|
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker; |
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
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.constant.CommonConstants; |
|
|
|
import com.youlai.boot.common.exception.MsgException; |
|
|
|
import com.youlai.boot.common.result.Result; |
|
|
|
@ -116,10 +125,93 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
|
|
|
|
private final MiniStrayAnimalConverter miniStrayAnimalConverter; |
|
|
|
|
|
|
|
private final ContentAuditConfigService contentAuditConfigService; |
|
|
|
private final AuditExecutorService auditExecutorService; |
|
|
|
private final ContentAuditService contentAuditService; |
|
|
|
private final ContentAuditTaskService contentAuditTaskService; |
|
|
|
|
|
|
|
public String getDefaultCatCoverHost() { |
|
|
|
return "https://" + bucketName + "." + endpoint; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 判断指定模块的审核是否已开启 |
|
|
|
*/ |
|
|
|
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()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从表单数据构建审核内容DTO |
|
|
|
*/ |
|
|
|
private AuditContentDTO buildAuditContent(StrayAnimalForm formData) { |
|
|
|
AuditContentDTO content = new AuditContentDTO(); |
|
|
|
|
|
|
|
List<String> texts = new ArrayList<>(); |
|
|
|
if (formData.getTitle() != null) { |
|
|
|
texts.add(formData.getTitle()); |
|
|
|
} |
|
|
|
if (formData.getContent() != null) { |
|
|
|
texts.add(formData.getContent()); |
|
|
|
} |
|
|
|
content.setTexts(texts); |
|
|
|
|
|
|
|
List<String> images = new ArrayList<>(); |
|
|
|
List<String> videos = new ArrayList<>(); |
|
|
|
if (formData.getMediaUrlList() != null) { |
|
|
|
for (String url : formData.getMediaUrlList()) { |
|
|
|
String lowerUrl = url.toLowerCase(); |
|
|
|
if (lowerUrl.matches(".*\\.(mp4|mov|avi|wmv|flv|mkv|webm)(\\?.*)?$")) { |
|
|
|
videos.add(url); |
|
|
|
} else { |
|
|
|
images.add(url); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
content.setImages(images); |
|
|
|
content.setVideos(videos); |
|
|
|
|
|
|
|
return content; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 审核异常降级:直接创建人工审核记录及对应任务 |
|
|
|
*/ |
|
|
|
private void createManualReviewFallback(Long animalId, StrayAnimalForm formData) { |
|
|
|
createManualReviewFallback(animalId, buildAuditContent(formData)); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 审核异常降级(通用版):根据已构建的审核内容直接创建人工审核记录 |
|
|
|
*/ |
|
|
|
private void createManualReviewFallback(Long animalId, AuditContentDTO auditContent) { |
|
|
|
MiniContentAudit audit = new MiniContentAudit(); |
|
|
|
audit.setUuid(UUID.randomUUID().toString()); |
|
|
|
audit.setModuleCode("animal_note"); |
|
|
|
audit.setBizId(animalId); |
|
|
|
audit.setAuditType("manual"); |
|
|
|
audit.setStatus(AuditConstants.STATUS_MANUAL_REVIEW); |
|
|
|
audit.setCreateBy(SecurityUtils.getUserId()); |
|
|
|
audit.setCreateTime(new Date()); |
|
|
|
audit.setCreateTimestamp(System.currentTimeMillis()); |
|
|
|
contentAuditService.save(audit); |
|
|
|
|
|
|
|
contentAuditTaskService.batchCreateTasks(audit.getId(), "manual", |
|
|
|
auditContent.getTexts(), auditContent.getImages(), auditContent.getVideos()); |
|
|
|
|
|
|
|
contentAuditTaskService.lambdaUpdate() |
|
|
|
.eq(MiniContentAuditTask::getContentAuditId, audit.getId()) |
|
|
|
.set(MiniContentAuditTask::getStatus, AuditConstants.STATUS_MANUAL_REVIEW) |
|
|
|
.update(); |
|
|
|
|
|
|
|
log.info("降级人工审核记录已创建, animalId={}, auditId={}", animalId, audit.getId()); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<String> saveFile(List<MultipartFile> images, List<MultipartFile> videos) { |
|
|
|
@ -213,19 +305,36 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
// 1. 参数校验
|
|
|
|
// validateInput(images, videos);
|
|
|
|
|
|
|
|
// 2. 保存流浪动物基本信息
|
|
|
|
MiniStrayAnimal miniStrayAnimal = saveAnimalInfo(formData); |
|
|
|
// 2. 查询审核配置,决定初始审核状态
|
|
|
|
boolean auditEnabled = isAuditEnabled("animal_note"); |
|
|
|
Integer initAuditStatus = auditEnabled |
|
|
|
? AuditConstants.BIZ_AUDIT_STATUS_REVIEWING |
|
|
|
: AuditConstants.BIZ_AUDIT_STATUS_PASSED; |
|
|
|
|
|
|
|
// 3. 保存流浪动物基本信息(含审核状态)
|
|
|
|
MiniStrayAnimal miniStrayAnimal = saveAnimalInfo(formData, initAuditStatus); |
|
|
|
|
|
|
|
// 3. 保存笔记信息
|
|
|
|
// 4. 保存笔记信息
|
|
|
|
MiniStrayAnimalNote note = saveNoteInfo(formData, miniStrayAnimal); |
|
|
|
|
|
|
|
// 4. 处理并保存媒体文件
|
|
|
|
// 5. 处理并保存媒体文件
|
|
|
|
// saveMediaFiles(note, images, videos, miniStrayAnimal.getCreateTimestamp());
|
|
|
|
saveMediaFiles(note, formData); |
|
|
|
// 5. 积分
|
|
|
|
// 6. 积分
|
|
|
|
pointRecordService.giveRegisterAnimalReward(miniStrayAnimal.getMiniUserId(), miniStrayAnimal.getId()); |
|
|
|
|
|
|
|
// 6. 提交审核
|
|
|
|
// 7. 提交审核(审核在独立事务中运行,失败降级为人工审核)
|
|
|
|
Long animalId = miniStrayAnimal.getId(); |
|
|
|
try { |
|
|
|
AuditContentDTO auditContent = buildAuditContent(formData); |
|
|
|
Map<String, Object> auditResult = auditExecutorService.executeAudit("animal_note", animalId, auditContent, AuditConstants.TRIGGER_CREATE); |
|
|
|
if (auditResult != null) { |
|
|
|
log.info("流浪动物审核任务已创建, animalId={}, auditResult={}", animalId, auditResult); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("创建流浪动物审核任务失败, 降级为人工审核, animalId={}", animalId, e); |
|
|
|
createManualReviewFallback(animalId, formData); |
|
|
|
} |
|
|
|
|
|
|
|
SaveStrayAnimalVO vo = new SaveStrayAnimalVO(); |
|
|
|
vo.setAnimalUuid(miniStrayAnimal.getUuid()); |
|
|
|
@ -243,7 +352,10 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void saveMediaFiles(MiniStrayAnimalNote note, List<MultipartFile> images, List<MultipartFile> videos, long currentTimestamp) { |
|
|
|
private Map<String, List<String>> saveMediaFiles(MiniStrayAnimalNote note, List<MultipartFile> images, List<MultipartFile> videos, long currentTimestamp) { |
|
|
|
List<String> imageUrls = new ArrayList<>(); |
|
|
|
List<String> videoUrls = new ArrayList<>(); |
|
|
|
|
|
|
|
// 处理图片
|
|
|
|
if (images != null) { |
|
|
|
for (MultipartFile image : images) { |
|
|
|
@ -267,6 +379,9 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
miniStrayAnimalNoteMedia.setCreateBy(note.getMiniUserId()); |
|
|
|
|
|
|
|
int result = miniStrayAnimalNoteMediaMapper.insert(miniStrayAnimalNoteMedia); |
|
|
|
if (result > 0) { |
|
|
|
imageUrls.add(url); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("image upload failed", e); |
|
|
|
} |
|
|
|
@ -309,6 +424,7 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
miniStrayAnimalNoteMedia.setThumbnailUrl(thumbnailUrl); |
|
|
|
|
|
|
|
miniStrayAnimalNoteMediaMapper.insert(miniStrayAnimalNoteMedia); |
|
|
|
videoUrls.add(url); |
|
|
|
|
|
|
|
FileUtils.delete(videoPath); |
|
|
|
|
|
|
|
@ -317,6 +433,11 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Map<String, List<String>> result = new HashMap<>(); |
|
|
|
result.put("imageUrls", imageUrls); |
|
|
|
result.put("videoUrls", videoUrls); |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
private MiniStrayAnimalNote saveNoteInfo(StrayAnimalForm formData, MiniStrayAnimal miniStrayAnimal) { |
|
|
|
@ -335,13 +456,14 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
return note; |
|
|
|
} |
|
|
|
|
|
|
|
private MiniStrayAnimal saveAnimalInfo(StrayAnimalForm formData) { |
|
|
|
private MiniStrayAnimal saveAnimalInfo(StrayAnimalForm formData, Integer auditStatus) { |
|
|
|
|
|
|
|
long currentTimeUnix = System.currentTimeMillis(); |
|
|
|
MiniStrayAnimal entity = miniStrayAnimalConverter.toEntity(formData); |
|
|
|
|
|
|
|
entity.setMiniUserId(SecurityUtils.getUserId()); |
|
|
|
entity.setUuid(UUID.randomUUID().toString()); |
|
|
|
entity.setAuditStatus(auditStatus); |
|
|
|
entity.setCreateTimestamp(currentTimeUnix); |
|
|
|
entity.setCreateTime(new Date(currentTimeUnix)); |
|
|
|
entity.setCreateBy(SecurityUtils.getUserId()); |
|
|
|
@ -416,8 +538,24 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
updateNoteInfo(miniStrayAnimalNote, formData, currentTimestamp); |
|
|
|
// 3. 处理并保存媒体文件
|
|
|
|
saveMediaFiles(miniStrayAnimalNote, formData); |
|
|
|
// 4. 提交审核
|
|
|
|
|
|
|
|
// 4. 提交审核(审核在独立事务中运行,失败降级为人工审核)
|
|
|
|
animal.setAuditStatus(AuditConstants.BIZ_AUDIT_STATUS_REVIEWING); |
|
|
|
animal.setUpdateTime(new Date(currentTimestamp)); |
|
|
|
animal.setUpdateTimestamp(currentTimestamp); |
|
|
|
miniStrayAnimalMapper.updateById(animal); |
|
|
|
|
|
|
|
Long animalId = animal.getId(); |
|
|
|
try { |
|
|
|
AuditContentDTO auditContent = buildAuditContent(formData); |
|
|
|
Map<String, Object> auditResult = auditExecutorService.executeAudit("animal_note", animalId, auditContent, AuditConstants.TRIGGER_CREATE); |
|
|
|
if (auditResult != null) { |
|
|
|
log.info("流浪动物编辑审核任务已创建, animalId={}, auditResult={}", animalId, auditResult); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("创建流浪动物编辑审核任务失败, 降级为人工审核, animalId={}", animalId, e); |
|
|
|
createManualReviewFallback(animalId, formData); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private MiniStrayAnimal getValidAnimal(String animalUuid) { |
|
|
|
@ -527,6 +665,7 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void saveMediaSource(String noteUuid, List<MultipartFile> images, List<MultipartFile> videos) { |
|
|
|
if ((images == null || images.isEmpty()) && (videos == null || videos.isEmpty())) { |
|
|
|
throw new MsgException("需要上传媒体资源"); |
|
|
|
@ -562,8 +701,34 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
saveMediaFiles(note, images, videos, System.currentTimeMillis()); |
|
|
|
Map<String, List<String>> urlMap = saveMediaFiles(note, images, videos, System.currentTimeMillis()); |
|
|
|
List<String> newImageUrls = urlMap.getOrDefault("imageUrls", Collections.emptyList()); |
|
|
|
List<String> newVideoUrls = urlMap.getOrDefault("videoUrls", Collections.emptyList()); |
|
|
|
|
|
|
|
// 补充媒体后重新审核(审核在独立事务中运行,失败降级为人工审核)
|
|
|
|
if (!newImageUrls.isEmpty() || !newVideoUrls.isEmpty()) { |
|
|
|
// 标记为审核中
|
|
|
|
miniStrayAnimal.setAuditStatus(AuditConstants.BIZ_AUDIT_STATUS_REVIEWING); |
|
|
|
miniStrayAnimal.setUpdateTime(new Date()); |
|
|
|
miniStrayAnimal.setUpdateTimestamp(System.currentTimeMillis()); |
|
|
|
miniStrayAnimalMapper.updateById(miniStrayAnimal); |
|
|
|
|
|
|
|
try { |
|
|
|
AuditContentDTO auditContent = new AuditContentDTO(); |
|
|
|
auditContent.setImages(newImageUrls); |
|
|
|
auditContent.setVideos(newVideoUrls); |
|
|
|
Map<String, Object> auditResult = auditExecutorService.executeAudit("animal_note", animalId, auditContent, AuditConstants.TRIGGER_CREATE); |
|
|
|
if (auditResult != null) { |
|
|
|
log.info("流浪动物补充媒体审核任务已创建, animalId={}, auditResult={}", animalId, auditResult); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("创建流浪动物补充媒体审核任务失败, 降级为人工审核, animalId={}", animalId, e); |
|
|
|
AuditContentDTO fallbackContent = new AuditContentDTO(); |
|
|
|
fallbackContent.setImages(newImageUrls); |
|
|
|
fallbackContent.setVideos(newVideoUrls); |
|
|
|
createManualReviewFallback(animalId, fallbackContent); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
|