Commit 1ac1c007ad5f0128712e841c5da59568ec202ecf

Authored by cherishsince
1 parent e781129d

【解决todo】修改命名、方法返回、链式调用、显示保存、代码逻辑换货

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java
@@ -74,16 +74,18 @@ public class AiImageController { @@ -74,16 +74,18 @@ public class AiImageController {
74 @Operation(summary = "Midjourney 回调通知", description = "由 Midjourney Proxy 回调") 74 @Operation(summary = "Midjourney 回调通知", description = "由 Midjourney Proxy 回调")
75 @PostMapping("/midjourney-notify") 75 @PostMapping("/midjourney-notify")
76 @PermitAll 76 @PermitAll
77 - public CommonResult<Boolean> midjourneyNotify(@RequestBody MidjourneyNotifyReqVO notifyReqVO) {  
78 - return success(imageService.midjourneyNotify(notifyReqVO)); 77 + public void midjourneyNotify(@RequestBody MidjourneyNotifyReqVO notifyReqVO) {
  78 + imageService.midjourneyNotify(notifyReqVO);
79 } 79 }
80 80
81 @Operation(summary = "Midjourney Action", description = "例如说:放大、缩小、U1、U2 等") 81 @Operation(summary = "Midjourney Action", description = "例如说:放大、缩小、U1、U2 等")
82 @GetMapping("/midjourney/action") 82 @GetMapping("/midjourney/action")
83 - // TODO @fan:id、customerId 的 swagger 注解 83 + @Parameter(name = "id", description = "图片id", example = "1")
  84 + @Parameter(name = "customId", description = "操作id", example = "MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862")
84 public CommonResult<Boolean> midjourneyAction(@RequestParam("id") Long imageId, 85 public CommonResult<Boolean> midjourneyAction(@RequestParam("id") Long imageId,
85 @RequestParam("customId") String customId) { 86 @RequestParam("customId") String customId) {
86 - return success(imageService.midjourneyAction(getLoginUserId(), imageId, customId)); 87 + imageService.midjourneyAction(getLoginUserId(), imageId, customId);
  88 + return success(null);
87 } 89 }
88 90
89 } 91 }
90 \ No newline at end of file 92 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java
@@ -103,7 +103,7 @@ public class AiImageDO extends BaseDO { @@ -103,7 +103,7 @@ public class AiImageDO extends BaseDO {
103 private MidjourneyNotifyReqVO response; 103 private MidjourneyNotifyReqVO response;
104 104
105 /** 105 /**
106 - * mj 进度 106 + * mj 进度(10%、50%、100%)
107 */ 107 */
108 private String progress; 108 private String progress;
109 109
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageService.java
@@ -63,7 +63,7 @@ public interface AiImageService { @@ -63,7 +63,7 @@ public interface AiImageService {
63 * @param notifyReqVO 63 * @param notifyReqVO
64 * @return 64 * @return
65 */ 65 */
66 - Boolean midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO); 66 + void midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO);
67 67
68 /** 68 /**
69 * 构建 midjourney - 更新对象 69 * 构建 midjourney - 更新对象
@@ -82,5 +82,5 @@ public interface AiImageService { @@ -82,5 +82,5 @@ public interface AiImageService {
82 * @param customId 82 * @param customId
83 * @return 83 * @return
84 */ 84 */
85 - Boolean midjourneyAction(Long loginUserId, Long imageId, String customId); 85 + void midjourneyAction(Long loginUserId, Long imageId, String customId);
86 } 86 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
@@ -134,49 +134,39 @@ public class AiImageServiceImpl implements AiImageService { @@ -134,49 +134,39 @@ public class AiImageServiceImpl implements AiImageService {
134 @Override 134 @Override
135 @Transactional(rollbackFor = Exception.class) 135 @Transactional(rollbackFor = Exception.class)
136 public Long midjourneyImagine(Long userId, AiImageMidjourneyImagineReqVO req) { 136 public Long midjourneyImagine(Long userId, AiImageMidjourneyImagineReqVO req) {
137 - // TODO @fan:1 和 2 应该放在一个 1 里面。不然 = = 一个逻辑就显得有很多 1、/2、/3、/4;这么分的原因,是方便阅读的时候,容易理解。  
138 - // 1、构建 AiImageDO  
139 - // TODO @fan:1)aiImageDO 可以缩写成 image 更简洁;2)可以链式调用,把相同的放在一行里,这样更容易分组  
140 - AiImageDO aiImageDO = new AiImageDO();  
141 - aiImageDO.setUserId(userId);  
142 - aiImageDO.setPrompt(req.getPrompt());  
143 - aiImageDO.setPlatform(AiPlatformEnum.MIDJOURNEY.getPlatform());  
144 - aiImageDO.setModel(req.getModel());  
145 - aiImageDO.setWidth(req.getWidth());  
146 - aiImageDO.setHeight(req.getHeight());  
147 - aiImageDO.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());  
148 - // 2、保存 image  
149 - imageMapper.insert(aiImageDO);  
150 - // TODO @fan:3 和 2 之间,应该空一行;因为这里是开始发起请求第三方,是个单独的小块逻辑 137 + // 1、构建 AiImageDO 并 保存
  138 + AiImageDO image = new AiImageDO()
  139 + .setUserId(userId)
  140 + .setPrompt(req.getPrompt())
  141 + .setPlatform(AiPlatformEnum.MIDJOURNEY.getPlatform())
  142 + .setModel(req.getModel())
  143 + .setWidth(req.getWidth())
  144 + .setHeight(req.getHeight())
  145 + .setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
  146 + imageMapper.insert(image);
  147 +
151 // 3、调用 MidjourneyProxy 提交任务 148 // 3、调用 MidjourneyProxy 提交任务
  149 +
  150 + // 3.1、设置 midjourney 扩展参数
152 MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class); 151 MidjourneyImagineReqVO imagineReqVO = BeanUtils.toBean(req, MidjourneyImagineReqVO.class);
153 imagineReqVO.setNotifyHook(midjourneyNotifyUrl); 152 imagineReqVO.setNotifyHook(midjourneyNotifyUrl);
154 - // 4、设置 midjourney 扩展参数  
155 imagineReqVO.setState(buildParams(req.getWidth(), 153 imagineReqVO.setState(buildParams(req.getWidth(),
156 req.getHeight(), req.getVersion(), MidjourneyModelEnum.valueOfModel(req.getModel()))); 154 req.getHeight(), req.getVersion(), MidjourneyModelEnum.valueOfModel(req.getModel())));
157 - // 5、提交绘画请求 155 + // 3.2、提交绘画请求
158 // TODO @fan:5 这里,失败的情况,到底抛出异常,还是 RespVO,可以参考 OpenAI 的 API 封装 156 // TODO @fan:5 这里,失败的情况,到底抛出异常,还是 RespVO,可以参考 OpenAI 的 API 封装
159 MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO); 157 MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.imagine(imagineReqVO);
160 - // 6、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) 158 +
  159 + // 4、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误))
161 if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) { 160 if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) {
162 throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription()); 161 throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription());
163 } 162 }
164 - // TODO @fan:7 和 6 之间,应该空一行;这样,最终这个逻辑,就会有 2 个空行,3 小块逻辑:1)插入;2)调用;3)更新  
165 - // 7、构建 imageOptions 参数  
166 - // TODO @fan:1)链式调用;2)其实可以直接使用 AiImageMidjourneyImagineReqVO。不用单独一个 options 类哈。  
167 - MidjourneyImageOptions imageOptions = new MidjourneyImageOptions()  
168 - .setWidth(req.getWidth())  
169 - .setHeight(req.getHeight())  
170 - .setModel(req.getModel())  
171 - .setVersion(req.getVersion())  
172 - .setState(imagineReqVO.getState());  
173 - // 8、更新 taskId 和参数 163 + // 4.1、更新 taskId 和参数
174 imageMapper.updateById(new AiImageDO() 164 imageMapper.updateById(new AiImageDO()
175 - .setId(aiImageDO.getId()) 165 + .setId(image.getId())
176 .setTaskId(submitRespVO.getResult()) 166 .setTaskId(submitRespVO.getResult())
177 - .setOptions(BeanUtil.beanToMap(imageOptions)) 167 + .setOptions(BeanUtil.beanToMap(req))
178 ); 168 );
179 - return aiImageDO.getId(); 169 + return image.getId();
180 } 170 }
181 171
182 172
@@ -191,23 +181,21 @@ public class AiImageServiceImpl implements AiImageService { @@ -191,23 +181,21 @@ public class AiImageServiceImpl implements AiImageService {
191 imageMapper.deleteById(id); 181 imageMapper.deleteById(id);
192 } 182 }
193 183
194 - // TODO @fan:建议返回 void;然后如果不存在,就抛出异常哈;  
195 @Override 184 @Override
196 - public Boolean midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) { 185 + public void midjourneyNotify(MidjourneyNotifyReqVO notifyReqVO) {
197 // 1、根据 job id 查询关联的 image 186 // 1、根据 job id 查询关联的 image
198 AiImageDO image = imageMapper.selectByJobId(notifyReqVO.getId()); 187 AiImageDO image = imageMapper.selectByJobId(notifyReqVO.getId());
199 if (image == null) { 188 if (image == null) {
200 log.warn("midjourneyNotify 回调的 jobId 不存在! jobId: {}", notifyReqVO.getId()); 189 log.warn("midjourneyNotify 回调的 jobId 不存在! jobId: {}", notifyReqVO.getId());
201 - return false;  
202 } 190 }
203 // 2、转换状态 191 // 2、转换状态
204 AiImageDO updateImage = buildUpdateImage(image.getId(), notifyReqVO); 192 AiImageDO updateImage = buildUpdateImage(image.getId(), notifyReqVO);
205 // 3、更新 image 状态 193 // 3、更新 image 状态
206 - return imageMapper.updateById(updateImage) > 0; 194 + imageMapper.updateById(updateImage);
207 } 195 }
208 196
209 public AiImageDO buildUpdateImage(Long imageId, MidjourneyNotifyReqVO notifyReqVO) { 197 public AiImageDO buildUpdateImage(Long imageId, MidjourneyNotifyReqVO notifyReqVO) {
210 - // 2、转换状态 198 + // 1、转换状态
211 String imageStatus = null; 199 String imageStatus = null;
212 MidjourneyTaskStatusEnum taskStatusEnum = MidjourneyTaskStatusEnum.valueOf(notifyReqVO.getStatus()); 200 MidjourneyTaskStatusEnum taskStatusEnum = MidjourneyTaskStatusEnum.valueOf(notifyReqVO.getStatus());
213 if (MidjourneyTaskStatusEnum.SUCCESS == taskStatusEnum) { 201 if (MidjourneyTaskStatusEnum.SUCCESS == taskStatusEnum) {
@@ -215,7 +203,8 @@ public class AiImageServiceImpl implements AiImageService { @@ -215,7 +203,8 @@ public class AiImageServiceImpl implements AiImageService {
215 } else if (MidjourneyTaskStatusEnum.FAILURE == taskStatusEnum) { 203 } else if (MidjourneyTaskStatusEnum.FAILURE == taskStatusEnum) {
216 imageStatus = AiImageStatusEnum.FAIL.getStatus(); 204 imageStatus = AiImageStatusEnum.FAIL.getStatus();
217 } 205 }
218 - // 3、上传图片 206 +
  207 + // 2、上传图片
219 String filePath = null; 208 String filePath = null;
220 if (!StrUtil.isBlank(notifyReqVO.getImageUrl())) { 209 if (!StrUtil.isBlank(notifyReqVO.getImageUrl())) {
221 try { 210 try {
@@ -224,7 +213,8 @@ public class AiImageServiceImpl implements AiImageService { @@ -224,7 +213,8 @@ public class AiImageServiceImpl implements AiImageService {
224 log.warn("midjourneyNotify 图片上传失败! {} 异常:{}", notifyReqVO.getImageUrl(), ExceptionUtil.getMessage(e)); 213 log.warn("midjourneyNotify 图片上传失败! {} 异常:{}", notifyReqVO.getImageUrl(), ExceptionUtil.getMessage(e));
225 } 214 }
226 } 215 }
227 - // 4、更新 image 状态 216 +
  217 + // 3、更新 image 状态
228 return new AiImageDO() 218 return new AiImageDO()
229 .setId(imageId) 219 .setId(imageId)
230 .setStatus(imageStatus) 220 .setStatus(imageStatus)
@@ -235,55 +225,60 @@ public class AiImageServiceImpl implements AiImageService { @@ -235,55 +225,60 @@ public class AiImageServiceImpl implements AiImageService {
235 .setErrorMessage(notifyReqVO.getFailReason()); 225 .setErrorMessage(notifyReqVO.getFailReason());
236 } 226 }
237 227
238 - // TODO @fan:1)不用返回 Boolean  
239 @Override 228 @Override
240 - @Transactional(rollbackFor = Exception.class) // TODO @fan:只操作一个 db,不用事务哈;  
241 - public Boolean midjourneyAction(Long loginUserId, Long imageId, String customId) {  
242 - // TODO @fan:1)1 和 2,可以写成 1.1、1.2,都是在做校验;2)validateCustomId 可以直接抛出 AI_IMAGE_CUSTOM_ID_NOT_EXISTS 异常;一般情况下,validateXXX 都是失败抛出异常,isXXXValid 返回 true、false 229 + public void midjourneyAction(Long loginUserId, Long imageId, String customId) {
243 // 1、检查 image 230 // 1、检查 image
244 - // TODO @fan:1)aiImageDO 缩写成 image;  
245 - AiImageDO aiImageDO = validateImageExists(imageId); 231 + AiImageDO image = validateImageExists(imageId);
246 // 2、检查 customId 232 // 2、检查 customId
247 - if (!validateCustomId(customId, aiImageDO.getButtons())) {  
248 - throw exception(AI_IMAGE_CUSTOM_ID_NOT_EXISTS);  
249 - }  
250 - // TODO @fan:2 和 3 之间,空一行 233 + validateCustomId(customId, image.getButtons());
  234 +
251 // 3、调用 midjourney proxy 235 // 3、调用 midjourney proxy
252 MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.action( 236 MidjourneySubmitRespVO submitRespVO = midjourneyProxyClient.action(
253 new MidjourneyActionReqVO() 237 new MidjourneyActionReqVO()
254 .setCustomId(customId) 238 .setCustomId(customId)
255 - .setTaskId(aiImageDO.getTaskId()) 239 + .setTaskId(image.getTaskId())
256 .setNotifyHook(midjourneyNotifyUrl) 240 .setNotifyHook(midjourneyNotifyUrl)
257 ); 241 );
258 - // 6、保存任务 id (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误)) 242 + // 4、检查错误 code (状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误))
259 if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) { 243 if (!MidjourneySubmitCodeEnum.SUCCESS_CODES.contains(submitRespVO.getCode())) {
260 throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription()); 244 throw exception(AI_IMAGE_MIDJOURNEY_SUBMIT_FAIL, submitRespVO.getDescription());
261 } 245 }
262 - // TODO 6 和 4 之间空一行;  
263 - // 4、新增 image 记录  
264 - AiImageDO newImage = BeanUtils.toBean(aiImageDO, AiImageDO.class);  
265 - // TODO @fan:最好不要 copy 属性。因为未来如果加属性,可能会导致额外 copy 了;最好是 new 赋值下,显示声明。  
266 - // 4.1、重置参数 246 +
  247 + // 5、新增 image 记录(根据 image 新增一个)
  248 + AiImageDO newImage = new AiImageDO();
267 newImage.setId(null); 249 newImage.setId(null);
  250 + newImage.setUserId(image.getUserId());
  251 + newImage.setPrompt(image.getPrompt());
  252 +
  253 + newImage.setPlatform(image.getPlatform());
  254 + newImage.setModel(image.getModel());
  255 + newImage.setWidth(image.getWidth());
  256 + newImage.setHeight(image.getHeight());
  257 +
268 newImage.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus()); 258 newImage.setStatus(AiImageStatusEnum.IN_PROGRESS.getStatus());
  259 + newImage.setPublicStatus(image.getPublicStatus());
  260 +
269 newImage.setPicUrl(null); 261 newImage.setPicUrl(null);
270 - newImage.setResponse(null);  
271 newImage.setProgress(null); 262 newImage.setProgress(null);
  263 + newImage.setButtons(null);
  264 + newImage.setOptions(image.getOptions());
  265 + newImage.setResponse(image.getResponse());
272 newImage.setTaskId(submitRespVO.getResult()); 266 newImage.setTaskId(submitRespVO.getResult());
273 newImage.setErrorMessage(null); 267 newImage.setErrorMessage(null);
274 - newImage.setButtons(null);  
275 - // 4.2、保存数据库  
276 imageMapper.insert(newImage); 268 imageMapper.insert(newImage);
277 - return Boolean.TRUE;  
278 } 269 }
279 270
280 - private static boolean validateCustomId(String customId, List<MidjourneyNotifyReqVO.Button> buttons) { 271 + private static void validateCustomId(String customId, List<MidjourneyNotifyReqVO.Button> buttons) {
  272 + boolean isTrue = false;
281 for (MidjourneyNotifyReqVO.Button button : buttons) { 273 for (MidjourneyNotifyReqVO.Button button : buttons) {
282 if (button.getCustomId().equals(customId)) { 274 if (button.getCustomId().equals(customId)) {
283 - return true; 275 + isTrue = true;
  276 + break;
284 } 277 }
285 } 278 }
286 - return false; 279 + if (isTrue) {
  280 + throw exception(AI_IMAGE_CUSTOM_ID_NOT_EXISTS);
  281 + }
287 } 282 }
288 283
289 private AiImageDO validateImageExists(Long id) { 284 private AiImageDO validateImageExists(Long id) {
@@ -304,6 +299,7 @@ public class AiImageServiceImpl implements AiImageService { @@ -304,6 +299,7 @@ public class AiImageServiceImpl implements AiImageService {
304 } 299 }
305 300
306 // TODO @fan:这个是不是应该放在 MJ API 的封装里面搞哈? 301 // TODO @fan:这个是不是应该放在 MJ API 的封装里面搞哈?
  302 +
307 /** 303 /**
308 * 构建 Midjourney 自定义参数 304 * 构建 Midjourney 自定义参数
309 * 305 *