【功能新增】AI:对接文多多 v2 接口

This commit is contained in:
xiaoxin 2025-03-15 22:38:09 +08:00
parent ea1d9f0075
commit a82abed2b5
1 changed files with 217 additions and 293 deletions

View File

@ -1,17 +1,26 @@
package cn.iocoder.yudao.framework.ai.core.model.wenduoduo.api; package cn.iocoder.yudao.framework.ai.core.model.wenduoduo.api;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpRequest; import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatusCode; import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -47,26 +56,24 @@ public class WddApi {
.build(); .build();
} }
/** /**
* 创建API令牌 * 创建 token
* *
* @param apiKey API密钥 * @param request 请求信息
* @param uid 用户ID * @return token
* @param limit 限制
* @return API令牌
*/ */
public String createApiToken(String apiKey, String uid, Integer limit) { public String createApiToken(CreateTokenRequest request) {
CreateApiTokenRequest request = new CreateApiTokenRequest(uid, limit);
return this.webClient.post() return this.webClient.post()
.uri("/api/user/createApiToken") .uri("/api/user/createApiToken")
.header("Api-Key", apiKey) .header("Api-Key", request.apiKey)
.body(Mono.just(request), CreateApiTokenRequest.class) .body(Mono.just(request), CreateTokenRequest.class)
.retrieve() .retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request)) .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(ApiResponse.class) .bodyToMono(ApiResponse.class)
.<String>handle((response, sink) -> { .<String>handle((response, sink) -> {
if (response.code != 0) { if (response.code != 0) {
sink.error(new IllegalStateException("创建apiToken异常," + response.message)); sink.error(new IllegalStateException("创建 token 异常," + response.message));
return; return;
} }
sink.next(response.data.get("token").toString()); sink.next(response.data.get("token").toString());
@ -74,259 +81,159 @@ public class WddApi {
.block(); .block();
} }
/** /**
* 解析文件数据 * 创建任务
* *
* @param apiToken API令牌 * @param type 类型
* @param content 内容 * @param content 内容
* @param fileUrl 文件URL * @param files 文件列表
* @return 数据URL * @return 任务ID
*/ */
public String parseFileData(String apiToken, String content, String fileUrl) { public ApiResponse createTask(String token, Integer type, String content, List<MultipartFile> files) {
ParseFileDataRequest request = new ParseFileDataRequest(content, fileUrl); MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
formData.add("type", type);
if (content != null) {
formData.add("content", content);
}
if (files != null) {
for (MultipartFile file : files) {
formData.add("file", file.getResource());
}
}
return this.webClient.post() return this.webClient.post()
.uri("/api/ppt/parseFileData") .uri("/api/ppt/v2/createTask")
.header("token", apiToken) .header("token", token)
.body(Mono.just(request), ParseFileDataRequest.class) .contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(formData))
.retrieve() .retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request)) .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(formData))
.bodyToMono(ApiResponse.class) .bodyToMono(ApiResponse.class)
.<String>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("解析文件或内容异常," + response.message));
return;
}
sink.next(response.data.get("dataUrl").toString());
})
.block(); .block();
} }
/** /**
* 生成大纲 * 获取生成选项
* *
* @param apiToken API令牌 * @param lang 语种
* @param subject 主题 * @return 生成选项
* @param dataUrl 数据URL
* @param prompt 提示词
* @return 大纲内容
*/ */
public String generateOutline(String apiToken, String subject, String dataUrl, String prompt) { public Map<String, Object> getOptions(String lang) {
GenerateOutlineRequest request = new GenerateOutlineRequest(subject, dataUrl, prompt); String uri = "/api/ppt/v2/options";
return this.webClient.post() if (lang != null) {
.uri("/api/ppt/generateOutline") uri += "?lang=" + lang;
.header("token", apiToken) }
.body(Mono.just(request), GenerateOutlineRequest.class) return this.webClient.get()
.uri(uri)
.retrieve() .retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request)) .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(null))
.bodyToMono(String.class) .bodyToMono(new ParameterizedTypeReference<ApiResponse>() {
})
.<Map<String, Object>>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("获取生成选项异常," + response.message));
return;
}
sink.next(response.data);
})
.block(); .block();
} }
/** /**
* 生成大纲内容 * 生成大纲内容
* *
* @param apiToken API令牌 * @return 大纲内容流
* @param outlineMarkdown 大纲Markdown
* @param dataUrl 数据URL
* @param prompt 提示词
* @return 大纲内容
*/ */
public String generateContent(String apiToken, String outlineMarkdown, String dataUrl, String prompt) { public Flux<Map<String, Object>> generateOutlineContent(String token, GenerateOutlineRequest request) {
GenerateContentRequest request = new GenerateContentRequest(outlineMarkdown, dataUrl, prompt);
return this.webClient.post() return this.webClient.post()
.uri("/api/ppt/generateContent") .uri("/api/ppt/v2/generateContent")
.header("token", apiToken) .header("token", token)
.body(Mono.just(request), GenerateContentRequest.class) .body(Mono.just(request), GenerateOutlineRequest.class)
.retrieve() .retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request)) .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(String.class) .bodyToFlux(new ParameterizedTypeReference<>() {
.block(); });
} }
/** /**
* 异步生成大纲内容 * 修改大纲内容
* *
* @param apiToken API令牌 * @param id 任务ID
* @param outlineMarkdown 大纲Markdown * @param markdown 大纲内容markdown
* @param dataUrl 数据URL * @param question 用户修改建议
* @param templateId 模板ID * @return 大纲内容流
* @param prompt 提示词
* @return 大纲内容和PPT ID
*/ */
public Map<String, Object> asyncGenerateContent(String apiToken, String outlineMarkdown, String dataUrl, String templateId, String prompt) { public Flux<Map<String, Object>> updateOutlineContent(String token, String id, String markdown, String question) {
AsyncGenerateContentRequest request = new AsyncGenerateContentRequest(outlineMarkdown, dataUrl, templateId, prompt); UpdateOutlineRequest request = new UpdateOutlineRequest(id, markdown, question);
return this.webClient.post() return this.webClient.post()
.uri("/api/ppt/generateContent") .uri("/api/ppt/v2/updateContent")
.header("token", apiToken) .header("token", token)
.body(Mono.just(request), AsyncGenerateContentRequest.class) .body(Mono.just(request), UpdateOutlineRequest.class)
.retrieve() .retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request)) .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() { .bodyToFlux(new ParameterizedTypeReference<Map<String, Object>>() {
}) });
.block();
} }
/**
* 随机获取一个模板ID
*
* @param apiToken API令牌
* @return 模板ID
*/
public String randomOneTemplateId(String apiToken) {
RandomTemplateRequest request = new RandomTemplateRequest(1, new TemplateFilter(1));
return this.webClient.post()
.uri("/api/ppt/randomTemplates")
.header("token", apiToken)
.body(Mono.just(request), RandomTemplateRequest.class)
.retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(ApiResponse.class)
.<String>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("获取模板异常," + response.message));
return;
}
sink.next(((Map<String, Object>) ((Object[]) response.data.get("data"))[0]).get("id").toString());
})
.block();
}
/**
* 生成PPT
*
* @param apiToken API令牌
* @param templateId 模板ID
* @param markdown Markdown内容
* @param pptxProperty PPT属性
* @return PPT信息
*/
public Map<String, Object> generatePptx(String apiToken, String templateId, String markdown, boolean pptxProperty) {
GeneratePptxRequest request = new GeneratePptxRequest(templateId, markdown, pptxProperty);
return this.webClient.post()
.uri("/api/ppt/generatePptx")
.header("token", apiToken)
.body(Mono.just(request), GeneratePptxRequest.class)
.retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(ApiResponse.class)
.<Map<String, Object>>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("生成PPT异常" + response.message));
return;
}
sink.next((Map<String, Object>) response.data.get("pptInfo"));
})
.block();
}
/**
* 下载PPT
*
* @param apiToken API令牌
* @param id PPT ID
* @return 下载信息
*/
public Map<String, Object> downloadPptx(String apiToken, String id) {
DownloadPptxRequest request = new DownloadPptxRequest(id);
return this.webClient.post()
.uri("/api/ppt/downloadPptx")
.header("token", apiToken)
.body(Mono.just(request), DownloadPptxRequest.class)
.retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(ApiResponse.class)
.<Map<String, Object>>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("下载PPT异常" + response.message));
return;
}
sink.next(response.data);
})
.block();
}
/**
* 直接生成PPT
*
* @param apiToken API令牌
* @param templateId 模板ID
* @param subject 主题
* @param dataUrl 数据URL
* @param prompt 提示词
* @param pptxProperty PPT属性
* @return PPT信息
*/
public Map<String, Object> directGeneratePptx(String apiToken, String templateId, String subject, String dataUrl, String prompt, boolean pptxProperty) {
DirectGeneratePptxRequest request = new DirectGeneratePptxRequest(false, templateId, subject, dataUrl, prompt, pptxProperty);
return this.webClient.post()
.uri("/api/ppt/directGeneratePptx")
.header("token", apiToken)
.body(Mono.just(request), DirectGeneratePptxRequest.class)
.retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(ApiResponse.class)
.<Map<String, Object>>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("生成PPT异常" + response.message));
return;
}
sink.next((Map<String, Object>) response.data.get("pptInfo"));
})
.block();
}
/**
* 查询所有PPT列表
*
* @param apiToken API令牌
* @param body 请求体
* @return PPT列表
*/
public Map<String, Object> listAllPptx(String apiToken, String body) {
return this.webClient.post()
.uri("/api/ppt/listAllPptx")
.header("token", apiToken)
.bodyValue(body)
.retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(body))
.bodyToMono(ApiResponse.class)
.<Map<String, Object>>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("查询所有PPT列表异常" + response.message));
return;
}
sink.next(response.data);
})
.block();
}
/** /**
* 分页查询PPT模板 * 分页查询PPT模板
* *
* @param apiToken API令牌 * @param token 令牌
* @param body 请求体 * @param request 请求体
* @return 模板列表 * @return 模板列表
*/ */
public Map<String, Object> getPptTemplates(String apiToken, String body) { public PagePptTemplateInfo getPptTemplatePage(String token, TemplateQueryRequest request) {
return this.webClient.post() return this.webClient.post()
.uri("/api/ppt/templates") .uri("/api/ppt/templates")
.header("token", apiToken) .header("token", token)
.bodyValue(body) .bodyValue(request)
.retrieve() .retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(body)) .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(ApiResponse.class) .bodyToMono(new ParameterizedTypeReference<PagePptTemplateInfo>() {
.<Map<String, Object>>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("分页查询PPT模板异常" + response.message));
return;
}
sink.next(response.data);
}) })
.block(); .block();
} }
/** /**
* API响应 * 生成PPT
*
* @return PPT信息
*/
public PptInfo generatePptx(String token, GeneratePptxRequest request) {
return this.webClient.post()
.uri("/api/ppt/v2/generatePptx")
.header("token", token)
.body(Mono.just(request), GeneratePptxRequest.class)
.retrieve()
.onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(request))
.bodyToMono(ApiResponse.class)
.<PptInfo>handle((response, sink) -> {
if (response.code != 0) {
sink.error(new IllegalStateException("生成 PPT 异常," + response.message));
return;
}
sink.next(Objects.requireNonNull(JsonUtils.parseObject(JsonUtils.toJsonString(response.data.get("pptInfo")), PptInfo.class)));
})
.block();
}
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record CreateTokenRequest(
String apiKey,
String uid,
Integer limit
) {
public CreateTokenRequest(String apiKey) {
this(apiKey, null, null);
}
}
/**
* API 通用响应
*/ */
@JsonInclude(value = JsonInclude.Include.NON_NULL) @JsonInclude(value = JsonInclude.Include.NON_NULL)
public record ApiResponse( public record ApiResponse(
@ -337,33 +244,13 @@ public class WddApi {
} }
/** /**
* 创建API令牌请求 * 创建任务
*/ */
@JsonInclude(value = JsonInclude.Include.NON_NULL) @JsonInclude(value = JsonInclude.Include.NON_NULL)
public record CreateApiTokenRequest( public record CreateTaskRequest(
String uid, Integer type,
Integer limit
) {
}
/**
* 解析文件数据请求
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record ParseFileDataRequest(
String content, String content,
String fileUrl List<MultipartFile> files
) {
}
/**
* 生成大纲请求
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record GenerateOutlineRequest(
String subject,
String dataUrl,
String prompt
) { ) {
} }
@ -371,45 +258,24 @@ public class WddApi {
* 生成大纲内容请求 * 生成大纲内容请求
*/ */
@JsonInclude(value = JsonInclude.Include.NON_NULL) @JsonInclude(value = JsonInclude.Include.NON_NULL)
public record GenerateContentRequest( public record GenerateOutlineRequest(
String outlineMarkdown, String id,
String dataUrl, String length,
String scene,
String audience,
String lang,
String prompt String prompt
) { ) {
} }
/** /**
* 异步生成大纲内容请求 * 修改大纲内容请求
*/ */
@JsonInclude(value = JsonInclude.Include.NON_NULL) @JsonInclude(value = JsonInclude.Include.NON_NULL)
public record AsyncGenerateContentRequest( public record UpdateOutlineRequest(
String outlineMarkdown, String id,
String dataUrl, String markdown,
String templateId, String question
String prompt,
@JsonProperty("asyncGenPptx") boolean asyncGenPptx
) {
public AsyncGenerateContentRequest(String outlineMarkdown, String dataUrl, String templateId, String prompt) {
this(outlineMarkdown, dataUrl, templateId, prompt, true);
}
}
/**
* 随机模板请求
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record RandomTemplateRequest(
Integer size,
TemplateFilter filters
) {
}
/**
* 模板过滤器
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record TemplateFilter(
Integer type
) { ) {
} }
@ -418,32 +284,90 @@ public class WddApi {
*/ */
@JsonInclude(value = JsonInclude.Include.NON_NULL) @JsonInclude(value = JsonInclude.Include.NON_NULL)
public record GeneratePptxRequest( public record GeneratePptxRequest(
String id,
String templateId, String templateId,
@JsonProperty("outlineContentMarkdown") String outlineContentMarkdown, String markdown
boolean pptxProperty
) { ) {
} }
/**
* 下载PPT请求
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record DownloadPptxRequest(
String id
) {
}
/**
* 直接生成PPT请求
*/
@JsonInclude(value = JsonInclude.Include.NON_NULL) @JsonInclude(value = JsonInclude.Include.NON_NULL)
public record DirectGeneratePptxRequest( public record PptInfo(
boolean stream, String id,
String templateId, String name,
String subject, String subject,
String dataUrl, String coverUrl,
String prompt, String fileUrl,
boolean pptxProperty String templateId,
String pptxProperty,
String userId,
String userName,
int companyId,
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime updateTime,
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime createTime,
String createUser,
String updateUser
) { ) {
} }
}
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record TemplateQueryRequest(
int page,
int size,
Filter filters
) {
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record Filter(
int type,
String category,
String style,
String themeColor
) {
}
}
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record PagePptTemplateInfo(
List<PptTemplateInfo> data,
String total
) {
}
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public record PptTemplateInfo(
String id,
int type,
Integer subType,
String layout,
String category,
String style,
String themeColor,
String lang,
boolean animation,
String subject,
String coverUrl,
String fileUrl,
List<String> pageCoverUrls,
String pptxProperty,
int sort,
int num,
Integer imgNum,
int isDeleted,
String userId,
int companyId,
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime updateTime,
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime createTime,
String createUser,
String updateUser
) {
}
}