diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java index 2d6b3d822..cf8076150 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java +++ b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java @@ -13,8 +13,8 @@ import lombok.Getter; public enum AiImageStatusEnum { IN_PROGRESS(10, "进行中"), - SUCCESS(20, "完成"), - FAIL(30, "失败"); + SUCCESS(20, "已完成"), + FAIL(30, "已失败"); /** * 状态 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java index bc48d9b77..3d80b845b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java @@ -7,7 +7,9 @@ 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.controller.admin.image.vo.AiImageDrawReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageRespVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdatePublicStatusReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; @@ -17,7 +19,9 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.annotation.security.PermitAll; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -88,4 +92,31 @@ public class AiImageController { return success(imageId); } + // ================ 绘图管理 ================ + + @GetMapping("/page") + @Operation(summary = "获得绘画分页") + @PreAuthorize("@ss.hasPermission('ai:image:query')") + public CommonResult> getImagePage(@Valid AiImagePageReqVO pageReqVO) { + PageResult pageResult = imageService.getImagePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); + } + + @PutMapping("/update-public-status") + @Operation(summary = "更新绘画发布状态") + @PreAuthorize("@ss.hasPermission('ai:image:update')") + public CommonResult updateImagePublicStatus(@Valid @RequestBody AiImageUpdatePublicStatusReqVO updateReqVO) { + imageService.updateImagePublicStatus(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除绘画") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('ai:image:delete')") + public CommonResult deleteImage(@RequestParam("id") Long id) { + imageService.deleteImage(id); + return success(true); + } + } \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java index 1fd1323bf..a38935ef7 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java @@ -10,7 +10,7 @@ import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; import java.util.Map; -@Schema(description = "管理后台 - 绘画 Request VO") +@Schema(description = "管理后台 - AI 绘画 Request VO") @Data public class AiImageDrawReqVO { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java new file mode 100644 index 000000000..6f6c6596f --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java @@ -0,0 +1,36 @@ +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.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - AI 绘画分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AiImagePageReqVO extends PageParam { + + @Schema(description = "用户编号", example = "28987") + private Long userId; + + @Schema(description = "平台") + private String platform; + + @Schema(description = "绘画状态", example = "1") + private Integer status; + + @Schema(description = "是否发布", example = "1") + private Boolean publicStatus; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java index 9d761a891..4e924463d 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java @@ -4,10 +4,11 @@ import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; -@Schema(description = "管理后台 - 绘画 Response VO") +@Schema(description = "管理后台 - AI 绘画 Response VO") @Data public class AiImageRespVO { @@ -47,11 +48,10 @@ public class AiImageRespVO { @Schema(description = "绘制参数") private Map options; - // TODO @fan:进度是百分比,还是一个数字哈?感觉这个可以统一成通用字段; - @Schema(description = "mj 进度") - private String progress; - @Schema(description = "mj buttons 按钮") private List buttons; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + } diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdatePublicStatusReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdatePublicStatusReqVO.java new file mode 100644 index 000000000..3d3404865 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdatePublicStatusReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.ai.controller.admin.image.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - AI 绘画修改发布状态 Request VO") +@Data +public class AiImageUpdatePublicStatusReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") + private Long id; + + @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否发布不能为空") + private Boolean publicStatus; + +} \ No newline at end of file diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java index d2b23178c..28803a051 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java @@ -5,7 +5,7 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; -@Schema(description = "管理后台 - Action(Midjourney) Request VO") +@Schema(description = "管理后台 - AI 绘图操作(Midjourney) Request VO") @Data public class AiMidjourneyActionReqVO { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java index 670c38d84..96c67acd3 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java @@ -7,7 +7,7 @@ import lombok.Data; import java.util.List; -@Schema(description = "管理后台 - 绘画生成(Midjourney) Request VO") +@Schema(description = "管理后台 - AI 绘画生成(Midjourney) Request VO") @Data public class AiMidjourneyImagineReqVO { diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java index f6212d9fd..fd6e4b398 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java @@ -4,6 +4,7 @@ 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.controller.admin.image.vo.AiImagePageReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import org.apache.ibatis.annotations.Mapper; @@ -21,6 +22,16 @@ public interface AiImageMapper extends BaseMapperX { return this.selectOne(AiImageDO::getTaskId, taskId); } + default PageResult selectPage(AiImagePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(AiImageDO::getUserId, reqVO.getUserId()) + .eqIfPresent(AiImageDO::getPlatform, reqVO.getPlatform()) + .eqIfPresent(AiImageDO::getStatus, reqVO.getStatus()) + .eqIfPresent(AiImageDO::getPublicStatus, reqVO.getPublicStatus()) + .betweenIfPresent(AiImageDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(AiImageDO::getId)); + } + default PageResult selectPage(Long userId, PageParam pageReqVO) { return selectPage(pageReqVO, new LambdaQueryWrapperX() .eq(AiImageDO::getUserId, userId) diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java index 69c3891ea..ebd8ebd6b 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java @@ -4,9 +4,12 @@ import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdatePublicStatusReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; +import jakarta.validation.Valid; /** * AI 绘图 Service 接口 @@ -49,6 +52,28 @@ public interface AiImageService { */ void deleteImageMy(Long id, Long userId); + /** + * 获得绘画分页 + * + * @param pageReqVO 分页查询 + * @return 绘画分页 + */ + PageResult getImagePage(AiImagePageReqVO pageReqVO); + + /** + * 更新绘画发布状态 + * + * @param updateReqVO 更新信息 + */ + void updateImagePublicStatus(@Valid AiImageUpdatePublicStatusReqVO updateReqVO); + + /** + * 删除绘画 + * + * @param id 编号 + */ + void deleteImage(Long id); + // ================ midjourney 专属 ================ /** diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 0ae2c3725..7f8697274 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -14,6 +14,8 @@ 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.controller.admin.image.vo.AiImageDrawReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePageReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageUpdatePublicStatusReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; @@ -134,6 +136,27 @@ public class AiImageServiceImpl implements AiImageService { imageMapper.deleteById(id); } + @Override + public PageResult getImagePage(AiImagePageReqVO pageReqVO) { + return imageMapper.selectPage(pageReqVO); + } + + @Override + public void updateImagePublicStatus(AiImageUpdatePublicStatusReqVO updateReqVO) { + // 1. 校验存在 + validateImageExists(updateReqVO.getId()); + // 2. 更新发布状态 + imageMapper.updateById(BeanUtils.toBean(updateReqVO, AiImageDO.class)); + } + + @Override + public void deleteImage(Long id) { + // 1. 校验存在 + validateImageExists(id); + // 2. 删除 + imageMapper.deleteById(id); + } + private AiImageDO validateImageExists(Long id) { AiImageDO image = imageMapper.selectById(id); if (image == null) { diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java index b2c72f7cd..5a509b6cb 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java @@ -21,7 +21,7 @@ public enum AiPlatformEnum { GEMIR ("gemir ", "gemir "), // 谷歌 STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI - MIDJOURNEY("midjourney", "midjourney"), // TODO MJ 提供的绘图,接入中 + MIDJOURNEY("Midjourney", "Midjourney"), SUNO("Suno", "Suno"), // Suno AI ; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/MidjourneyConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/MidjourneyConfig.java deleted file mode 100644 index 5b695c290..000000000 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/midjourney/MidjourneyConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.framework.ai.core.model.midjourney; - -import lombok.Data; - -/** - * Midjourney 属性 - * - * @author fansili - * @time 2024/6/5 15:02 - * @since 1.0 - */ -@Data -public class MidjourneyConfig { - - /** - * keys - */ - private String key; - /** - * 请求地址 - */ - private String url; -}