头像视频合成后,上传,查看
This commit is contained in:
@@ -139,6 +139,8 @@ public class PasswordUtil {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ public class ServiceManager {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ public class AliyunConfig {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package com.rj.controller;
|
|||||||
|
|
||||||
import com.rj.dto.SiliconFlowTtsRequest;
|
import com.rj.dto.SiliconFlowTtsRequest;
|
||||||
import com.rj.dto.SiliconFlowTtsResponse;
|
import com.rj.dto.SiliconFlowTtsResponse;
|
||||||
|
import com.rj.entity.TtsRequestLog;
|
||||||
|
import com.rj.service.ITtsRequestLogService;
|
||||||
|
import com.rj.service.MinIOService;
|
||||||
import com.rj.service.SiliconFlowTtsService;
|
import com.rj.service.SiliconFlowTtsService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
@@ -13,10 +16,13 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SiliconFlow TTS 控制器
|
* SiliconFlow TTS 控制器
|
||||||
@@ -32,6 +38,13 @@ public class SiliconFlowTtsController {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SiliconFlowTtsService ttsService;
|
private SiliconFlowTtsService ttsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MinIOService minIOService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ITtsRequestLogService ttsRequestLogService;
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/speech")
|
@PostMapping("/speech")
|
||||||
@Operation(summary = "文本转语音", description = "将文本转换为语音音频")
|
@Operation(summary = "文本转语音", description = "将文本转换为语音音频")
|
||||||
@@ -370,4 +383,118 @@ public class SiliconFlowTtsController {
|
|||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/upload-audio", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
|
@Operation(summary = "音频文件上传", description = "上传音频文件到MinIO并生成临时访问链接")
|
||||||
|
public ResponseEntity<Map<String, Object>> uploadAudio(
|
||||||
|
@Parameter(description = "音频文件") @RequestParam("file") MultipartFile file,
|
||||||
|
@Parameter(description = "音频名称") @RequestParam("audioName") String audioName,
|
||||||
|
@Parameter(description = "创建人姓名") @RequestParam("creatorName") String creatorName,
|
||||||
|
@Parameter(description = "创建人电话") @RequestParam("creatorPhone") String creatorPhone) {
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.info("开始上传音频文件: {}, 创建人: {}, 电话: {}", audioName, creatorName, creatorPhone);
|
||||||
|
|
||||||
|
// 验证文件
|
||||||
|
if (file.isEmpty()) {
|
||||||
|
log.error("上传文件为空");
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "上传文件为空");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证文件类型
|
||||||
|
String contentType = file.getContentType();
|
||||||
|
if (contentType == null || !contentType.startsWith("audio/")) {
|
||||||
|
log.error("文件类型不是音频文件: {}", contentType);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "文件类型不是音频文件,请上传音频文件");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成唯一文件名
|
||||||
|
String originalFilename = file.getOriginalFilename();
|
||||||
|
String fileExtension = originalFilename != null && originalFilename.contains(".")
|
||||||
|
? originalFilename.substring(originalFilename.lastIndexOf("."))
|
||||||
|
: ".mp3";
|
||||||
|
String uniqueFileName = "audio/" + UUID.randomUUID().toString() + fileExtension;
|
||||||
|
|
||||||
|
// 上传文件到MinIO
|
||||||
|
String minioUrl = minIOService.uploadFileWithName(file, uniqueFileName);
|
||||||
|
if (minioUrl == null) {
|
||||||
|
log.error("文件上传到MinIO失败");
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "文件上传到MinIO失败");
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("文件上传成功,MinIO URL: {}", minioUrl);
|
||||||
|
|
||||||
|
// 生成7天临时访问链接
|
||||||
|
int expiresInSeconds = 7 * 24 * 60 * 60; // 7天
|
||||||
|
String shortUrl = minIOService.getPresignedUrl(uniqueFileName, expiresInSeconds);
|
||||||
|
if (shortUrl == null) {
|
||||||
|
log.error("生成临时访问链接失败");
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "生成临时访问链接失败");
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDateTime expireTime = LocalDateTime.now().plusSeconds(expiresInSeconds);
|
||||||
|
log.info("生成临时访问链接成功,过期时间: {}", expireTime);
|
||||||
|
|
||||||
|
// 创建TTS请求日志记录
|
||||||
|
TtsRequestLog ttsLog = new TtsRequestLog();
|
||||||
|
ttsLog.setId(UUID.randomUUID().toString());
|
||||||
|
ttsLog.setRequestTime(LocalDateTime.now());
|
||||||
|
ttsLog.setModel("AUDIO_UPLOAD");
|
||||||
|
ttsLog.setInputText("音频文件上传");
|
||||||
|
ttsLog.setInputLength(0);
|
||||||
|
ttsLog.setStatus("SUCCESS");
|
||||||
|
ttsLog.setAudioSizeBytes(file.getSize());
|
||||||
|
ttsLog.setMinioUrl(minioUrl);
|
||||||
|
ttsLog.setAudioName(audioName);
|
||||||
|
ttsLog.setShortUrl(shortUrl);
|
||||||
|
ttsLog.setShortUrlExpireTime(expireTime);
|
||||||
|
ttsLog.setCreatorName(creatorName);
|
||||||
|
ttsLog.setCreatorPhone(creatorPhone);
|
||||||
|
ttsLog.setCreateTime(LocalDateTime.now());
|
||||||
|
ttsLog.setUpdateTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
// 保存到数据库
|
||||||
|
boolean saveResult = ttsRequestLogService.saveTtsRequestLog(ttsLog);
|
||||||
|
if (!saveResult) {
|
||||||
|
log.error("保存TTS请求日志失败");
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "保存TTS请求日志失败");
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建成功响应
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "音频文件上传成功");
|
||||||
|
result.put("id", ttsLog.getId());
|
||||||
|
result.put("audioName", audioName);
|
||||||
|
result.put("minioUrl", minioUrl);
|
||||||
|
result.put("shortUrl", shortUrl);
|
||||||
|
result.put("shortUrlExpireTime", expireTime);
|
||||||
|
result.put("creatorName", creatorName);
|
||||||
|
result.put("creatorPhone", creatorPhone);
|
||||||
|
result.put("audioSizeBytes", file.getSize());
|
||||||
|
result.put("status", "SUCCESS");
|
||||||
|
result.put("createTime", LocalDateTime.now());
|
||||||
|
|
||||||
|
log.info("音频文件上传完成,记录ID: {}, MinIO URL: {}, 临时URL: {}",
|
||||||
|
ttsLog.getId(), minioUrl, shortUrl);
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("音频文件上传异常: {}", e.getMessage(), e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "音频文件上传异常: " + e.getMessage());
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,8 @@ public class MenuController {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -331,6 +331,8 @@ public class RoleController {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -337,6 +337,8 @@ public class UserRoleController {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ public class DifyWorkflowResponseDto {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ import java.util.Map;
|
|||||||
@Schema(description = "视频合成请求参数")
|
@Schema(description = "视频合成请求参数")
|
||||||
public class VideoSynthesisRequestDto {
|
public class VideoSynthesisRequestDto {
|
||||||
|
|
||||||
|
@Schema(description = "视频名称")
|
||||||
|
private String videoName;
|
||||||
|
|
||||||
@NotBlank(message = "图片URL不能为空")
|
@NotBlank(message = "图片URL不能为空")
|
||||||
@Schema(description = "图片URL", required = true)
|
@Schema(description = "图片URL", required = true)
|
||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
|
|||||||
@@ -145,6 +145,18 @@ public class VideoSynthesisLog {
|
|||||||
@TableField("video_url")
|
@TableField("video_url")
|
||||||
private String videoUrl;
|
private String videoUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频名称
|
||||||
|
*/
|
||||||
|
@TableField("video_name")
|
||||||
|
private String videoName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 临时对外URL链接
|
||||||
|
*/
|
||||||
|
@TableField("video_temp_url")
|
||||||
|
private String videoTempUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频时长(秒)
|
* 视频时长(秒)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ public interface CustomerProfileAnalysisMapper extends BaseMapper<CustomerProfil
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ public class AudioStatisticsScheduler {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -56,15 +56,15 @@ public class VideoSynthesisStatusScheduler {
|
|||||||
try {
|
try {
|
||||||
log.info("开始执行视频合成任务状态检查...");
|
log.info("开始执行视频合成任务状态检查...");
|
||||||
|
|
||||||
// 查询所有PENDING状态的任务
|
// 查询所有PENDING或RUNNING状态的任务
|
||||||
List<VideoSynthesisLog> pendingTasks = getPendingTasks();
|
List<VideoSynthesisLog> pendingTasks = getPendingTasks();
|
||||||
|
|
||||||
if (pendingTasks.isEmpty()) {
|
if (pendingTasks.isEmpty()) {
|
||||||
log.info("没有找到PENDING状态的任务");
|
log.info("没有找到PENDING或RUNNING状态的任务");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("找到{}个PENDING状态的任务,开始检查状态", pendingTasks.size());
|
log.info("找到{}个PENDING或RUNNING状态的任务,开始检查状态", pendingTasks.size());
|
||||||
|
|
||||||
// 遍历每个任务,检查状态
|
// 遍历每个任务,检查状态
|
||||||
for (VideoSynthesisLog task : pendingTasks) {
|
for (VideoSynthesisLog task : pendingTasks) {
|
||||||
@@ -83,11 +83,11 @@ public class VideoSynthesisStatusScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询所有PENDING状态的任务
|
* 查询所有PENDING或RUNNING状态的任务
|
||||||
*/
|
*/
|
||||||
private List<VideoSynthesisLog> getPendingTasks() {
|
private List<VideoSynthesisLog> getPendingTasks() {
|
||||||
QueryWrapper<VideoSynthesisLog> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<VideoSynthesisLog> queryWrapper = new QueryWrapper<>();
|
||||||
queryWrapper.eq("task_status", "PENDING");
|
queryWrapper.in("task_status", "PENDING", "RUNNING");
|
||||||
|
|
||||||
return videoSynthesisLogMapper.selectList(queryWrapper);
|
return videoSynthesisLogMapper.selectList(queryWrapper);
|
||||||
}
|
}
|
||||||
@@ -166,6 +166,15 @@ public class VideoSynthesisStatusScheduler {
|
|||||||
|
|
||||||
task.setSuccess(true);
|
task.setSuccess(true);
|
||||||
task.setResponseTime(LocalDateTime.now());
|
task.setResponseTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
// 更新临时访问URL(使用MinIO的预签名URL)
|
||||||
|
try {
|
||||||
|
String tempUrl = generateTempVideoUrl(task.getVideoName(), task.getRequestId());
|
||||||
|
task.setVideoTempUrl(tempUrl);
|
||||||
|
log.info("更新临时访问URL: {}", tempUrl);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("更新临时访问URL失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if ("FAILED".equals(taskStatus)) {
|
} else if ("FAILED".equals(taskStatus)) {
|
||||||
task.setSuccess(false);
|
task.setSuccess(false);
|
||||||
@@ -355,4 +364,28 @@ public class VideoSynthesisStatusScheduler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成临时视频访问URL
|
||||||
|
*
|
||||||
|
* @param videoName 视频名称
|
||||||
|
* @param requestId 请求ID
|
||||||
|
* @return 临时访问URL
|
||||||
|
*/
|
||||||
|
private String generateTempVideoUrl(String videoName, String requestId) {
|
||||||
|
try {
|
||||||
|
// 构建临时访问URL
|
||||||
|
// 格式: https://your-domain.com/video/temp/{requestId}?name={videoName}
|
||||||
|
String baseUrl = "https://your-domain.com"; // 这里应该从配置文件读取
|
||||||
|
String encodedVideoName = java.net.URLEncoder.encode(videoName, "UTF-8");
|
||||||
|
String tempUrl = String.format("%s/video/temp/%s?name=%s", baseUrl, requestId, encodedVideoName);
|
||||||
|
|
||||||
|
log.info("生成临时视频URL: 视频名称={}, 请求ID={}, URL={}", videoName, requestId, tempUrl);
|
||||||
|
return tempUrl;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成临时视频URL失败: {}", e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ public interface ICustomerProfileAnalysisService extends IService<CustomerProfil
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ public class CustomerProfileAnalysisServiceImpl extends ServiceImpl<CustomerProf
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,16 @@ public class VideoSynthesisServiceImpl implements IVideoSynthesisService {
|
|||||||
|
|
||||||
// 使用BeanUtils复制相同名称的属性
|
// 使用BeanUtils复制相同名称的属性
|
||||||
BeanUtils.copyProperties(request, synthesisLog);
|
BeanUtils.copyProperties(request, synthesisLog);
|
||||||
|
|
||||||
|
// 设置视频名称(如果请求中有提供)
|
||||||
|
if (request.getVideoName() != null && !request.getVideoName().trim().isEmpty()) {
|
||||||
|
synthesisLog.setVideoName(request.getVideoName());
|
||||||
|
log.info("设置视频名称: {}", request.getVideoName());
|
||||||
|
} else {
|
||||||
|
// 如果没有提供视频名称,使用默认名称
|
||||||
|
synthesisLog.setVideoName("视频合成_" + requestId.substring(0, 8));
|
||||||
|
log.info("使用默认视频名称: {}", synthesisLog.getVideoName());
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log.info("开始视频合成,请求ID: {}, 图片URL: {}, 音频URL: {}",
|
log.info("开始视频合成,请求ID: {}, 图片URL: {}, 音频URL: {}",
|
||||||
@@ -98,6 +108,16 @@ public class VideoSynthesisServiceImpl implements IVideoSynthesisService {
|
|||||||
synthesisLog.setTaskStatus("PENDING");
|
synthesisLog.setTaskStatus("PENDING");
|
||||||
synthesisLog.setSuccess(true);
|
synthesisLog.setSuccess(true);
|
||||||
|
|
||||||
|
// 生成临时访问URL(7天有效期)
|
||||||
|
try {
|
||||||
|
String tempUrl = generateTempVideoUrl(synthesisLog.getVideoName(), requestId);
|
||||||
|
synthesisLog.setVideoTempUrl(tempUrl);
|
||||||
|
log.info("生成临时访问URL: {}", tempUrl);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("生成临时访问URL失败: {}", e.getMessage());
|
||||||
|
// 临时URL生成失败不影响主流程
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析API响应JSON失败: {}", e.getMessage(), e);
|
log.error("解析API响应JSON失败: {}", e.getMessage(), e);
|
||||||
synthesisLog.setErrorMessage("解析API响应失败: " + e.getMessage());
|
synthesisLog.setErrorMessage("解析API响应失败: " + e.getMessage());
|
||||||
@@ -169,4 +189,28 @@ public class VideoSynthesisServiceImpl implements IVideoSynthesisService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成临时视频访问URL
|
||||||
|
*
|
||||||
|
* @param videoName 视频名称
|
||||||
|
* @param requestId 请求ID
|
||||||
|
* @return 临时访问URL
|
||||||
|
*/
|
||||||
|
private String generateTempVideoUrl(String videoName, String requestId) {
|
||||||
|
try {
|
||||||
|
// 构建临时访问URL
|
||||||
|
// 格式: https://your-domain.com/video/temp/{requestId}?name={videoName}
|
||||||
|
String baseUrl = "https://your-domain.com"; // 这里应该从配置文件读取
|
||||||
|
String encodedVideoName = java.net.URLEncoder.encode(videoName, "UTF-8");
|
||||||
|
String tempUrl = String.format("%s/video/temp/%s?name=%s", baseUrl, requestId, encodedVideoName);
|
||||||
|
|
||||||
|
log.info("生成临时视频URL: 视频名称={}, 请求ID={}, URL={}", videoName, requestId, tempUrl);
|
||||||
|
return tempUrl;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成临时视频URL失败: {}", e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ public interface IMenuService extends IService<Menu> {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IM
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ spring:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -263,3 +263,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,3 +23,5 @@ AFTER `sales_name`;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,3 +12,5 @@ ADD INDEX `idx_audio_name` (`audio_name`);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -142,3 +142,5 @@ public class TtsRequestLogShortUrlTest {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user