【代码优化】AI:Image 图片的列表、详情等接口
This commit is contained in:
parent
c1f2e49066
commit
458f5acdf0
|
@ -1,13 +1,14 @@
|
|||
package cn.iocoder.yudao.module.ai.controller.admin.image;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageMyRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageRespVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
|
||||
import cn.iocoder.yudao.module.ai.service.image.AiImageService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
@ -21,35 +22,30 @@ import org.springframework.web.bind.annotation.*;
|
|||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - Ai 绘画")
|
||||
@Tag(name = "管理后台 - AI 绘画")
|
||||
@RestController
|
||||
@RequestMapping("/ai/image")
|
||||
@Slf4j
|
||||
public class AiImageController {
|
||||
|
||||
@Resource
|
||||
private AiImageService aiImageService;
|
||||
private AiImageService imageService;
|
||||
|
||||
@Operation(summary = "获取【我的】绘图分页")
|
||||
@GetMapping("/my-page")
|
||||
public CommonResult<PageResult<AiImagePageMyRespVO>> getImagePageMy(@Validated AiImageListReqVO req) {
|
||||
// 转换 resp
|
||||
PageResult<AiImageDO> pageResult = aiImageService.getImagePageMy(getLoginUserId(), req);
|
||||
// 转换 PageResult<AiImageListRespVO> 返回
|
||||
PageResult<AiImagePageMyRespVO> result = new PageResult<>();
|
||||
result.setTotal(pageResult.getTotal());
|
||||
result.setList(BeanUtils.toBean(pageResult.getList(), AiImagePageMyRespVO.class));
|
||||
return success(result);
|
||||
public CommonResult<PageResult<AiImageRespVO>> getImagePageMy(@Validated PageParam pageReqVO) {
|
||||
PageResult<AiImageDO> pageResult = imageService.getImagePageMy(getLoginUserId(), pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, AiImageRespVO.class));
|
||||
}
|
||||
|
||||
// TODO @fan:类似 /my-page 的建议
|
||||
@Operation(summary = "获取【我的】绘图记录", description = "...")
|
||||
@Operation(summary = "获取【我的】绘图记录")
|
||||
@GetMapping("/get-my")
|
||||
public CommonResult<AiImagePageMyRespVO> getMy(@RequestParam("id") Long id) {
|
||||
// 获取 image 信息
|
||||
AiImageDO imageDO = aiImageService.getMy(id);
|
||||
// 转 resp 并返回
|
||||
return CommonResult.success(BeanUtils.toBean(imageDO, AiImagePageMyRespVO.class));
|
||||
public CommonResult<AiImageRespVO> getImageMy(@RequestParam("id") Long id) {
|
||||
AiImageDO image = imageService.getImage(id);
|
||||
if (image == null || ObjUtil.notEqual(getLoginUserId(), image.getUserId())) {
|
||||
return success(null);
|
||||
}
|
||||
return success(BeanUtils.toBean(image, AiImageRespVO.class));
|
||||
}
|
||||
|
||||
// TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功
|
||||
|
@ -58,14 +54,15 @@ public class AiImageController {
|
|||
@Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!")
|
||||
@PostMapping("/dall")
|
||||
public CommonResult<Long> dall(@Validated @RequestBody AiImageDallReqVO req) {
|
||||
return success(aiImageService.dall(getLoginUserId(), req));
|
||||
return success(imageService.dall(getLoginUserId(), req));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除【我的】绘画记录")
|
||||
@DeleteMapping("/delete-id-my")
|
||||
@DeleteMapping("/delete-my")
|
||||
@Parameter(name = "id", required = true, description = "绘画编号", example = "1024")
|
||||
public CommonResult<Boolean> deleteIdMy(@RequestParam("id") Long id) {
|
||||
return success(aiImageService.deleteIdMy(id, getLoginUserId()));
|
||||
public CommonResult<Boolean> deleteImageMy(@RequestParam("id") Long id) {
|
||||
imageService.deleteImageMy(id, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// ================ midjourney 接口
|
||||
|
@ -73,12 +70,14 @@ public class AiImageController {
|
|||
@Operation(summary = "midjourney-imagine 绘画", description = "...")
|
||||
@PostMapping("/midjourney/imagine")
|
||||
public CommonResult<Long> midjourneyImagine(@Validated @RequestBody AiImageMidjourneyImagineReqVO req) {
|
||||
return success(aiImageService.midjourneyImagine(getLoginUserId(), req));
|
||||
return success(imageService.midjourneyImagine(getLoginUserId(), req));
|
||||
}
|
||||
|
||||
// TODO @fan:可以考虑,复用 AiImageDallRespVO,统一成 AIImageRespVO
|
||||
@Operation(summary = "midjourney proxy - 回调通知")
|
||||
@RequestMapping("/midjourney-notify")
|
||||
public CommonResult<Boolean> midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) {
|
||||
return success(aiImageService.midjourneyNotify(getLoginUserId(), notifyReqVO));
|
||||
return success(imageService.midjourneyNotify(getLoginUserId(), notifyReqVO));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package cn.iocoder.yudao.module.ai.controller.admin.image.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* AI Image 我的图片列表 req
|
||||
*
|
||||
* @author fansili
|
||||
* @time 2024/4/28 17:42
|
||||
* @since 1.0
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AiImageListReqVO extends PageParam {
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package cn.iocoder.yudao.module.ai.controller.admin.image.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* midjourney
|
||||
*
|
||||
* @author fansili
|
||||
* @time 2024/4/28 17:42
|
||||
* @since 1.0
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AiImageMidjourneyRes {
|
||||
}
|
|
@ -1,23 +1,13 @@
|
|||
package cn.iocoder.yudao.module.ai.controller.admin.image.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
// TODO @fan:可以考虑,复用 AiImageDallRespVO,统一成 AIImageRespVO
|
||||
/**
|
||||
* midjourney req
|
||||
*
|
||||
* @author fansili
|
||||
* @time 2024/4/28 17:42
|
||||
* @since 1.0
|
||||
*/
|
||||
// TODO @芋艿:完善 swagger 注解
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AiImagePageMyRespVO extends PageParam {
|
||||
public class AiImageRespVO {
|
||||
|
||||
@Schema(description = "id编号", example = "1")
|
||||
private Long id;
|
|
@ -1,5 +1,7 @@
|
|||
package cn.iocoder.yudao.module.ai.dal.mysql.image;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
|
||||
|
@ -35,4 +37,10 @@ public interface AiImageMapper extends BaseMapperX<AiImageDO> {
|
|||
return this.selectOne(new LambdaQueryWrapperX<AiImageDO>().eq(AiImageDO::getJobId, id));
|
||||
}
|
||||
|
||||
default PageResult<AiImageDO> selectPage(Long userId, PageParam pageReqVO) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<AiImageDO>()
|
||||
.eq(AiImageDO::getUserId, userId)
|
||||
.orderByDesc(AiImageDO::getId));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,38 +1,35 @@
|
|||
package cn.iocoder.yudao.module.ai.service.image;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
|
||||
|
||||
/**
|
||||
* ai 作图
|
||||
* AI 绘图 Service 接口
|
||||
*
|
||||
* @author fansili
|
||||
* @time 2024/4/25 15:50
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface AiImageService {
|
||||
|
||||
/**
|
||||
* ai绘画 - 列表
|
||||
* 获取【我的】绘图分页
|
||||
*
|
||||
* @param loginUserId
|
||||
* @param req
|
||||
* @return
|
||||
* @param userId 用户编号
|
||||
* @param pageReqVO 分页条件
|
||||
* @return 绘图分页
|
||||
*/
|
||||
PageResult<AiImageDO> getImagePageMy(Long loginUserId, AiImageListReqVO req);
|
||||
PageResult<AiImageDO> getImagePageMy(Long userId, PageParam pageReqVO);
|
||||
|
||||
/**
|
||||
* 获取 - image 信息
|
||||
* 获得绘图记录
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
* @param id 绘图编号
|
||||
* @return 绘图记录
|
||||
*/
|
||||
AiImageDO getMy(Long id);
|
||||
AiImageDO getImage(Long id);
|
||||
|
||||
/**
|
||||
* ai绘画 - dall2/dall3 绘画
|
||||
|
@ -52,19 +49,12 @@ public interface AiImageService {
|
|||
Long midjourneyImagine(Long loginUserId, AiImageMidjourneyImagineReqVO req);
|
||||
|
||||
/**
|
||||
* midjourney 操作(u1、u2、放大、换一批...)
|
||||
* 删除【我的】绘画记录
|
||||
*
|
||||
* @param req
|
||||
* @param id 绘画编号
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
void midjourneyOperate(AiImageMidjourneyOperateReqVO req);
|
||||
|
||||
/**
|
||||
* 删除 - image 记录
|
||||
*
|
||||
* @param id
|
||||
* @param loginUserId
|
||||
*/
|
||||
Boolean deleteIdMy(Long id, Long loginUserId);
|
||||
void deleteImageMy(Long id, Long userId);
|
||||
|
||||
/**
|
||||
* midjourney proxy - 回调通知
|
||||
|
|
|
@ -2,17 +2,17 @@ package cn.iocoder.yudao.module.ai.service.image;
|
|||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageModelEnum;
|
||||
import cn.iocoder.yudao.framework.ai.core.enums.OpenAiImageStyleEnum;
|
||||
import cn.iocoder.yudao.framework.ai.core.exception.AiException;
|
||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.ai.AiCommonConstants;
|
||||
import cn.iocoder.yudao.module.ai.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.ai.client.MidjourneyProxyClient;
|
||||
import cn.iocoder.yudao.module.ai.client.enums.MidjourneyModelEnum;
|
||||
import cn.iocoder.yudao.module.ai.client.enums.MidjourneySubmitCodeEnum;
|
||||
|
@ -21,9 +21,7 @@ import cn.iocoder.yudao.module.ai.client.vo.MidjourneyImagineReqVO;
|
|||
import cn.iocoder.yudao.module.ai.client.vo.MidjourneyNotifyReqVO;
|
||||
import cn.iocoder.yudao.module.ai.client.vo.MidjourneySubmitRespVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDallReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageListReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyImagineReqVO;
|
||||
import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageMidjourneyOperateReqVO;
|
||||
import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO;
|
||||
import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper;
|
||||
import cn.iocoder.yudao.module.ai.enums.AiImagePublicStatusEnum;
|
||||
|
@ -46,12 +44,12 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
|
||||
import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.AI_IMAGE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* AI 绘画(接入 dall2/dall3、midjourney)
|
||||
* AI 绘画 Service 实现类
|
||||
*
|
||||
* @author fansili
|
||||
* @time 2024/4/25 15:51
|
||||
* @since 1.0
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
|
@ -59,10 +57,13 @@ public class AiImageServiceImpl implements AiImageService {
|
|||
|
||||
@Resource
|
||||
private AiImageMapper imageMapper;
|
||||
|
||||
@Resource
|
||||
private FileApi fileApi;
|
||||
|
||||
@Resource
|
||||
private OpenAiImageClient openAiImageClient;
|
||||
|
||||
@Autowired
|
||||
private MidjourneyProxyClient midjourneyProxyClient;
|
||||
|
||||
|
@ -70,16 +71,12 @@ public class AiImageServiceImpl implements AiImageService {
|
|||
private String midjourneyNotifyUrl;
|
||||
|
||||
@Override
|
||||
public PageResult<AiImageDO> getImagePageMy(Long loginUserId, AiImageListReqVO req) {
|
||||
// 查询当前用户下所有的绘画记录
|
||||
return imageMapper.selectPage(req,
|
||||
new LambdaQueryWrapperX<AiImageDO>()
|
||||
.eq(AiImageDO::getUserId, loginUserId)
|
||||
.orderByDesc(AiImageDO::getId));
|
||||
public PageResult<AiImageDO> getImagePageMy(Long userId, PageParam pageReqVO) {
|
||||
return imageMapper.selectPage(userId, pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiImageDO getMy(Long id) {
|
||||
public AiImageDO getImage(Long id) {
|
||||
return imageMapper.selectById(id);
|
||||
}
|
||||
|
||||
|
@ -95,7 +92,7 @@ public class AiImageServiceImpl implements AiImageService {
|
|||
.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
|
||||
imageMapper.insert(aiImageDO);
|
||||
// 异步执行
|
||||
doDall(aiImageDO, req);
|
||||
getSelf().doDall(aiImageDO, req);
|
||||
// 转换 AiImageDallDrawingRespVO
|
||||
return aiImageDO.getId();
|
||||
}
|
||||
|
@ -185,42 +182,15 @@ public class AiImageServiceImpl implements AiImageService {
|
|||
return aiImageDO.getId();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void midjourneyOperate(AiImageMidjourneyOperateReqVO req) {
|
||||
// // 校验是否存在
|
||||
// AiImageDO aiImageDO = validateExists(req.getId());
|
||||
// // 获取 midjourneyOperations
|
||||
// List<AiImageMidjourneyOperationsVO> midjourneyOperations = getMidjourneyOperations(aiImageDO);
|
||||
// // 校验 OperateId 是否存在
|
||||
// AiImageMidjourneyOperationsVO midjourneyOperationsVO = validateMidjourneyOperationsExists(midjourneyOperations, req.getOperateId());
|
||||
// // 校验 messageId
|
||||
// validateMessageId(aiImageDO.getMjNonceId(), req.getMessageId());
|
||||
// // 获取 mjOperationName
|
||||
// String mjOperationName = midjourneyOperationsVO.getLabel();
|
||||
// // 保存一个 image 任务记录
|
||||
// // todo
|
||||
//// doSave(aiImageDO.getPrompt(), aiImageDO.getSize(), aiImageDO.getModel(),
|
||||
//// null, null, AiImageStatusEnum.SUBMIT, null,
|
||||
//// req.getMessageId(), req.getOperateId(), mjOperationName);
|
||||
// // 提交操作
|
||||
// midjourneyInteractionsApi.reRoll(
|
||||
// new ReRollReq()
|
||||
// .setCustomId(req.getOperateId())
|
||||
// .setMessageId(req.getMessageId())
|
||||
// );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteIdMy(Long id, Long userId) {
|
||||
// 校验是否存在,并获取 image
|
||||
AiImageDO image = validateExists(id);
|
||||
// 是否属于当前用户
|
||||
if (!image.getUserId().equals(userId)) {
|
||||
throw exception(ErrorCodeConstants.AI_IMAGE_NOT_EXISTS);
|
||||
public void deleteImageMy(Long id, Long userId) {
|
||||
// 1. 校验是否存在
|
||||
AiImageDO image = validateImageExists(id);
|
||||
if (ObjUtil.notEqual(image.getUserId(), userId)) {
|
||||
throw exception(AI_IMAGE_NOT_EXISTS);
|
||||
}
|
||||
// 删除记录
|
||||
return imageMapper.deleteById(id) > 0;
|
||||
imageMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -255,11 +225,21 @@ public class AiImageServiceImpl implements AiImageService {
|
|||
return true;
|
||||
}
|
||||
|
||||
private AiImageDO validateExists(Long id) {
|
||||
AiImageDO aiImageDO = imageMapper.selectById(id);
|
||||
if (aiImageDO == null) {
|
||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MIDJOURNEY_IMAGINE_FAIL);
|
||||
private AiImageDO validateImageExists(Long id) {
|
||||
AiImageDO image = imageMapper.selectById(id);
|
||||
if (image == null) {
|
||||
throw exception(AI_IMAGE_NOT_EXISTS);
|
||||
}
|
||||
return aiImageDO;
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得自身的代理对象,解决 AOP 生效问题
|
||||
*
|
||||
* @return 自己
|
||||
*/
|
||||
private AiImageServiceImpl getSelf() {
|
||||
return SpringUtil.getBean(getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue