Commit acf68b1cec62da862210dae1fd180c15c71fcc12

Authored by YunaiV
1 parent 1db3b867

【代码评审】AI:PPT API 的接入

yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/wenduoduo/api/WddPptApi.java
... ... @@ -24,11 +24,11 @@ import java.util.Objects;
24 24 import java.util.function.Function;
25 25 import java.util.function.Predicate;
26 26  
  27 +// TODO @新:要不改成 WenDuoDuoPptApi
27 28 /**
28 29 * 文多多 API
29   - * <p>
30   - * <p>
31   - * * 对接文多多:<a href="https://docmee.cn/open-platform/api">PPT 生成 API</a>
  30 + *
  31 + * @see <a href="https://docmee.cn/open-platform/api">PPT 生成 API</a>
32 32 *
33 33 * @author xiaoxin
34 34 */
... ... @@ -49,14 +49,15 @@ public class WddPptApi {
49 49 sink.error(new IllegalStateException("[wdd-api] 调用失败!"));
50 50 });
51 51  
  52 + // TODO @新:是不是不用 baseUrl 哈
52 53 public WddPptApi(String baseUrl) {
53 54 this.webClient = WebClient.builder()
54 55 .baseUrl(baseUrl)
  56 + // TODO @新:建议,token 作为 defaultHeader
55 57 .defaultHeaders((headers) -> headers.setContentType(MediaType.APPLICATION_JSON))
56 58 .build();
57 59 }
58 60  
59   -
60 61 /**
61 62 * 创建 token
62 63 *
... ... @@ -81,7 +82,7 @@ public class WddPptApi {
81 82 .block();
82 83 }
83 84  
84   -
  85 + // TODO @xin:是不是给个 API 连接,这样 type、content、files 都不用写注释太细了
85 86 /**
86 87 * 创建任务
87 88 *
... ... @@ -122,7 +123,6 @@ public class WddPptApi {
122 123 formData.add("file", file.getResource());
123 124 }
124 125 }
125   -
126 126 return this.webClient.post()
127 127 .uri("/api/ppt/v2/createTask")
128 128 .header("token", token)
... ... @@ -162,7 +162,7 @@ public class WddPptApi {
162 162 }
163 163  
164 164 /**
165   - * 分页查询PPT模板
  165 + * 分页查询 PPT 模板
166 166 *
167 167 * @param token 令牌
168 168 * @param request 请求体
... ... @@ -214,7 +214,7 @@ public class WddPptApi {
214 214 }
215 215  
216 216 /**
217   - * 生成PPT
  217 + * 生成 PPT
218 218 *
219 219 * @return PPT信息
220 220 */
... ... @@ -243,9 +243,11 @@ public class WddPptApi {
243 243 String uid,
244 244 Integer limit
245 245 ) {
  246 +
246 247 public CreateTokenRequest(String apiKey) {
247 248 this(apiKey, null, null);
248 249 }
  250 +
249 251 }
250 252  
251 253 /**
... ... @@ -256,8 +258,7 @@ public class WddPptApi {
256 258 Integer code,
257 259 String message,
258 260 Map<String, Object> data
259   - ) {
260   - }
  261 + ) { }
261 262  
262 263 /**
263 264 * 创建任务
... ... @@ -267,8 +268,7 @@ public class WddPptApi {
267 268 Integer type,
268 269 String content,
269 270 List<MultipartFile> files
270   - ) {
271   - }
  271 + ) { }
272 272  
273 273 /**
274 274 * 生成大纲内容请求
... ... @@ -281,8 +281,7 @@ public class WddPptApi {
281 281 String audience,
282 282 String lang,
283 283 String prompt
284   - ) {
285   - }
  284 + ) { }
286 285  
287 286 /**
288 287 * 修改大纲内容请求
... ... @@ -292,21 +291,20 @@ public class WddPptApi {
292 291 String id,
293 292 String markdown,
294 293 String question
295   - ) {
296   - }
  294 + ) { }
297 295  
298 296 /**
299   - * 生成PPT请求
  297 + * 生成 PPT 请求
300 298 */
  299 + // TODO @新:要不按照 PptCreateRequest 这样的风格
301 300 @JsonInclude(value = JsonInclude.Include.NON_NULL)
302 301 public record CreatePptRequest(
303 302 String id,
304 303 String templateId,
305 304 String markdown
306   - ) {
307   - }
308   -
  305 + ) { }
309 306  
  307 + // TODO @新:要不写下类注释
310 308 @JsonInclude(value = JsonInclude.Include.NON_NULL)
311 309 public record PptInfo(
312 310 String id,
... ... @@ -325,36 +323,35 @@ public class WddPptApi {
325 323 LocalDateTime createTime,
326 324 String createUser,
327 325 String updateUser
328   - ) {
329   - }
330   -
  326 + ) { }
331 327  
  328 + // TODO @新:要不写下类注释
