|
|
|
@ -123,6 +123,19 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
@Value("${ai.task.timeout-minutes:300}") |
|
|
|
private int taskTimeoutMinutes; |
|
|
|
|
|
|
|
//AI任务状态查询接口
|
|
|
|
@Value("${ai.status.single-image-url}") |
|
|
|
private String aiSingleImageStatusUrl; |
|
|
|
|
|
|
|
@Value("${ai.status.four-panel-url}") |
|
|
|
private String aiFourPanelStatusUrl; |
|
|
|
|
|
|
|
@Value("${ai.status.video-url}") |
|
|
|
private String aiVideoStatusUrl; |
|
|
|
|
|
|
|
@Value("${ai.status.sync-min-interval-minutes:30}") |
|
|
|
private int syncMinIntervalMinutes; |
|
|
|
|
|
|
|
//AI单图生成积分规则编码
|
|
|
|
private static final String AI_GENERATE_SINGLE_IMAGE_RULE = "AI_GENERATE_SINGLE_IMAGE"; |
|
|
|
//AI四宫格生成积分规则编码
|
|
|
|
@ -285,6 +298,9 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
|
|
|
|
aiGenerationTaskMapper.insert(task); |
|
|
|
|
|
|
|
// 立即关联用户上传的参考文件到当前任务并软删除
|
|
|
|
softDeleteUserUploads(userId, task.getId()); |
|
|
|
|
|
|
|
// 组装第三方AI接口需要的参数
|
|
|
|
Map<String, Object> aiRequest = new HashMap<>(); |
|
|
|
aiRequest.put("model", form.getModel() == null ? aiDefaultImageModel : form.getModel()); |
|
|
|
@ -373,6 +389,9 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
|
|
|
|
aiGenerationTaskMapper.insert(task); |
|
|
|
|
|
|
|
// 立即关联用户上传的参考文件到当前任务并软删除
|
|
|
|
softDeleteUserUploads(userId, task.getId()); |
|
|
|
|
|
|
|
// 组装第三方AI接口需要的参数
|
|
|
|
Map<String, Object> aiRequest = new HashMap<>(); |
|
|
|
aiRequest.put("model", form.getModel() == null ? aiDefaultImageModel : form.getModel()); |
|
|
|
@ -461,6 +480,9 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
|
|
|
|
aiGenerationTaskMapper.insert(task); |
|
|
|
|
|
|
|
// 立即关联用户上传的参考文件到当前任务并软删除
|
|
|
|
softDeleteUserUploads(userId, task.getId()); |
|
|
|
|
|
|
|
// 组装第三方接口参数
|
|
|
|
Map<String, Object> aiRequest = new HashMap<>(); |
|
|
|
aiRequest.put("model", form.getModel() == null ? aiDefaultVideoModel : form.getModel()); |
|
|
|
@ -564,18 +586,6 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
.setCreateTime(new Date()); |
|
|
|
aiTaskMediaMapper.insert(media); |
|
|
|
|
|
|
|
// 更新用户上传的参考文件:关联当前任务ID并软删除
|
|
|
|
LambdaUpdateWrapper<MiniAiTaskMedia> updateMediaWrapper = new LambdaUpdateWrapper<>(); |
|
|
|
updateMediaWrapper.eq(MiniAiTaskMedia::getMiniUserId, task.getMiniUserId()) |
|
|
|
.isNull(MiniAiTaskMedia::getTaskId) |
|
|
|
.eq(MiniAiTaskMedia::getFileSource, "user_upload") |
|
|
|
.eq(MiniAiTaskMedia::getDeleted, false) |
|
|
|
.set(MiniAiTaskMedia::getTaskId, task.getId()) |
|
|
|
.set(MiniAiTaskMedia::getDeleted, true) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTime, new Date()) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTimestamp, System.currentTimeMillis()); |
|
|
|
aiTaskMediaMapper.update(null, updateMediaWrapper); |
|
|
|
|
|
|
|
// 同步发送订阅消息通知
|
|
|
|
sendAiGenerateSuccessNotify(task.getMiniUserId(), subscribeTemplate, task.getId()); |
|
|
|
} |
|
|
|
@ -654,7 +664,7 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
media.setUuid(mediaUuid) |
|
|
|
.setTaskId(task.getId()) |
|
|
|
.setMiniUserId(task.getMiniUserId()) |
|
|
|
.setFileSource("ai_generate") |
|
|
|
.setFileSource("ai_generated") |
|
|
|
.setMediaType("image") |
|
|
|
.setSourceUrl(ossUrl) |
|
|
|
.setWidth(width) |
|
|
|
@ -665,18 +675,6 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
aiTaskMediaMapper.insert(media); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新用户上传的参考文件:关联当前任务ID并软删除
|
|
|
|
LambdaUpdateWrapper<MiniAiTaskMedia> updateMediaWrapper = new LambdaUpdateWrapper<>(); |
|
|
|
updateMediaWrapper.eq(MiniAiTaskMedia::getMiniUserId, task.getMiniUserId()) |
|
|
|
.isNull(MiniAiTaskMedia::getTaskId) |
|
|
|
.eq(MiniAiTaskMedia::getFileSource, "user_upload") |
|
|
|
.eq(MiniAiTaskMedia::getDeleted, false) |
|
|
|
.set(MiniAiTaskMedia::getTaskId, task.getId()) |
|
|
|
.set(MiniAiTaskMedia::getDeleted, true) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTime, new Date()) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTimestamp, System.currentTimeMillis()); |
|
|
|
aiTaskMediaMapper.update(null, updateMediaWrapper); |
|
|
|
|
|
|
|
// 同步发送订阅消息通知
|
|
|
|
sendAiGenerateSuccessNotify(task.getMiniUserId(), subscribeTemplate, task.getId()); |
|
|
|
} |
|
|
|
@ -770,18 +768,6 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
aiTaskMediaMapper.insert(media); |
|
|
|
} |
|
|
|
|
|
|
|
// 更新用户上传的参考文件:关联当前任务ID并软删除
|
|
|
|
LambdaUpdateWrapper<MiniAiTaskMedia> updateMediaWrapper = new LambdaUpdateWrapper<>(); |
|
|
|
updateMediaWrapper.eq(MiniAiTaskMedia::getMiniUserId, task.getMiniUserId()) |
|
|
|
.isNull(MiniAiTaskMedia::getTaskId) |
|
|
|
.eq(MiniAiTaskMedia::getFileSource, "user_upload") |
|
|
|
.eq(MiniAiTaskMedia::getDeleted, false) |
|
|
|
.set(MiniAiTaskMedia::getTaskId, task.getId()) |
|
|
|
.set(MiniAiTaskMedia::getDeleted, true) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTime, new Date()) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTimestamp, System.currentTimeMillis()); |
|
|
|
aiTaskMediaMapper.update(null, updateMediaWrapper); |
|
|
|
|
|
|
|
// 同步发送订阅消息通知
|
|
|
|
sendAiGenerateSuccessNotify(task.getMiniUserId(), subscribeTemplate, task.getId()); |
|
|
|
} |
|
|
|
@ -805,6 +791,77 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void syncTaskStatus(String taskUuid) { |
|
|
|
MiniAiGenerationTask task = getTaskByUuid(taskUuid); |
|
|
|
if (task == null) { |
|
|
|
throw new BusinessException("任务不存在"); |
|
|
|
} |
|
|
|
|
|
|
|
// 终态不允许手动同步
|
|
|
|
if (task.getStatus() != null && (task.getStatus() == 1 || task.getStatus() == 2)) { |
|
|
|
throw new BusinessException("任务已完成或已失败,无需同步"); |
|
|
|
} |
|
|
|
|
|
|
|
// 创建后需等待配置的时间才能手动同步
|
|
|
|
long elapsedMinutes = (System.currentTimeMillis() - task.getCreateTimestamp()) / 60000; |
|
|
|
if (elapsedMinutes < syncMinIntervalMinutes) { |
|
|
|
throw new BusinessException("任务创建不足" + syncMinIntervalMinutes + "分钟,请" + (syncMinIntervalMinutes - elapsedMinutes) + "分钟后再试"); |
|
|
|
} |
|
|
|
|
|
|
|
String statusUrl = buildAiStatusUrl(task); |
|
|
|
log.info("手动同步任务状态,taskUuid:{},type:{},statusUrl:{}", taskUuid, task.getType(), statusUrl); |
|
|
|
|
|
|
|
String responseBody; |
|
|
|
try { |
|
|
|
HttpResponse response = HttpRequest.get(statusUrl).timeout(10000).execute(); |
|
|
|
if (!response.isOk()) { |
|
|
|
log.error("AI状态查询返回非200,taskUuid:{},httpStatus:{}", taskUuid, response.getStatus()); |
|
|
|
throw new BusinessException("查询AI任务状态失败,HTTP状态码: " + response.getStatus()); |
|
|
|
} |
|
|
|
responseBody = response.body(); |
|
|
|
} catch (BusinessException e) { |
|
|
|
throw e; |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("调用AI状态查询接口失败,taskUuid:{}", taskUuid, e); |
|
|
|
throw new BusinessException("查询AI任务状态失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
|
|
|
|
log.info("AI状态查询响应,taskUuid:{},body:{}", taskUuid, responseBody); |
|
|
|
processAiStatusResponse(task.getType(), responseBody); |
|
|
|
} |
|
|
|
|
|
|
|
private String buildAiStatusUrl(MiniAiGenerationTask task) { |
|
|
|
switch (task.getType()) { |
|
|
|
case "img_single": |
|
|
|
return aiSingleImageStatusUrl + task.getUuid(); |
|
|
|
case "img_grid_4": |
|
|
|
return aiFourPanelStatusUrl + task.getUuid(); |
|
|
|
case "video": |
|
|
|
if (StrUtil.isBlank(task.getVideoTaskUuid())) { |
|
|
|
throw new BusinessException("视频任务尚未获取到第三方任务ID"); |
|
|
|
} |
|
|
|
return aiVideoStatusUrl + task.getVideoTaskUuid(); |
|
|
|
default: |
|
|
|
throw new BusinessException("不支持的任务类型: " + task.getType()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void processAiStatusResponse(String type, String responseBody) { |
|
|
|
switch (type) { |
|
|
|
case "img_single": |
|
|
|
handleTaskCallback(JSONUtil.toBean(responseBody, AiSingleImageCallbackForm.class)); |
|
|
|
break; |
|
|
|
case "img_grid_4": |
|
|
|
handleFourPanelCallback(JSONUtil.toBean(responseBody, AiFourPanelCallbackForm.class)); |
|
|
|
break; |
|
|
|
case "video": |
|
|
|
handleVideoTaskCallback(JSONUtil.toBean(responseBody, AiVideoCallbackVO.class)); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public MiniAiGenerationTask getTaskByUuid(String uuid) { |
|
|
|
return aiGenerationTaskMapper.selectOne(new LambdaQueryWrapper<MiniAiGenerationTask>() |
|
|
|
@ -1093,6 +1150,7 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
AiGenerationTaskVO vo = new AiGenerationTaskVO(); |
|
|
|
// vo.setId(task.getId());
|
|
|
|
vo.setUuid(task.getUuid()); |
|
|
|
vo.setVisibility(task.getVisibility()); |
|
|
|
vo.setType(task.getType()); |
|
|
|
vo.setStatus(task.getStatus()); |
|
|
|
vo.setPointsConsumed(task.getPointsConsumed()); |
|
|
|
@ -1181,6 +1239,23 @@ public class AiGenerationServiceImpl implements AiGenerationService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 将用户当前未关联任务的上传文件关联到指定任务并软删除。 |
|
|
|
* 在创建任务时调用,避免任务生成中用户仍能看到旧上传文件。 |
|
|
|
*/ |
|
|
|
private void softDeleteUserUploads(Long userId, Long taskId) { |
|
|
|
LambdaUpdateWrapper<MiniAiTaskMedia> updateWrapper = new LambdaUpdateWrapper<>(); |
|
|
|
updateWrapper.eq(MiniAiTaskMedia::getMiniUserId, userId) |
|
|
|
.isNull(MiniAiTaskMedia::getTaskId) |
|
|
|
.eq(MiniAiTaskMedia::getFileSource, "user_upload") |
|
|
|
.eq(MiniAiTaskMedia::getDeleted, false) |
|
|
|
.set(MiniAiTaskMedia::getTaskId, taskId) |
|
|
|
.set(MiniAiTaskMedia::getDeleted, true) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTime, new Date()) |
|
|
|
.set(MiniAiTaskMedia::getUpdateTimestamp, System.currentTimeMillis()); |
|
|
|
aiTaskMediaMapper.update(null, updateWrapper); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 发送AI作品完成订阅消息通知 |
|
|
|
* @param userId 接收用户ID |
|
|
|
|