You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
8.7 KiB

package com.youlai.boot.mini.controller;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.common.annotation.RepeatSubmit;
import com.youlai.boot.common.enums.ActionTypeEnum;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.framework.security.util.SecurityUtils;
import com.youlai.boot.mini.model.form.*;
import com.youlai.boot.mini.model.vo.AiVideoCallbackVO;
import com.youlai.boot.mini.service.AiGenerationService;
import com.youlai.boot.mini.service.WxSubscribeService;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Pattern;
import org.springframework.security.access.prepost.PreAuthorize;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.boot.mini.model.query.AiTaskMediaQuery;
import com.youlai.boot.mini.model.vo.AiGenerationTaskVO;
import cn.hutool.core.util.StrUtil;
import java.util.List;
import com.youlai.boot.mini.model.vo.UserUploadMediaVO;
@Tag(name = "AI生成相关接口")
@RestController
@RequestMapping("/api/v1/mini/ai/generation")
@RequiredArgsConstructor
@Valid
public class AiGenerationController {
private final AiGenerationService aiGenerationService;
private final WxSubscribeService wxSubscribeService;
@Operation(summary = "上传AI生成参考文件")
@PostMapping(value = "/upload/reference", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@RepeatSubmit
@Log(module = LogModuleEnum.AI_TASK_MEDIA, value = ActionTypeEnum.INSERT)
public Result<List<String>> uploadReferenceFile(
@RequestParam(name = "images", required = false) List<MultipartFile> images,
@RequestParam(name = "videos", required = false) List<MultipartFile> videos
) {
Long userId = SecurityUtils.getUserId();
List<String> urlList = aiGenerationService.uploadReferenceFile(images, videos, userId);
return Result.success(urlList);
}
@Operation(summary = "提交单图生成任务")
@PostMapping("/generate-single-image")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.INSERT)
public Result<String> generateSingleImage(@Valid @RequestBody AiSingleImageGenerateForm form) {
Long userId = SecurityUtils.getUserId();
String taskUuid = aiGenerationService.createAndGenerateImage(form, userId);
return Result.success(taskUuid);
}
@Operation(summary = "单图任务回调接口")
@PostMapping("/single-image/task/callback")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.UPDATE)
public Result<Boolean> singleImageTaskCallback(@Valid @RequestBody AiSingleImageCallbackForm form) {
boolean success = aiGenerationService.handleTaskCallback(form);
return Result.success(success);
}
@Operation(summary = "提交四宫格漫画生成任务")
@PostMapping("/generate-four-panel")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.INSERT)
public Result<String> generateFourPanelImage(@Valid @RequestBody AiFourPanelGenerateForm form) {
Long userId = SecurityUtils.getUserId();
String taskUuid = aiGenerationService.createAndGenerateFourPanel(form, userId);
return Result.success(taskUuid);
}
@Operation(summary = "四宫格漫画任务回调接口")
@PostMapping("/four-panel/task/callback")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.UPDATE)
public Result<Boolean> fourPanelTaskCallback(@Valid @RequestBody AiFourPanelCallbackForm form) {
boolean success = aiGenerationService.handleFourPanelCallback(form);
return Result.success(success);
}
@Operation(summary = "提交视频生成任务")
@PostMapping("/generate-video")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.INSERT)
public Result<String> generateVideo(@Valid @RequestBody AiVideoGenerateForm form) {
Long userId = SecurityUtils.getUserId();
String taskUuid = aiGenerationService.createAndGenerateVideo(form, userId);
return Result.success(taskUuid);
}
@Operation(summary = "视频任务回调接口")
@PostMapping("/video/task/callback")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.UPDATE)
public Result<Boolean> videoTaskCallback(@Valid @RequestBody AiVideoCallbackVO vo) {
boolean success = aiGenerationService.handleVideoTaskCallback(vo);
return Result.success(success);
}
@Operation(summary = "上报微信订阅消息授权状态")
@PostMapping("/subscribe/auth/report")
@Log(module = LogModuleEnum.USER_SUBSCRIBE, value = ActionTypeEnum.UPDATE)
public Result<Void> reportSubscribeAuth(@Valid @RequestBody WxSubscribeAuthForm form) {
form.setUserId(SecurityUtils.getUserId());
wxSubscribeService.reportAuth(form);
return Result.success();
}
@Hidden
@Operation(summary = "发送微信订阅消息")
@PostMapping("/subscribe/send")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.INSERT)
public Result<Boolean> sendSubscribeMessage(@Valid @RequestBody WxSubscribeSendForm form) {
form.setUserId(SecurityUtils.getUserId());
Boolean result = wxSubscribeService.sendMessage(form);
return Result.success(result);
}
@Operation(summary = "查询当前用户最近上传的图片视频")
@GetMapping("/my/recent-upload")
public Result<List<UserUploadMediaVO>> getMyRecentUpload() {
Long userId = SecurityUtils.getUserId();
List<UserUploadMediaVO> voList = aiGenerationService.getRecentUploadVO(userId);
return Result.success(voList);
}
@Operation(summary = "删除用户上传的图片/视频")
@DeleteMapping("/my/upload/delete")
@Log(module = LogModuleEnum.AI_TASK_MEDIA, value = ActionTypeEnum.DELETE)
public Result<Boolean> deleteMyUpload(@RequestParam String uuid) {
Long userId = SecurityUtils.getUserId();
boolean success = aiGenerationService.deleteUploadMedia(userId, uuid);
return Result.success(success);
}
@Operation(summary = "查询我的AI生成任务历史")
@GetMapping("/my/history")
@Log(module = LogModuleEnum.AI_TASK_MEDIA, value = ActionTypeEnum.LIST)
public Result<IPage<AiGenerationTaskVO>> getMyAiGenerateHistory(@Valid AiTaskMediaQuery query) {
Long userId = SecurityUtils.getUserId();
IPage<AiGenerationTaskVO> result = aiGenerationService.getMyAiGenerateHistory(query, userId);
return Result.success(result);
}
@Operation(summary = "设置微信订阅消息跳转版本")
@PostMapping("/subscribe/mini-program-state/set")
@Log(module = LogModuleEnum.AI_GENERATION_TASK, value = ActionTypeEnum.UPDATE)
public Result<Void> setMiniProgramState(
@Schema(description = "跳转版本:developer=开发版 trial=体验版 formal=正式版,为空时删除配置")
@Pattern(regexp = "^(developer|trial|formal|)$", message = "参数只能是developer/trial/formal或为空")
@RequestParam(required = false) String miniProgramState
) {
aiGenerationService.setMiniProgramState(miniProgramState);
return Result.success();
}
//需要在三个回调接口中控制状态,更新其他状态; 更新状态时需要判断 当前状态已是成功或失败时不能再更新状态,当状态是失败时需要退还补偿积分;
// mini_point_rule积分规则表,每个回调回退的积分是对应的规则扣减积分的负数值;mini_point_record积分记录表;mini_point_account用户积分账户
// 当外部服务挂掉,不回调我的接口时,需要根据时间段判断,如果超过一定时间未回调,则更新状态为失败,并退还积分;
//TODO 现在 用户生成内容时,需要增加一个参数,同意或不同意公开生成的作品内容
//TODO mini 中增加 查询 用户公开生成作品的接口,考虑设计一下查询规则 满足平台前中后期运营需求
//TODO admin 中 后台管理中增加 查询用户生成任务历史的接口
//TODO admin 中 编辑用户生成作品历史接口
//TODO admin 中 增加 手动查询生成任务接口,手动跳转生成失败任务,或做个接口给用户手动刷新查看,需要注意状态流转,只有超时未完成任务可出现刷新按钮
}