332 329 @JsonInclude(value = JsonInclude.Include.NON_NULL)
333 330 public record TemplateQueryRequest(
334 331 int page,
335 332 int size,
336 333 Filter filters
337 334 ) {
  335 +
338 336 @JsonInclude(value = JsonInclude.Include.NON_NULL)
339 337 public record Filter(
340 338 int type,
341 339 String category,
342 340 String style,
343 341 String themeColor
344   - ) {
345   - }
346   - }
  342 + ) { }
347 343  
  344 + }
348 345  
  346 + // TODO @新:要不写下类注释
349 347 @JsonInclude(value = JsonInclude.Include.NON_NULL)
350 348 public record PagePptTemplateInfo(
351 349 List<PptTemplateInfo> data,
352 350 String total
353   - ) {
354   -
355   - }
  351 + ) {}
356 352  
357 353  
  354 + // TODO @新:要不写下类注释
358 355 @JsonInclude(value = JsonInclude.Include.NON_NULL)
359 356 public record PptTemplateInfo(
360 357 String id,
... ... @@ -383,7 +380,6 @@ public class WddPptApi {
383 380 LocalDateTime createTime,
384 381 String createUser,
385 382 String updateUser
386   - ) {
387   - }
  383 + ) { }
388 384  
389 385 }
390 386 \ No newline at end of file
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xunfei/api/XunfeiPptApi.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/api/XunfeiPptApi.java
1   -package cn.iocoder.yudao.framework.ai.core.model.xunfei.api;
  1 +package cn.iocoder.yudao.framework.ai.core.model.xinghuo.api;
2 2  
3 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 4 import com.fasterxml.jackson.annotation.JsonInclude;
... ... @@ -28,10 +28,11 @@ import java.util.Map;
28 28 import java.util.function.Function;
29 29 import java.util.function.Predicate;
30 30  
  31 +// TODO @新:要不改成 XunFeiPptApi
31 32 /**
32   - * 讯飞智能PPT生成 API
33   - * <p>
34   - * 对接讯飞:<a href="https://www.xfyun.cn/doc/spark/PPTv2.html">智能 PPT 生成 API</a>
  33 + * 讯飞智能 PPT 生成 API
  34 + *
  35 + * @see <a href="https://www.xfyun.cn/doc/spark/PPTv2.html">智能 PPT 生成 API</a>
35 36 *
36 37 * @author xiaoxin
37 38 */
... ... @@ -52,7 +53,9 @@ public class XunfeiPptApi {
52 53 sink.error(new IllegalStateException("[xunfei-ppt-api] 调用失败!"));
53 54 });
54 55  
  56 + // TODO @新:是不是不用 baseUrl 哈
55 57 public XunfeiPptApi(String baseUrl, String appId, String apiSecret) {
  58 + // TODO @新:建议,增加 defaultheaders,例如说 appid 之类的;或者每个请求,通过 headers customer 处理。
56 59 this.webClient = WebClient.builder()
57 60 .baseUrl(baseUrl)
58 61 .build();
... ... @@ -82,6 +85,7 @@ public class XunfeiPptApi {
82 85 */
83 86 private String generateSignature(String appId, String apiSecret, long timestamp) {
84 87 try {
  88 + // TODO @新:使用 hutool 简化
85 89 String auth = md5(appId + timestamp);
86 90 return hmacSHA1Encrypt(auth, apiSecret);
87 91 } catch (NoSuchAlgorithmException | InvalidKeyException e) {
... ... @@ -120,7 +124,7 @@ public class XunfeiPptApi {
120 124 }
121 125  
122 126 /**
123   - * 获取PPT模板列表
  127 + * 获取 PPT 模板列表
124 128 *
125 129 * @param style 风格,如"商务"
126 130 * @param pageSize 每页数量
... ... @@ -130,8 +134,8 @@ public class XunfeiPptApi {
130 134 SignatureInfo signInfo = getSignature();
131 135 Map<String, Object> requestBody = new HashMap<>();
132 136 requestBody.put("style", style);
133   - requestBody.put("pageSize", pageSize != null ? pageSize.toString() : "10");
134   -
  137 + // TODO @新:可以使用 ObjUtil.defaultIfNull
  138 + requestBody.put("pageSize", pageSize != null ? pageSize : 10);
135 139 return this.webClient.post()
136 140 .uri("/template/list")
137 141 .header("appId", signInfo.appId)
... ... @@ -155,7 +159,6 @@ public class XunfeiPptApi {
155 159 SignatureInfo signInfo = getSignature();
156 160 MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
157 161 formData.add("query", query);
158   -
159 162 return this.webClient.post()
160 163 .uri("/createOutline")
161 164 .header("appId", signInfo.appId)
... ... @@ -171,7 +174,7 @@ public class XunfeiPptApi {
171 174  
172 175  
173 176 /**
174   - * 直接创建PPT(简化版 - 通过文本)
  177 + * 直接创建 PPT(简化版 - 通过文本)
175 178 *
176 179 * @param query 查询文本
177 180 * @return 创建响应
... ... @@ -184,7 +187,7 @@ public class XunfeiPptApi {
184 187 }
185 188  
186 189 /**
187   - * 直接创建PPT(简化版 - 通过文件)
  190 + * 直接创建 PPT(简化版 - 通过文件)
188 191 *
189 192 * @param file 文件
190 193 * @param fileName 文件名
... ... @@ -192,14 +195,12 @@ public class XunfeiPptApi {
192 195 */
193 196 public CreateResponse create(MultipartFile file, String fileName) {
194 197 CreatePptRequest request = CreatePptRequest.builder()
195   - .file(file)
196   - .fileName(fileName)
197   - .build();
  198 + .file(file).fileName(fileName).build();
198 199 return create(request);
199 200 }
200 201  
201 202 /**
202   - * 直接创建PPT(完整版)
  203 + * 直接创建 PPT(完整版)
203 204 *
204 205 * @param request 请求参数
205 206 * @return 创建响应
... ... @@ -207,7 +208,6 @@ public class XunfeiPptApi {
207 208 public CreateResponse create(CreatePptRequest request) {
208 209 SignatureInfo signInfo = getSignature();
209 210 MultiValueMap<String, Object> formData = buildCreateFormData(request);
210   -
211 211 return this.webClient.post()
212 212 .uri("/create")
213 213 .header("appId", signInfo.appId)
... ... @@ -223,7 +223,7 @@ public class XunfeiPptApi {
223 223  
224 224  
225 225 /**
226   - * 通过大纲创建PPT(简化版)
  226 + * 通过大纲创建 PPT(简化版)
227 227 *
228 228 * @param outline 大纲内容
229 229 * @param query 查询文本
... ... @@ -238,14 +238,13 @@ public class XunfeiPptApi {
238 238 }
239 239  
240 240 /**
241   - * 通过大纲创建PPT(完整版)
  241 + * 通过大纲创建 PPT(完整版)
242 242 *
243 243 * @param request 请求参数
244 244 * @return 创建响应
245 245 */
246 246 public CreateResponse createPptByOutline(CreatePptByOutlineRequest request) {
247 247 SignatureInfo signInfo = getSignature();
248   -
249 248 return this.webClient.post()
250 249 .uri("/createPptByOutline")
251 250 .header("appId", signInfo.appId)
... ... @@ -260,14 +259,13 @@ public class XunfeiPptApi {
260 259 }
261 260  
262 261 /**
263   - * 检查PPT生成进度
  262 + * 检查 PPT 生成进度
264 263 *
265   - * @param sid 任务ID
  264 + * @param sid 任务 ID
266 265 * @return 进度响应
267 266 */
268 267 public ProgressResponse checkProgress(String sid) {
269 268 SignatureInfo signInfo = getSignature();
270   -
271 269 return this.webClient.get()
272 270 .uri(uriBuilder -> uriBuilder
273 271 .path("/progress")
... ... @@ -290,8 +288,7 @@ public class XunfeiPptApi {
290 288 String appId,
291 289 String timestamp,
292 290 String signature
293   - ) {
294   - }
  291 + ) { }
295 292  
296 293 /**
297 294 * 模板列表响应
... ... @@ -303,8 +300,7 @@ public class XunfeiPptApi {
303 300 String desc,
304 301 Integer count,
305 302 TemplatePageData data
306   - ) {
307   - }
  303 + ) { }
308 304  
309 305 /**
310 306 * 模板列表数据
... ... @@ -314,8 +310,7 @@ public class XunfeiPptApi {
314 310 String total,
315 311 List<TemplateInfo> records,
316 312 Integer pageNum
317   - ) {
318   - }
  313 + ) { }
319 314  
320 315 /**
321 316 * 模板信息
... ... @@ -329,8 +324,7 @@ public class XunfeiPptApi {
329 324 String industry,
330 325 String style,
331 326 String detailImage
332   - ) {
333   - }
  327 + ) { }
334 328  
335 329 /**
336 330 * 创建响应
... ... @@ -342,8 +336,7 @@ public class XunfeiPptApi {
342 336 String desc,
343 337 Integer count,
344 338 CreateResponseData data
345   - ) {
346   - }
  339 + ) { }
347 340  
348 341 /**
349 342 * 创建响应数据
... ... @@ -355,8 +348,7 @@ public class XunfeiPptApi {
355 348 String title,
356 349 String subTitle,
357 350 OutlineData outline
358   - ) {
359   - }
  351 + ) { }
360 352  
361 353 /**
362 354 * 大纲数据结构
... ... @@ -367,6 +359,7 @@ public class XunfeiPptApi {
367 359 String subTitle,
368 360 List<Chapter> chapters
369 361 ) {
  362 +
370 363 /**
371 364 * 章节结构
372 365 */
... ... @@ -375,14 +368,15 @@ public class XunfeiPptApi {
375 368 String chapterTitle,
376 369 List<ChapterContent> chapterContents
377 370 ) {
  371 +
378 372 /**
379 373 * 章节内容
380 374 */
381 375 @JsonInclude(value = JsonInclude.Include.NON_NULL)
382 376 public record ChapterContent(
383 377 String chapterTitle
384   - ) {
385   - }
  378 + ) { }
  379 +
386 380 }
387 381  
388 382 /**
... ... @@ -403,8 +397,7 @@ public class XunfeiPptApi {
403 397 int code,
404 398 String desc,
405 399 ProgressResponseData data
406   - ) {
407   - }
  400 + ) { }
408 401  
409 402 /**
410 403 * 进度响应数据
... ... @@ -414,6 +407,7 @@ public class XunfeiPptApi {
414 407 int process,
415 408 String pptId,
416 409 String pptUrl,
  410 + // TODO @新:字段注释,去掉
417 411 String pptStatus, // PPT构建状态:building(构建中),done(已完成),build_failed(生成失败)
418 412 String aiImageStatus, // ai配图状态:building(构建中),done(已完成)
419 413 String cardNoteStatus, // 演讲备注状态:building(构建中),done(已完成)
... ... @@ -421,6 +415,7 @@ public class XunfeiPptApi {
421 415 Integer totalPages, // 生成PPT的总页数
422 416 Integer donePages // 生成PPT的完成页数
423 417 ) {
  418 +
424 419 /**
425 420 * 是否全部完成
426 421 *
... ... @@ -452,10 +447,11 @@ public class XunfeiPptApi {
452 447 }
453 448 return (int) (donePages * 100.0 / totalPages);
454 449 }
  450 +
455 451 }
456 452  
457 453 /**
458   - * 通过大纲创建PPT请求参数
  454 + * 通过大纲创建 PPT 请求参数
459 455 */
460 456 @JsonInclude(value = JsonInclude.Include.NON_NULL)
461 457 public record CreatePptByOutlineRequest(
... ... @@ -473,6 +469,7 @@ public class XunfeiPptApi {
473 469 Boolean isFigure, // 是否自动配图
474 470 String aiImage // ai配图类型:normal、advanced
475 471 ) {
  472 +
476 473 /**
477 474 * 创建构建器
478 475 *
... ... @@ -482,10 +479,12 @@ public class XunfeiPptApi {
482 479 return new Builder();
483 480 }
484 481  
  482 + // TODO @新:这个可以用 lombok 简化么?
485 483 /**
486 484 * 构建器类
487 485 */
488 486 public static class Builder {
  487 +
489 488 private String query;
490 489 private String outlineSid;
491 490 private OutlineData outline;
... ... @@ -575,7 +574,7 @@ public class XunfeiPptApi {
575 574 }
576 575  
577 576 /**
578   - * 构建创建PPT的表单数据
  577 + * 构建创建 PPT 的表单数据
579 578 *
580 579 * @param request 请求参数
581 580 * @return 表单数据
... ... @@ -586,7 +585,6 @@ public class XunfeiPptApi {
586 585 if (request.query() != null) {
587 586 formData.add("query", request.query());
588 587 }
589   -
590 588 if (request.file() != null) {
591 589 try {
592 590 formData.add("file", new ByteArrayResource(request.file().getBytes()) {
... ... @@ -600,47 +598,37 @@ public class XunfeiPptApi {
600 598 throw new IllegalStateException("[xunfei-ppt-api] 文件处理失败", e);
601 599 }
602 600 }
603   -
  601 + // TODO @新:要不搞个 MapUtil.addIfPresent 方法?
604 602 if (request.fileUrl() != null) {
605 603 formData.add("fileUrl", request.fileUrl());
606 604 }
607   -
608 605 if (request.fileName() != null) {
609 606 formData.add("fileName", request.fileName());
610 607 }
611   -
612 608 if (request.templateId() != null) {
613 609 formData.add("templateId", request.templateId());
614 610 }
615   -
616 611 if (request.businessId() != null) {
617 612 formData.add("businessId", request.businessId());
618 613 }
619   -
620 614 if (request.author() != null) {
621 615 formData.add("author", request.author());
622 616 }
623   -
624 617 if (request.isCardNote() != null) {
625 618 formData.add("isCardNote", request.isCardNote().toString());
626 619 }
627   -
628 620 if (request.search() != null) {
629 621 formData.add("search", request.search().toString());
630 622 }
631   -
632 623 if (request.language() != null) {
633 624 formData.add("language", request.language());
634 625 }
635   -
636 626 if (request.isFigure() != null) {
637 627 formData.add("isFigure", request.isFigure().toString());
638 628 }
639   -
640 629 if (request.aiImage() != null) {
641 630 formData.add("aiImage", request.aiImage());
642 631 }
643   -
644 632 return formData;
645 633 }
646 634  
... ... @@ -662,6 +650,7 @@ public class XunfeiPptApi {
662 650 Boolean isFigure, // 是否自动配图
663 651 String aiImage // ai配图类型:normal、advanced
664 652 ) {
  653 +
665 654 /**
666 655 * 创建构建器
667 656 *
... ... @@ -675,6 +664,7 @@ public class XunfeiPptApi {
675 664 * 构建器类
676 665 */
677 666 public static class Builder {
  667 +
678 668 private String query;
679 669 private MultipartFile file;
680 670 private String fileUrl;
... ... @@ -688,6 +678,8 @@ public class XunfeiPptApi {
688 678 private Boolean isFigure;
689 679 private String aiImage;
690 680  
  681 + // TODO @新:这个可以用 lombok 简化么?
  682 +
691 683 public Builder query(String query) {
692 684 this.query = query;
693 685 return this;
... ... @@ -763,4 +755,5 @@ public class XunfeiPptApi {
763 755 }
764 756 }
765 757 }
766   -}
767 758 \ No newline at end of file
  759 +
  760 +}
768 761 \ No newline at end of file
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/ppt/wdd/WddPptApiTests.java
... ... @@ -9,7 +9,6 @@ import reactor.core.publisher.Flux;
9 9 import java.util.Map;
10 10 import java.util.Objects;
11 11  
12   -
13 12 /**
14 13 * {@link WddPptApi} 集成测试
15 14 *
... ... @@ -19,11 +18,9 @@ public class WddPptApiTests {
19 18  
20 19 private final WddPptApi wddPptApi = new WddPptApi("https://docmee.cn");
21 20  
  21 + private final String token = ""; // API Token
22 22  
23   - private final String token = "";
24   -
25   -
26   - @Test //获取token
  23 + @Test
27 24 @Disabled
28 25 public void testCreateApiToken() {
29 26 // 准备参数
... ... @@ -35,8 +32,10 @@ public class WddPptApiTests {
35 32 System.out.println(token);
36 33 }
37 34  
38   -
39   - @Test // 创建任务
  35 + /**
  36 + * 创建任务
  37 + */
  38 + @Test
40 39 @Disabled
41 40 public void testCreateTask() {
42 41 WddPptApi.ApiResponse apiResponse = wddPptApi.createTask(token, 1, "dify 介绍", null);
... ... @@ -47,8 +46,9 @@ public class WddPptApiTests {
47 46 @Test // 创建大纲
48 47 @Disabled
49 48 public void testGenerateOutlineRequest() {
50   - WddPptApi.CreateOutlineRequest request = new WddPptApi.CreateOutlineRequest("1901539019628613632", "medium", null, null, null, null);
51   - //调用
  49 + WddPptApi.CreateOutlineRequest request = new WddPptApi.CreateOutlineRequest(
  50 + "1901539019628613632", "medium", null, null, null, null);
  51 + // 调用
52 52 Flux<Map<String, Object>> flux = wddPptApi.createOutline(token, request);
53 53 StringBuffer contentBuffer = new StringBuffer();
54 54 flux.doOnNext(chunk -> {
... ... @@ -61,14 +61,17 @@ public class WddPptApiTests {
61 61 }).then().block();
62 62 // 打印结果
63 63 System.out.println(contentBuffer);
64   -
65 64 }
66 65  
67   - @Test // 修改大纲
  66 + /**
  67 + * 修改大纲
  68 + */
  69 + @Test
68 70 @Disabled
69 71 public void testUpdateOutlineRequest() {
70   - WddPptApi.UpdateOutlineRequest request = new WddPptApi.UpdateOutlineRequest("1901539019628613632", TEST_OUT_LINE_CONTENT, "精简一点,三个章节即可");
71   - //调用
  72 + WddPptApi.UpdateOutlineRequest request = new WddPptApi.UpdateOutlineRequest(
  73 + "1901539019628613632", TEST_OUT_LINE_CONTENT, "精简一点,三个章节即可");
  74 + // 调用
72 75 Flux<Map<String, Object>> flux = wddPptApi.updateOutline(token, request);
73 76 StringBuffer contentBuffer = new StringBuffer();
74 77 flux.doOnNext(chunk -> {
... ... @@ -84,31 +87,36 @@ public class WddPptApiTests {
84 87  
85 88 }
86 89  
87   - @Test // 获取 PPT 模版分页
  90 + /**
  91 + * 获取 PPT 模版分页
  92 + */
  93 + @Test
88 94 @Disabled
89 95 public void testGetPptTemplatePage() {
90 96 // 准备参数
91   - WddPptApi.TemplateQueryRequest.Filter filter = new WddPptApi.TemplateQueryRequest.Filter(1, null, null, null);
  97 + WddPptApi.TemplateQueryRequest.Filter filter = new WddPptApi.TemplateQueryRequest.Filter(
  98 + 1, null, null, null);
92 99 WddPptApi.TemplateQueryRequest request = new WddPptApi.TemplateQueryRequest(1, 10, filter);
93   - //调用
  100 + // 调用
94 101 WddPptApi.PagePptTemplateInfo pptTemplatePage = wddPptApi.getTemplatePage(token, request);
95 102 // 打印结果
96 103 System.out.println(pptTemplatePage);
97 104 }
98 105  
99   -
100   - @Test // 生成 PPT
  106 + /**
  107 + * 生成 PPT
  108 + */
  109 + @Test
101 110 @Disabled
102 111 public void testGeneratePptx() {
103 112 // 准备参数
104 113 WddPptApi.CreatePptRequest request = new WddPptApi.CreatePptRequest("1901539019628613632", "1805081814809960448", TEST_OUT_LINE_CONTENT);
105   - //调用
  114 + // 调用
106 115 WddPptApi.PptInfo pptInfo = wddPptApi.create(token, request);
107 116 // 打印结果
108 117 System.out.println(pptInfo);
109 118 }
110 119  
111   -
112 120 private final String TEST_OUT_LINE_CONTENT = """
113 121 # Dify:新一代AI应用开发平台
114 122  
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/ppt/xunfei/XunfeiPptApiTests.java
1 1 package cn.iocoder.yudao.framework.ai.ppt.xunfei;
2 2  
3   -import cn.iocoder.yudao.framework.ai.core.model.xunfei.api.XunfeiPptApi;
  3 +import cn.hutool.core.io.FileUtil;
  4 +import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XunfeiPptApi;
4 5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 6 import org.junit.jupiter.api.Disabled;
6 7 import org.junit.jupiter.api.Test;
... ... @@ -8,8 +9,6 @@ import org.springframework.mock.web.MockMultipartFile;
8 9 import org.springframework.web.multipart.MultipartFile;
9 10  
10 11 import java.io.File;
11   -import java.io.FileInputStream;
12   -import java.io.IOException;
13 12  
14 13 /**
15 14 * {@link XunfeiPptApi} 集成测试
... ... @@ -18,13 +17,16 @@ import java.io.IOException;
18 17 */
19 18 public class XunfeiPptApiTests {
20 19  
21   - // 讯飞API配置信息,实际使用时请替换为您的应用信息
  20 + // 讯飞 API 配置信息,实际使用时请替换为您的应用信息
22 21 private static final String APP_ID = "";
23 22 private static final String API_SECRET = "";
24 23  
25 24 private final XunfeiPptApi xunfeiPptApi = new XunfeiPptApi(XunfeiPptApi.BASE_URL, APP_ID, API_SECRET);
26 25  
27   - @Test // 获取PPT模板列表
  26 + /**
  27 + * 获取 PPT 模板列表
  28 + */
  29 + @Test
28 30 @Disabled
29 31 public void testGetTemplatePage() {
30 32 // 调用方法
... ... @@ -48,35 +50,42 @@ public class XunfeiPptApiTests {
48 50 }
49 51 }
50 52  
51   - @Test // 创建大纲(通过文本)
  53 + /**
  54 + * 创建大纲(通过文本)
  55 + */
  56 + @Test
52 57 @Disabled
53 58 public void testCreateOutline() {
54 59 XunfeiPptApi.CreateResponse response = getCreateResponse();
55 60 // 打印结果
56 61 System.out.println("创建大纲响应:" + JsonUtils.toJsonString(response));
57 62  
58   - // 保存sid和outline用于后续测试
  63 + // 保存 sid 和 outline 用于后续测试
59 64 if (response != null && response.data() != null) {
60 65 System.out.println("sid: " + response.data().sid());
61 66 if (response.data().outline() != null) {
62   - // 使用OutlineData的toJsonString方法
  67 + // 使用 OutlineData 的 toJsonString 方法
63 68 System.out.println("outline: " + response.data().outline().toJsonString());
64   - // 将outline对象转换为JSON字符串,用于后续createPptByOutline测试
  69 + // 将 outline 对象转换为 JSON 字符串,用于后续 createPptByOutline 测试
65 70 String outlineJson = response.data().outline().toJsonString();
66   - System.out.println("可用于createPptByOutline的outline字符串: " + outlineJson);
  71 + System.out.println("可用于 createPptByOutline 的 outline 字符串: " + outlineJson);
67 72 }
68 73 }
69 74 }
70 75  
71   - // 创建大纲(通过文本)
  76 + /**
  77 + * 创建大纲(通过文本)
  78 + * @return 创建大纲响应
  79 + */
72 80 private XunfeiPptApi.CreateResponse getCreateResponse() {
73   - // 准备参数
74 81 String param = "智能体平台 Dify 介绍";
75   - // 调用方法
76 82 return xunfeiPptApi.createOutline(param);
77 83 }
78 84  
79   - @Test // 通过大纲创建PPT(完整参数)
  85 + /**
  86 + * 通过大纲创建 PPT(完整参数)
  87 + */
  88 + @Test
80 89 @Disabled
81 90 public void testCreatePptByOutlineWithFullParams() {
82 91 // 创建大纲对象
... ... @@ -84,7 +93,7 @@ public class XunfeiPptApiTests {
84 93 // 调用方法
85 94 XunfeiPptApi.CreateResponse response = xunfeiPptApi.createPptByOutline(createResponse.data().outline(), "精简一些,不要超过6个章节");
86 95 // 打印结果
87   - System.out.println("通过大纲创建PPT响应:" + JsonUtils.toJsonString(response));
  96 + System.out.println("通过大纲创建 PPT 响应:" + JsonUtils.toJsonString(response));
88 97  
89 98 // 保存sid用于后续进度查询
90 99 if (response != null && response.data() != null) {
... ... @@ -95,10 +104,13 @@ public class XunfeiPptApiTests {
95 104 }
96 105 }
97 106  
98   - @Test // 检查PPT生成进度
  107 + /**
  108 + * 检查 PPT 生成进度
  109 + */
  110 + @Test
99 111 @Disabled
100 112 public void testCheckProgress() {
101   - // 准备参数 - 使用之前创建PPT时返回的sid
  113 + // 准备参数 - 使用之前创建 PPT 时返回的 sid
102 114 String sid = "e96dac09f2ec4ee289f029a5fb874ecd"; // 替换为实际的sid
103 115  
104 116 // 调用方法
... ... @@ -111,8 +123,8 @@ public class XunfeiPptApiTests {
111 123 XunfeiPptApi.ProgressResponseData data = response.data();
112 124  
113 125 // 打印PPT生成状态
114   - System.out.println("PPT构建状态: " + data.pptStatus());
115   - System.out.println("AI配图状态: " + data.aiImageStatus());
  126 + System.out.println("PPT 构建状态: " + data.pptStatus());
  127 + System.out.println("AI 配图状态: " + data.aiImageStatus());
116 128 System.out.println("演讲备注状态: " + data.cardNoteStatus());
117 129  
118 130 // 打印进度信息
... ... @@ -126,30 +138,33 @@ public class XunfeiPptApiTests {
126 138  
127 139 // 检查是否完成
128 140 if (data.isAllDone()) {
129   - System.out.println("PPT生成已完成!");
130   - System.out.println("PPT下载链接: " + data.pptUrl());
  141 + System.out.println("PPT 生成已完成!");
  142 + System.out.println("PPT 下载链接: " + data.pptUrl());
131 143 }
132 144 // 检查是否失败
133 145 else if (data.isFailed()) {
134   - System.out.println("PPT生成失败!");
  146 + System.out.println("PPT 生成失败!");
135 147 System.out.println("错误信息: " + data.errMsg());
136 148 }
137 149 // 正在进行中
138 150 else {
139   - System.out.println("PPT生成中,请稍后再查询...");
  151 + System.out.println("PPT 生成中,请稍后再查询...");
140 152 }
141 153 }
142 154 }
143 155  
144   - @Test // 轮询检查PPT生成进度直到完成
  156 + /**
  157 + * 轮询检查 PPT 生成进度直到完成
  158 + */
  159 + @Test
145 160 @Disabled
146 161 public void testPollCheckProgress() throws InterruptedException {
147   - // 准备参数 - 使用之前创建PPT时返回的sid
  162 + // 准备参数 - 使用之前创建 PP T时返回的 sid
148 163 String sid = "fa36e926f2ed434987fcb4c1f0776ffb"; // 替换为实际的sid
149 164  
150 165 // 最大轮询次数
151 166 int maxPolls = 20;
152   - // 轮询间隔(毫秒)- 讯飞API限流为3秒一次
  167 + // 轮询间隔(毫秒)- 讯飞 API 限流为 3 秒一次
153 168 long pollInterval = 3500;
154 169  
155 170 for (int i = 0; i < maxPolls; i++) {
... ... @@ -163,7 +178,7 @@ public class XunfeiPptApiTests {
163 178 XunfeiPptApi.ProgressResponseData data = response.data();
164 179  
165 180 // 打印进度信息
166   - System.out.println("PPT构建状态: " + data.pptStatus());
  181 + System.out.println("PPT 构建状态: " + data.pptStatus());
167 182 if (data.totalPages() != null && data.donePages() != null) {
168 183 System.out.println("完成进度: " + data.donePages() + "/" + data.totalPages()
169 184 + " (" + data.getProgressPercent() + "%)");
... ... @@ -171,19 +186,19 @@ public class XunfeiPptApiTests {
171 186  
172 187 // 检查是否完成
173 188 if (data.isAllDone()) {
174   - System.out.println("PPT生成已完成!");
175   - System.out.println("PPT下载链接: " + data.pptUrl());
  189 + System.out.println("PPT 生成已完成!");
  190 + System.out.println("PPT 下载链接: " + data.pptUrl());
176 191 break;
177 192 }
178 193 // 检查是否失败
179 194 else if (data.isFailed()) {
180   - System.out.println("PPT生成失败!");
  195 + System.out.println("PPT 生成失败!");
181 196 System.out.println("错误信息: " + data.errMsg());
182 197 break;
183 198 }
184 199 // 正在进行中,继续轮询
185 200 else {
186   - System.out.println("PPT生成中,等待" + (pollInterval / 1000) + "秒后继续查询...");
  201 + System.out.println("PPT 生成中,等待" + (pollInterval / 1000) + "秒后继续查询...");
187 202 Thread.sleep(pollInterval);
188 203 }
189 204 } else {
... ... @@ -193,7 +208,10 @@ public class XunfeiPptApiTests {
193 208 }
194 209 }
195 210  
196   - @Test // 直接创建PPT(通过文本)
  211 + /**
  212 + * 直接创建 PPT(通过文本)
  213 + */
  214 + @Test
197 215 @Disabled
198 216 public void testCreatePptByText() {
199 217 // 准备参数
... ... @@ -202,9 +220,9 @@ public class XunfeiPptApiTests {
202 220 // 调用方法
203 221 XunfeiPptApi.CreateResponse response = xunfeiPptApi.create(query);
204 222 // 打印结果
205   - System.out.println("直接创建PPT响应:" + JsonUtils.toJsonString(response));
  223 + System.out.println("直接创建 PPT 响应:" + JsonUtils.toJsonString(response));
206 224  
207   - // 保存sid用于后续进度查询
  225 + // 保存 sid 用于后续进度查询
208 226 if (response != null && response.data() != null) {
209 227 System.out.println("sid: " + response.data().sid());
210 228 if (response.data().coverImgSrc() != null) {
... ... @@ -215,9 +233,12 @@ public class XunfeiPptApiTests {
215 233 }
216 234 }
217 235  
218   - @Test // 直接创建PPT(通过文件)
  236 + /**
  237 + * 直接创建 PPT(通过文件)
  238 + */
  239 + @Test
219 240 @Disabled
220   - public void testCreatePptByFile() throws IOException {
  241 + public void testCreatePptByFile() {
221 242 // 准备参数
222 243 File file = new File("src/test/resources/test.txt"); // 请确保此文件存在
223 244 MultipartFile multipartFile = convertFileToMultipartFile(file);
... ... @@ -227,7 +248,7 @@ public class XunfeiPptApiTests {
227 248 // 打印结果
228 249 System.out.println("通过文件创建PPT响应:" + JsonUtils.toJsonString(response));
229 250  
230   - // 保存sid用于后续进度查询
  251 + // 保存 sid 用于后续进度查询
231 252 if (response != null && response.data() != null) {
232 253 System.out.println("sid: " + response.data().sid());
233 254 if (response.data().coverImgSrc() != null) {
... ... @@ -238,11 +259,14 @@ public class XunfeiPptApiTests {
238 259 }
239 260 }
240 261  
241   - @Test // 直接创建PPT(完整参数)
  262 + /**
  263 + * 直接创建 PPT(完整参数)
  264 + */
  265 + @Test
242 266 @Disabled
243   - public void testCreatePptWithFullParams() throws IOException {
  267 + public void testCreatePptWithFullParams() {
244 268 // 准备参数
245   - String query = "合肥天气趋势分析,包括近5年的气温变化、降水量变化、极端天气事件,以及对城市生活的影响";
  269 + String query = "合肥天气趋势分析,包括近 5 年的气温变化、降水量变化、极端天气事件,以及对城市生活的影响";
246 270  
247 271 // 创建请求对象
248 272 XunfeiPptApi.CreatePptRequest request = XunfeiPptApi.CreatePptRequest.builder()
... ... @@ -258,9 +282,9 @@ public class XunfeiPptApiTests {
258 282 // 调用方法
259 283 XunfeiPptApi.CreateResponse response = xunfeiPptApi.create(request);
260 284 // 打印结果
261   - System.out.println("使用完整参数创建PPT响应:" + JsonUtils.toJsonString(response));
  285 + System.out.println("使用完整参数创建 PPT 响应:" + JsonUtils.toJsonString(response));
262 286  
263   - // 保存sid用于后续进度查询
  287 + // 保存 sid 用于后续进度查询
264 288 if (response != null && response.data() != null) {
265 289 String sid = response.data().sid();
266 290 System.out.println("sid: " + sid);
... ... @@ -275,7 +299,7 @@ public class XunfeiPptApiTests {
275 299 XunfeiPptApi.ProgressResponse progressResponse = xunfeiPptApi.checkProgress(sid);
276 300 if (progressResponse != null && progressResponse.data() != null) {
277 301 XunfeiPptApi.ProgressResponseData progressData = progressResponse.data();
278   - System.out.println("PPT构建状态: " + progressData.pptStatus());
  302 + System.out.println("PPT 构建状态: " + progressData.pptStatus());
279 303 if (progressData.totalPages() != null && progressData.donePages() != null) {
280 304 System.out.println("完成进度: " + progressData.donePages() + "/" + progressData.totalPages()
281 305 + " (" + progressData.getProgressPercent() + "%)");
... ... @@ -285,16 +309,10 @@ public class XunfeiPptApiTests {
285 309 }
286 310  
287 311 /**
288   - * 将File转换为MultipartFile
  312 + * 将 File 转换为 MultipartFile
289 313 */
290   - private MultipartFile convertFileToMultipartFile(File file) throws IOException {
291   - FileInputStream input = new FileInputStream(file);
292   - return new MockMultipartFile(
293   - "file",
294   - file.getName(),
295   - "text/plain",
296   - input.readAllBytes()
297   - );
  314 + private MultipartFile convertFileToMultipartFile(File file) {
  315 + return new MockMultipartFile("file", file.getName(), "text/plain", FileUtil.readBytes(file));
298 316 }
299 317  
300   -}
301 318 \ No newline at end of file
  319 +}
302 320 \ No newline at end of file
... ...