mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	【代码评审】AI:AI 绘图的逻辑
This commit is contained in:
		| @@ -14,6 +14,7 @@ import lombok.Getter; | |||||||
| @Getter | @Getter | ||||||
| public enum AiImageStatusEnum { | public enum AiImageStatusEnum { | ||||||
|  |  | ||||||
|  |     // TODO @fan:改成 10 生成中;20 成功;30 失败;其它可以去掉噢 | ||||||
|     SUBMIT("submit", "提交任务"), |     SUBMIT("submit", "提交任务"), | ||||||
|     WAITING("waiting", "等待"), |     WAITING("waiting", "等待"), | ||||||
|     IN_PROGRESS("in_progress", "进行中"), |     IN_PROGRESS("in_progress", "进行中"), | ||||||
| @@ -22,6 +23,7 @@ public enum AiImageStatusEnum { | |||||||
|  |  | ||||||
|     ; |     ; | ||||||
|  |  | ||||||
|  |     // TODO @fan:final 一下 | ||||||
|     private String status; |     private String status; | ||||||
|  |  | ||||||
|     private String name; |     private String name; | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*; | |||||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||||
|  |  | ||||||
| // TODO @芋艿:整理接口定义 | // TODO @芋艿:整理接口定义 | ||||||
|  | // TODO @fan:参考 AiChatMessageController 改下 swagger 注解、注释 | ||||||
| /** | /** | ||||||
|  * ai作图 |  * ai作图 | ||||||
|  * |  * | ||||||
| @@ -28,20 +29,28 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |||||||
| @AllArgsConstructor | @AllArgsConstructor | ||||||
| public class AiImageController { | public class AiImageController { | ||||||
|  |  | ||||||
|  |     // TODO @fan:使用 @Resource 注入哈;然后 aiImageService => imageService; | ||||||
|     private final AiImageService aiImageService; |     private final AiImageService aiImageService; | ||||||
|  |  | ||||||
|  |     // TODO @fan:分页列表,建议是 getImagePage,包括接口 path 也建议改下哈; | ||||||
|  |     // TODO @fan:@ModelAttribute 不需要哈; | ||||||
|  |     // TODO @fan:这个要不搞成 my-page?因为是我的哈 | ||||||
|     @Operation(summary = "获取image列表", description = "dall3、midjourney") |     @Operation(summary = "获取image列表", description = "dall3、midjourney") | ||||||
|     @GetMapping("/list") |     @GetMapping("/list") | ||||||
|     public CommonResult<PageResult<AiImageListRespVO>> list(@Validated @ModelAttribute AiImageListReqVO req) { |     public CommonResult<PageResult<AiImageListRespVO>> list(@Validated @ModelAttribute AiImageListReqVO req) { | ||||||
|  |         // TODO @fan:import static,这样只要 success() 就行啦 | ||||||
|         return CommonResult.success(aiImageService.list(req)); |         return CommonResult.success(aiImageService.list(req)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:搞成 get-my? | ||||||
|  |     // TODO @fan:方法名改下哈。 | ||||||
|     @Operation(summary = "获取image信息", description = "获取image信息") |     @Operation(summary = "获取image信息", description = "获取image信息") | ||||||
|     @GetMapping("/get") |     @GetMapping("/get") | ||||||
|     public CommonResult<AiImageListRespVO> get(@RequestParam("id") Long id) { |     public CommonResult<AiImageListRespVO> get(@RequestParam("id") Long id) { | ||||||
|         return CommonResult.success(aiImageService.get(id)); |         return CommonResult.success(aiImageService.get(id)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:建议把 dallDrawing、midjourney 融合成一个 draw 接口,异步绘制;然后返回一个 id 给前端;前端通过 get 接口轮询,直到获取到生成成功 | ||||||
|     @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") |     @Operation(summary = "dall2/dall3绘画", description = "openAi dall3是付费的!") | ||||||
|     @PostMapping("/dall") |     @PostMapping("/dall") | ||||||
|     public AiImageDallRespVO dallDrawing(@Validated @RequestBody AiImageDallReqVO req) { |     public AiImageDallRespVO dallDrawing(@Validated @RequestBody AiImageDallReqVO req) { | ||||||
| @@ -62,6 +71,7 @@ public class AiImageController { | |||||||
|         return success(null); |         return success(null); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:要不先不要 midjourneyOperate、cancelMidjourney 接口哈 | ||||||
|     @Operation(summary = "取消 midjourney 绘画", description = "取消 midjourney 绘画") |     @Operation(summary = "取消 midjourney 绘画", description = "取消 midjourney 绘画") | ||||||
|     @PostMapping("/cancel-midjourney") |     @PostMapping("/cancel-midjourney") | ||||||
|     public CommonResult<Void> cancelMidjourney(@RequestParam("id") Long id) { |     public CommonResult<Void> cancelMidjourney(@RequestParam("id") Long id) { | ||||||
| @@ -69,10 +79,12 @@ public class AiImageController { | |||||||
|         return success(null); |         return success(null); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:delete-my?需要校验是不是当前人哈 | ||||||
|     @Operation(summary = "删除绘画记录", description = "") |     @Operation(summary = "删除绘画记录", description = "") | ||||||
|     @DeleteMapping("/delete") |     @DeleteMapping("/delete") | ||||||
|     public CommonResult<Void> delete(@RequestParam("id") Long id) { |     public CommonResult<Void> delete(@RequestParam("id") Long id) { | ||||||
|         aiImageService.delete(id); |         aiImageService.delete(id); | ||||||
|         return success(null); |         return success(null); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ import org.mapstruct.factory.Mappers; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | // TODO @fan:convert 可以考虑去掉,使用 BeanUtils.copy 替代 | ||||||
| /** | /** | ||||||
|  * ai image convert |  * ai image convert | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -29,6 +29,8 @@ public class AiImageDO extends BaseDO { | |||||||
|     @Schema(description = "提示词") |     @Schema(description = "提示词") | ||||||
|     private String prompt; |     private String prompt; | ||||||
|  |  | ||||||
|  |     // TODO @fan:要加一个平台字段;platform;因为一个平台,会有多种 model 模型; | ||||||
|  |  | ||||||
|     @Schema(description = "模型 dall2/dall3、MJ、NIJI") |     @Schema(description = "模型 dall2/dall3、MJ、NIJI") | ||||||
|     private String model; |     private String model; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ import java.util.concurrent.LinkedBlockingQueue; | |||||||
| import java.util.concurrent.ThreadPoolExecutor; | import java.util.concurrent.ThreadPoolExecutor; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
|  | // TODO @fan:注释优化下哈 | ||||||
| /** | /** | ||||||
|  * ai 作图 |  * ai 作图 | ||||||
|  * |  * | ||||||
| @@ -51,14 +52,23 @@ import java.util.concurrent.TimeUnit; | |||||||
| @Slf4j | @Slf4j | ||||||
| public class AiImageServiceImpl implements AiImageService { | public class AiImageServiceImpl implements AiImageService { | ||||||
|  |  | ||||||
|  |     // TODO @fan:使用 @Resource 注入 | ||||||
|  |  | ||||||
|  |     // TODO @fan:imageMapper | ||||||
|     private final AiImageMapper aiImageMapper; |     private final AiImageMapper aiImageMapper; | ||||||
|  |  | ||||||
|     private final FileApi fileApi; |     private final FileApi fileApi; | ||||||
|  |  | ||||||
|     private final OpenAiImageClient openAiImageClient; |     private final OpenAiImageClient openAiImageClient; | ||||||
|  |  | ||||||
|     private final MidjourneyWebSocketStarter midjourneyWebSocketStarter; |     private final MidjourneyWebSocketStarter midjourneyWebSocketStarter; | ||||||
|  |  | ||||||
|     private final MidjourneyInteractionsApi midjourneyInteractionsApi; |     private final MidjourneyInteractionsApi midjourneyInteractionsApi; | ||||||
|  |  | ||||||
|     private static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor( |     private static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor( | ||||||
|             3, 5, 1, TimeUnit.HOURS, new LinkedBlockingQueue<>(32)); |             3, 5, 1, TimeUnit.HOURS, new LinkedBlockingQueue<>(32)); | ||||||
|  |  | ||||||
|  |     // TODO @fan:接 mj proxy | ||||||
|     @PostConstruct |     @PostConstruct | ||||||
|     public void startMidjourney() { |     public void startMidjourney() { | ||||||
|         log.info("midjourney web socket starter..."); |         log.info("midjourney web socket starter..."); | ||||||
| @@ -75,6 +85,7 @@ public class AiImageServiceImpl implements AiImageService { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:1)分页,然后 loginUser 通过参数传入,这样 Service 无状态;2)另外,返回 DO;VO 的翻译,交给 Controller;3:还有,使用 BeanUtils 替代哈 | ||||||
|     @Override |     @Override | ||||||
|     public PageResult<AiImageListRespVO> list(AiImageListReqVO req) { |     public PageResult<AiImageListRespVO> list(AiImageListReqVO req) { | ||||||
|         // 获取登录用户 |         // 获取登录用户 | ||||||
| @@ -92,29 +103,33 @@ public class AiImageServiceImpl implements AiImageService { | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:1)返回 DO;VO 的翻译,交给 Controller;2)还有,使用 BeanUtils 替代哈 | ||||||
|     @Override |     @Override | ||||||
|     public AiImageListRespVO get(Long id) { |     public AiImageListRespVO get(Long id) { | ||||||
|         AiImageDO aiImageDO = aiImageMapper.selectById(id); |         AiImageDO aiImageDO = aiImageMapper.selectById(id); | ||||||
|         return AiImageConvert.INSTANCE.convertAiImageListRespVO(aiImageDO); |         return AiImageConvert.INSTANCE.convertAiImageListRespVO(aiImageDO); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:1)loginUserId 通过 controller 传入; | ||||||
|     @Override |     @Override | ||||||
|     public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) { |     public AiImageDallRespVO dallDrawing(AiImageDallReqVO req) { | ||||||
|         Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); |         Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); | ||||||
|         // 保存数据库 |         // 保存数据库 | ||||||
|  |         // TODO @fan:1)使用 BeanUtils;2)使用链式调用哈; | ||||||
|         AiImageDO aiImageDO = AiImageConvert.INSTANCE.convertAiImageDO(req); |         AiImageDO aiImageDO = AiImageConvert.INSTANCE.convertAiImageDO(req); | ||||||
|         aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); |         aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); | ||||||
|         aiImageDO.setUserId(loginUserId); |         aiImageDO.setUserId(loginUserId); | ||||||
|         aiImageMapper.insert(aiImageDO); |         aiImageMapper.insert(aiImageDO); | ||||||
|         // 异步执行 |         // 异步执行 | ||||||
|  |         // TODO @fan:使用 @Async 去调用哈; | ||||||
|         EXECUTOR.execute(() -> { |         EXECUTOR.execute(() -> { | ||||||
|             try { |             try { | ||||||
|  |  | ||||||
|                 // 获取 model |                 // 获取 model | ||||||
|                 OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); |                 OpenAiImageModelEnum openAiImageModelEnum = OpenAiImageModelEnum.valueOfModel(req.getModel()); | ||||||
|                 OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); |                 OpenAiImageStyleEnum openAiImageStyleEnum = OpenAiImageStyleEnum.valueOfStyle(req.getStyle()); | ||||||
|  |  | ||||||
|                 // 转换openai 参数 |                 // 转换openai 参数 | ||||||
|  |                 // TODO @fan:需要考虑,不同平台,参数不同; | ||||||
|                 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); |                 OpenAiImageOptions openAiImageOptions = new OpenAiImageOptions(); | ||||||
|                 openAiImageOptions.setModel(openAiImageModelEnum.getModel()); |                 openAiImageOptions.setModel(openAiImageModelEnum.getModel()); | ||||||
|                 openAiImageOptions.setStyle(openAiImageStyleEnum.getStyle()); |                 openAiImageOptions.setStyle(openAiImageStyleEnum.getStyle()); | ||||||
| @@ -125,23 +140,16 @@ public class AiImageServiceImpl implements AiImageService { | |||||||
|                 // 图片保存到服务器 |                 // 图片保存到服务器 | ||||||
|                 String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl())); |                 String filePath = fileApi.createFile(HttpUtil.downloadBytes(imageGeneration.getOutput().getUrl())); | ||||||
|                 // 更新数据库 |                 // 更新数据库 | ||||||
|                 aiImageMapper.updateById( |                 aiImageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.COMPLETE.getStatus()) | ||||||
|                         new AiImageDO() |                         .setPicUrl(filePath).setOriginalPicUrl(imageGeneration.getOutput().getUrl()) | ||||||
|                                 .setId(aiImageDO.getId()) |  | ||||||
|                                 .setStatus(AiImageStatusEnum.COMPLETE.getStatus()) |  | ||||||
|                                 .setPicUrl(filePath) |  | ||||||
|                                 .setOriginalPicUrl(imageGeneration.getOutput().getUrl()) |  | ||||||
|                 ); |                 ); | ||||||
|             } catch (AiException aiException) { |             } catch (AiException aiException) { | ||||||
|                 // 更新错误信息 |                 // TODO @fan:错误日志,也打印下哈;因为 aiException.getMessage() 比较精简; | ||||||
|                 aiImageMapper.updateById( |                 aiImageMapper.updateById(new AiImageDO().setId(aiImageDO.getId()).setStatus(AiImageStatusEnum.FAIL.getStatus()) | ||||||
|                         new AiImageDO() |                         .setErrorMessage(aiException.getMessage())); | ||||||
|                                 .setId(aiImageDO.getId()) |  | ||||||
|                                 .setStatus(AiImageStatusEnum.FAIL.getStatus()) |  | ||||||
|                                 .setErrorMessage(aiException.getMessage()) |  | ||||||
|                 ); |  | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |         // TODO @fan:返回 id 就可以啦 | ||||||
|         // 转换 AiImageDallDrawingRespVO |         // 转换 AiImageDallDrawingRespVO | ||||||
|         return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); |         return AiImageConvert.INSTANCE.convertAiImageDallDrawingRespVO(aiImageDO); | ||||||
|     } |     } | ||||||
| @@ -188,6 +196,7 @@ public class AiImageServiceImpl implements AiImageService { | |||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // TODO @fan:1)需要校验存在;2)需要校验属于我; | ||||||
|     @Override |     @Override | ||||||
|     public void delete(Long id) { |     public void delete(Long id) { | ||||||
|         // 校验记录是否存在 |         // 校验记录是否存在 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV