Merge #142 into master from cc_20260515_audio_ge
音频生成 * cc_20260515_audio_ge: (3 commits squashed) - fix:音频生成 - fix:新增删除音频记录接口 - fix:删除音频记录接口入参修改 Signed-off-by: 王非凡 <accounts_67eba0c5fee9c49c80c8e2b4@mail.teambition.com> Merged-by: 正新 <accounts_6964c7bcd2a2c377c5bbd01b@mail.teambition.com> CR-link: https://codeup.aliyun.com/692ea314dec569489f6f167c/hangzhou/java/custom_zxjp/change/142
This commit is contained in:
@@ -502,6 +502,9 @@ public enum ErrorCodeEnum {
|
|||||||
BONUS_DISTRIBUTE_RATIO_OVER_100(1850003, "分配规则员工比例之和大于100", null),
|
BONUS_DISTRIBUTE_RATIO_OVER_100(1850003, "分配规则员工比例之和大于100", null),
|
||||||
BONUS_PRODUCT_CONFIG_DUPLICATE(1850004, "奖金规则配置存在重复菜品", null),
|
BONUS_PRODUCT_CONFIG_DUPLICATE(1850004, "奖金规则配置存在重复菜品", null),
|
||||||
BONUS_RULE_CONFIG_ERROR(1850005, "规则配置异常", null),
|
BONUS_RULE_CONFIG_ERROR(1850005, "规则配置异常", null),
|
||||||
|
|
||||||
|
NO_PERMISSION_TO_DELETE_THE_RECORD(1850006, "无权限删除该记录", null),
|
||||||
|
THE_AUDIO_GENERATION_RECORD_DOES_NOT_EXIST(1850007, "音频生成记录不存在", null),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.cool.store.dao;
|
||||||
|
|
||||||
|
import com.cool.store.entity.audio.AudioGenerateRecordDO;
|
||||||
|
import com.cool.store.mapper.audio.AudioGenerateRecordMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频生成记录DAO
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Repository
|
||||||
|
public class AudioGenerateRecordDAO {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AudioGenerateRecordMapper audioGenerateRecordMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入音频生成记录
|
||||||
|
* @param record 音频生成记录
|
||||||
|
* @return 影响行数
|
||||||
|
*/
|
||||||
|
public int insert(AudioGenerateRecordDO record) {
|
||||||
|
return audioGenerateRecordMapper.insertSelective(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据创建用户ID查询记录
|
||||||
|
* @param createUserId 创建用户ID
|
||||||
|
* @return 记录列表
|
||||||
|
*/
|
||||||
|
public List<AudioGenerateRecordDO> queryByCreateUserId(String createUserId) {
|
||||||
|
return audioGenerateRecordMapper.queryByCreateUserId(createUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询记录
|
||||||
|
* @param id 记录ID
|
||||||
|
* @return 音频生成记录
|
||||||
|
*/
|
||||||
|
public AudioGenerateRecordDO selectById(Long id) {
|
||||||
|
return audioGenerateRecordMapper.selectByPrimaryKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID删除记录
|
||||||
|
* @param id 记录ID
|
||||||
|
* @return 影响行数
|
||||||
|
*/
|
||||||
|
public int deleteById(Long id) {
|
||||||
|
return audioGenerateRecordMapper.deleteByPrimaryKey(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.cool.store.mapper.audio;
|
||||||
|
|
||||||
|
import com.cool.store.entity.audio.AudioGenerateRecordDO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import tk.mybatis.mapper.common.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频生成记录
|
||||||
|
*/
|
||||||
|
public interface AudioGenerateRecordMapper extends Mapper<AudioGenerateRecordDO> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据创建用户ID查询记录,按创建时间倒序
|
||||||
|
* @param createUserId 创建用户ID
|
||||||
|
* @return 记录列表
|
||||||
|
*/
|
||||||
|
List<AudioGenerateRecordDO> queryByCreateUserId(@Param("createUserId") String createUserId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.cool.store.mapper.audio.AudioGenerateRecordMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="com.cool.store.entity.audio.AudioGenerateRecordDO">
|
||||||
|
<!--
|
||||||
|
WARNING - @mbg.generated
|
||||||
|
-->
|
||||||
|
<id column="id" jdbcType="BIGINT" property="id" />
|
||||||
|
<result column="url" jdbcType="VARCHAR" property="url" />
|
||||||
|
<result column="voice_id" jdbcType="VARCHAR" property="voiceId" />
|
||||||
|
<result column="voice_name" jdbcType="VARCHAR" property="voiceName" />
|
||||||
|
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
|
||||||
|
<result column="create_user_id" jdbcType="VARCHAR" property="createUserId" />
|
||||||
|
<result column="content" jdbcType="LONGVARCHAR" property="content" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="queryByCreateUserId" resultMap="BaseResultMap">
|
||||||
|
SELECT id, url, voice_id, voice_name, create_time, create_user_id, content
|
||||||
|
FROM zxjp_audio_generate_record
|
||||||
|
WHERE create_user_id = #{createUserId}
|
||||||
|
ORDER BY create_time DESC
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频附加信息DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AudioExtraInfoDTO {
|
||||||
|
/**
|
||||||
|
* 音频时长(毫秒)
|
||||||
|
*/
|
||||||
|
private Long audioLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频采样率
|
||||||
|
*/
|
||||||
|
private Long audioSampleRate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频大小
|
||||||
|
*/
|
||||||
|
private Long audioSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比特率
|
||||||
|
*/
|
||||||
|
private Long bitrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用字符数
|
||||||
|
*/
|
||||||
|
private Long usageCharacters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频格式
|
||||||
|
*/
|
||||||
|
private String audioFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频声道
|
||||||
|
*/
|
||||||
|
private Integer audioChannel;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频生成记录VO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("音频生成记录")
|
||||||
|
public class AudioGenerateRecordVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("记录ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty("音频URL")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@ApiModelProperty("音色ID")
|
||||||
|
private String voiceId;
|
||||||
|
|
||||||
|
@ApiModelProperty("音色名称")
|
||||||
|
private String voiceName;
|
||||||
|
|
||||||
|
@ApiModelProperty("文案内容")
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@ApiModelProperty("创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除音频生成记录请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DeleteAudioRecordReqDTO {
|
||||||
|
@NotNull(message = "记录ID不能为空")
|
||||||
|
@ApiModelProperty(value = "音频生成记录ID", required = true)
|
||||||
|
private Long id;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色记忆DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FavoriteVoiceDTO {
|
||||||
|
/**
|
||||||
|
* 音色ID
|
||||||
|
*/
|
||||||
|
private String voiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色名称
|
||||||
|
*/
|
||||||
|
private String voiceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参考文案
|
||||||
|
*/
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模式标记
|
||||||
|
*/
|
||||||
|
private String mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模式展示名
|
||||||
|
*/
|
||||||
|
private String modeLabel;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频生成请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class GenerateAudioReqDTO {
|
||||||
|
@NotBlank(message = "文案不能为空")
|
||||||
|
@Size(max = 500, message = "文案长度不能超过500")
|
||||||
|
@ApiModelProperty(value = "文案", required = true)
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@NotBlank(message = "音色不能为空")
|
||||||
|
@ApiModelProperty(value = "音色ID", required = true)
|
||||||
|
private String voiceId;
|
||||||
|
|
||||||
|
@NotBlank(message = "音色名称不能为空")
|
||||||
|
@ApiModelProperty("音色名称")
|
||||||
|
private String voiceName;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI文案优化请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OptimizeCopyReqDTO {
|
||||||
|
@NotBlank(message = "文案不能为空")
|
||||||
|
@ApiModelProperty(value = "原始文案", required = true)
|
||||||
|
private String text;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文案优化请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OptimizeCopyRequestDTO {
|
||||||
|
/**
|
||||||
|
* 原始文案
|
||||||
|
*/
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前音色ID
|
||||||
|
*/
|
||||||
|
private String voiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色记忆列表
|
||||||
|
*/
|
||||||
|
private List<FavoriteVoiceDTO> favorites;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文案优化响应DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OptimizeCopyResponseDTO {
|
||||||
|
/**
|
||||||
|
* 优化后的文案
|
||||||
|
*/
|
||||||
|
private String optimizedText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推荐音色ID
|
||||||
|
*/
|
||||||
|
private String recommendedVoiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 朗读指令
|
||||||
|
*/
|
||||||
|
private String ttsInstructions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推荐原因
|
||||||
|
*/
|
||||||
|
private String reason;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本生成语音请求DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SpeechRequestDTO {
|
||||||
|
/**
|
||||||
|
* 待合成文本
|
||||||
|
*/
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色配置
|
||||||
|
*/
|
||||||
|
private VoiceConfigDTO voice;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本生成语音响应DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SpeechResponseDTO {
|
||||||
|
/**
|
||||||
|
* 音频Base64
|
||||||
|
*/
|
||||||
|
private String audioBase64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原始hex音频
|
||||||
|
*/
|
||||||
|
private String audioHex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求追踪ID
|
||||||
|
*/
|
||||||
|
private String traceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频附加信息
|
||||||
|
*/
|
||||||
|
private AudioExtraInfoDTO extraInfo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色配置DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class VoiceConfigDTO {
|
||||||
|
/**
|
||||||
|
* 音色ID
|
||||||
|
*/
|
||||||
|
private String voiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 语速
|
||||||
|
*/
|
||||||
|
private Double speed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音量
|
||||||
|
*/
|
||||||
|
private Double vol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音高
|
||||||
|
*/
|
||||||
|
private Double pitch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 情绪
|
||||||
|
*/
|
||||||
|
private String emotion;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色对象DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class VoiceDTO {
|
||||||
|
/**
|
||||||
|
* 音色ID
|
||||||
|
*/
|
||||||
|
private String voiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色名称
|
||||||
|
*/
|
||||||
|
private String voiceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色描述
|
||||||
|
*/
|
||||||
|
private List<String> description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private String createdTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.cool.store.dto.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色列表响应DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class VoiceListDTO {
|
||||||
|
/**
|
||||||
|
* 系统音色列表
|
||||||
|
*/
|
||||||
|
private List<VoiceDTO> systemVoice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 快速复刻音色列表
|
||||||
|
*/
|
||||||
|
private List<VoiceDTO> voiceCloning;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文生音色列表
|
||||||
|
*/
|
||||||
|
private List<VoiceDTO> voiceGeneration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义音色列表
|
||||||
|
*/
|
||||||
|
private List<VoiceDTO> customVoice;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.cool.store.entity.audio;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频生成记录
|
||||||
|
*/
|
||||||
|
@Table(name = "zxjp_audio_generate_record")
|
||||||
|
@Data
|
||||||
|
public class AudioGenerateRecordDO {
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频路径
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色id
|
||||||
|
*/
|
||||||
|
@Column(name = "voice_id")
|
||||||
|
private String voiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色名称
|
||||||
|
*/
|
||||||
|
@Column(name = "voice_name")
|
||||||
|
private String voiceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@Column(name = "create_time")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人id
|
||||||
|
*/
|
||||||
|
@Column(name = "create_user_id")
|
||||||
|
private String createUserId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文案
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
package com.cool.store.service.audio;
|
||||||
|
|
||||||
|
import com.cool.store.dto.audio.*;
|
||||||
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
|
import com.cool.store.exception.ServiceException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import okhttp3.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频API调用服务
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AudioApiService {
|
||||||
|
|
||||||
|
@Value("${audio.api.url}")
|
||||||
|
private String audioApiUrl;
|
||||||
|
|
||||||
|
@Value("${audio.api.secret}")
|
||||||
|
private String audioApiSecret;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OkHttpClient okHttpClient;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询音色列表
|
||||||
|
* @param voiceType 音色类型
|
||||||
|
* @return 音色列表
|
||||||
|
*/
|
||||||
|
public VoiceListDTO getVoiceList(String voiceType) {
|
||||||
|
String path = "/api/audio/voices";
|
||||||
|
String query = voiceType != null ? "voiceType=" + voiceType : "";
|
||||||
|
return executeGet(path, query, VoiceListDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文本生成语音
|
||||||
|
* @param request 请求参数
|
||||||
|
* @return 音频响应
|
||||||
|
*/
|
||||||
|
public SpeechResponseDTO generateSpeech(SpeechRequestDTO request) {
|
||||||
|
return executePost("/api/audio/speech", request, SpeechResponseDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能优化口播文案
|
||||||
|
* @param request 请求参数
|
||||||
|
* @return 优化后的文案
|
||||||
|
*/
|
||||||
|
public OptimizeCopyResponseDTO optimizeCopy(OptimizeCopyRequestDTO request) {
|
||||||
|
return executePost("/api/voice-agent/optimize-copy", request, OptimizeCopyResponseDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送带签名的GET请求
|
||||||
|
*/
|
||||||
|
private <T> T executeGet(String path, String query, Class<T> responseType) {
|
||||||
|
try {
|
||||||
|
String url = audioApiUrl + path + (query.isEmpty() ? "" : "?" + query);
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
String signature = generateSignature("GET", path, query, "", timestamp);
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.get()
|
||||||
|
.addHeader("X-Signature-Version", "v1")
|
||||||
|
.addHeader("X-Timestamp", String.valueOf(timestamp))
|
||||||
|
.addHeader("X-Signature", signature)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
log.info("发送GET请求: {}", url);
|
||||||
|
Response response = okHttpClient.newCall(request).execute();
|
||||||
|
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
log.error("GET请求失败: {}", response.code());
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, response.code() + " " + response.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseBody = response.body().string();
|
||||||
|
log.info("收到响应: {}", responseBody);
|
||||||
|
|
||||||
|
return parseResponse(responseBody, responseType);
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送GET请求失败: {}", path, e);
|
||||||
|
throw new RuntimeException("接口调用异常: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送带签名的POST请求
|
||||||
|
*/
|
||||||
|
private <T> T executePost(String path, Object body, Class<T> responseType) {
|
||||||
|
try {
|
||||||
|
String url = audioApiUrl + path;
|
||||||
|
String bodyJson = objectMapper.writeValueAsString(body);
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
String signature = generateSignature("POST", path, "", bodyJson, timestamp);
|
||||||
|
|
||||||
|
RequestBody requestBody = RequestBody.create(
|
||||||
|
MediaType.parse("application/json; charset=utf-8"), bodyJson);
|
||||||
|
|
||||||
|
Request httpRequest = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(requestBody)
|
||||||
|
.addHeader("Content-Type", "application/json")
|
||||||
|
.addHeader("X-Signature-Version", "v1")
|
||||||
|
.addHeader("X-Timestamp", String.valueOf(timestamp))
|
||||||
|
.addHeader("X-Signature", signature)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
log.info("发送POST请求: {}, 数据: {}", url, bodyJson);
|
||||||
|
Response response = okHttpClient.newCall(httpRequest).execute();
|
||||||
|
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
log.error("POST请求失败: {}", response.code());
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, response.code() + " " + response.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseBody = response.body().string();
|
||||||
|
log.info("收到响应长度: {}", responseBody.length());
|
||||||
|
|
||||||
|
return parseResponse(responseBody, responseType);
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送POST请求失败: {}", path, e);
|
||||||
|
throw new RuntimeException("接口调用异常: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析响应
|
||||||
|
*/
|
||||||
|
private <T> T parseResponse(String responseJson, Class<T> responseType) throws IOException {
|
||||||
|
Map<String, Object> responseMap = objectMapper.readValue(responseJson,
|
||||||
|
new TypeReference<Map<String, Object>>() {});
|
||||||
|
|
||||||
|
checkBusinessResponseCode(responseMap);
|
||||||
|
|
||||||
|
Object data = responseMap.get("data");
|
||||||
|
if (data != null) {
|
||||||
|
return objectMapper.convertValue(data, responseType);
|
||||||
|
}
|
||||||
|
return objectMapper.convertValue(responseMap, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查业务响应码
|
||||||
|
*/
|
||||||
|
private void checkBusinessResponseCode(Map<String, Object> responseMap) {
|
||||||
|
Object codeObj = responseMap.get("code");
|
||||||
|
if (codeObj != null) {
|
||||||
|
int code = 0;
|
||||||
|
if (codeObj instanceof Number) {
|
||||||
|
code = ((Number) codeObj).intValue();
|
||||||
|
} else {
|
||||||
|
code = Integer.parseInt(codeObj.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code != 200 && code != 0) {
|
||||||
|
String msg = (String) responseMap.get("msg");
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
|
||||||
|
"code: " + code + ", msg: " + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成HMAC-SHA256签名
|
||||||
|
*/
|
||||||
|
private String generateSignature(String method, String path, String query, String body, long timestamp) {
|
||||||
|
try {
|
||||||
|
String bodySha256 = sha256(body);
|
||||||
|
String canonicalQuery = canonicalizeQuery(query);
|
||||||
|
|
||||||
|
String signingString = method + "\n" +
|
||||||
|
path + "\n" +
|
||||||
|
canonicalQuery + "\n" +
|
||||||
|
bodySha256 + "\n" +
|
||||||
|
timestamp;
|
||||||
|
|
||||||
|
log.debug("签名原文: {}", signingString);
|
||||||
|
|
||||||
|
return hmacSha256(signingString, audioApiSecret);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成签名失败", e);
|
||||||
|
throw new RuntimeException("生成签名失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算SHA256
|
||||||
|
*/
|
||||||
|
private String sha256(String input) {
|
||||||
|
try {
|
||||||
|
if (input == null || input.isEmpty()) {
|
||||||
|
input = "";
|
||||||
|
}
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return bytesToHex(hash);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("SHA256计算失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HMAC-SHA256签名
|
||||||
|
*/
|
||||||
|
private String hmacSha256(String data, String key) {
|
||||||
|
try {
|
||||||
|
javax.crypto.spec.SecretKeySpec secretKey = new javax.crypto.spec.SecretKeySpec(
|
||||||
|
key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
|
||||||
|
javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA256");
|
||||||
|
mac.init(secretKey);
|
||||||
|
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return bytesToHex(hash);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("HMAC-SHA256签名失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字节数组转十六进制字符串
|
||||||
|
*/
|
||||||
|
private String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 规范化Query参数
|
||||||
|
*/
|
||||||
|
private String canonicalizeQuery(String query) {
|
||||||
|
if (query == null || query.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
TreeMap<String, String> params = new TreeMap<>();
|
||||||
|
String[] pairs = query.split("&");
|
||||||
|
for (String pair : pairs) {
|
||||||
|
String[] kv = pair.split("=", 2);
|
||||||
|
if (kv.length == 2) {
|
||||||
|
params.put(kv[0], kv[1]);
|
||||||
|
} else if (kv.length == 1) {
|
||||||
|
params.put(kv[0], "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append("&");
|
||||||
|
}
|
||||||
|
sb.append(entry.getKey()).append("=").append(entry.getValue());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.cool.store.service.audio;
|
||||||
|
|
||||||
|
import com.cool.store.dto.audio.*;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频生成记录服务接口
|
||||||
|
*/
|
||||||
|
public interface AudioGenerateRecordService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI文案优化
|
||||||
|
* @param text 原始文案
|
||||||
|
* @return 优化后的文案
|
||||||
|
*/
|
||||||
|
String optimizeCopy(String text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询音色列表
|
||||||
|
* @param voiceType 音色类型
|
||||||
|
* @return 音色列表
|
||||||
|
*/
|
||||||
|
VoiceListDTO getVoiceList(String voiceType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文案生成音频,上传OSS并入库
|
||||||
|
* @param request 音频生成请求DTO
|
||||||
|
* @return 音频生成记录
|
||||||
|
*/
|
||||||
|
AudioGenerateRecordVO generateAudio(GenerateAudioReqDTO request, String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询当前用户的音频生成记录
|
||||||
|
* @param pageNum 页码
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @return 分页结果
|
||||||
|
*/
|
||||||
|
PageInfo<AudioGenerateRecordVO> queryUserAudioRecords(Integer pageNum, Integer pageSize, String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除音频生成记录
|
||||||
|
* @param id 记录ID
|
||||||
|
* @param userId 用户ID(用于权限校验)
|
||||||
|
*/
|
||||||
|
Boolean deleteAudioRecord(Long id, String userId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
package com.cool.store.service.audio;
|
||||||
|
|
||||||
|
import com.cool.store.dao.AudioGenerateRecordDAO;
|
||||||
|
import com.cool.store.dto.audio.*;
|
||||||
|
import com.cool.store.entity.audio.AudioGenerateRecordDO;
|
||||||
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
|
import com.cool.store.exception.ServiceException;
|
||||||
|
import com.cool.store.oss.OssClientService;
|
||||||
|
import com.cool.store.utils.BeanUtil;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频生成记录服务实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AudioGenerateRecordServiceImpl implements AudioGenerateRecordService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AudioApiService audioApiService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OssClientService ossClientService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AudioGenerateRecordDAO audioGenerateRecordDAO;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String optimizeCopy(String text) {
|
||||||
|
OptimizeCopyRequestDTO request = new OptimizeCopyRequestDTO();
|
||||||
|
request.setText(text);
|
||||||
|
|
||||||
|
OptimizeCopyResponseDTO response = audioApiService.optimizeCopy(request);
|
||||||
|
return response.getOptimizedText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoiceListDTO getVoiceList(String voiceType) {
|
||||||
|
return audioApiService.getVoiceList(voiceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public AudioGenerateRecordVO generateAudio(GenerateAudioReqDTO request, String userId) {
|
||||||
|
// 1. 调用音频生成接口
|
||||||
|
SpeechRequestDTO speechRequest = new SpeechRequestDTO();
|
||||||
|
speechRequest.setText(request.getContent());
|
||||||
|
|
||||||
|
VoiceConfigDTO voiceConfig = new VoiceConfigDTO();
|
||||||
|
voiceConfig.setVoiceId(request.getVoiceId());
|
||||||
|
speechRequest.setVoice(voiceConfig);
|
||||||
|
|
||||||
|
SpeechResponseDTO response = audioApiService.generateSpeech(speechRequest);
|
||||||
|
|
||||||
|
// 2. 将Base64音频解码并上传到OSS
|
||||||
|
String audioUrl = uploadAudioToOss(response.getAudioBase64(), response.getTraceId());
|
||||||
|
|
||||||
|
// 3. 入库音频生成记录
|
||||||
|
AudioGenerateRecordDO record = saveAudioRecord(request.getContent(), request.getVoiceId(), request.getVoiceName(), audioUrl, userId);
|
||||||
|
|
||||||
|
// 4. 转换为VO返回
|
||||||
|
return BeanUtil.toBean(record, AudioGenerateRecordVO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传音频到OSS
|
||||||
|
*/
|
||||||
|
private String uploadAudioToOss(String audioBase64, String traceId) {
|
||||||
|
try {
|
||||||
|
byte[] audioBytes = Base64.getDecoder().decode(audioBase64);
|
||||||
|
|
||||||
|
String fileName = "audio/" + UUID.randomUUID().toString() + ".mp3";
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(audioBytes);
|
||||||
|
|
||||||
|
String url = ossClientService.putObject(fileName, inputStream, (long) audioBytes.length, "audio/mpeg");
|
||||||
|
log.info("音频上传OSS成功, url: {}", url);
|
||||||
|
|
||||||
|
return url;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("音频上传OSS失败", e);
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "音频上传OSS失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存音频生成记录
|
||||||
|
*/
|
||||||
|
private AudioGenerateRecordDO saveAudioRecord(String content, String voiceId, String voiceName, String audioUrl, String userId) {
|
||||||
|
AudioGenerateRecordDO record = new AudioGenerateRecordDO();
|
||||||
|
record.setContent(content);
|
||||||
|
record.setVoiceId(voiceId);
|
||||||
|
record.setVoiceName(voiceName);
|
||||||
|
record.setUrl(audioUrl);
|
||||||
|
record.setCreateTime(new Date());
|
||||||
|
record.setCreateUserId(userId);
|
||||||
|
|
||||||
|
audioGenerateRecordDAO.insert(record);
|
||||||
|
log.info("音频生成记录入库成功, id: {}", record.getId());
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageInfo<AudioGenerateRecordVO> queryUserAudioRecords(Integer pageNum, Integer pageSize, String userId) {
|
||||||
|
PageHelper.startPage(pageNum, pageSize);
|
||||||
|
List<AudioGenerateRecordDO> records = audioGenerateRecordDAO.queryByCreateUserId(userId);
|
||||||
|
|
||||||
|
return BeanUtil.toPage(new PageInfo<>(records), AudioGenerateRecordVO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean deleteAudioRecord(Long id, String userId) {
|
||||||
|
// 1. 查询记录是否存在
|
||||||
|
AudioGenerateRecordDO record = audioGenerateRecordDAO.selectById(id);
|
||||||
|
if (record == null) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THE_AUDIO_GENERATION_RECORD_DOES_NOT_EXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 校验用户权限(只能删除自己创建的记录)
|
||||||
|
if (!record.getCreateUserId().equals(userId)) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.NO_PERMISSION_TO_DELETE_THE_RECORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 删除记录
|
||||||
|
return audioGenerateRecordDAO.deleteById(id) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package com.cool.store.controller.webc;
|
||||||
|
|
||||||
|
import com.cool.store.common.PageBasicInfo;
|
||||||
|
import com.cool.store.context.PartnerUserHolder;
|
||||||
|
import com.cool.store.dto.audio.*;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import com.cool.store.service.audio.AudioGenerateRecordService;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序音频控制器
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/mini/audio")
|
||||||
|
@Api(tags = "小程序音频")
|
||||||
|
@Slf4j
|
||||||
|
public class MiniAudioController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AudioGenerateRecordService audioGenerateRecordService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI文案优化接口
|
||||||
|
* @param request 请求参数
|
||||||
|
* @return 优化后的文案
|
||||||
|
*/
|
||||||
|
@PostMapping("/optimizeCopy")
|
||||||
|
@ApiOperation("AI文案优化")
|
||||||
|
public ResponseResult<String> optimizeCopy(@Valid @RequestBody OptimizeCopyReqDTO request) {
|
||||||
|
String optimizedText = audioGenerateRecordService.optimizeCopy(request.getText());
|
||||||
|
return ResponseResult.success(optimizedText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色列表查询接口
|
||||||
|
* @param voiceType 音色类型
|
||||||
|
* @return 音色列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/voiceList")
|
||||||
|
@ApiOperation("查询音色列表")
|
||||||
|
@ApiImplicitParam(name = "voiceType", value = "音色类型,system-系统音色 voice_cloning-快速复刻音色 voice_generation-文生音色 custom-本系统录入音色 all-返回全部分类")
|
||||||
|
public ResponseResult<VoiceListDTO> getVoiceList(@RequestParam(required = false) String voiceType) {
|
||||||
|
VoiceListDTO voiceList = audioGenerateRecordService.getVoiceList(voiceType);
|
||||||
|
return ResponseResult.success(voiceList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文案生成音频接口
|
||||||
|
* @param request 请求参数
|
||||||
|
* @return 音频生成记录
|
||||||
|
*/
|
||||||
|
@PostMapping("/generate")
|
||||||
|
@ApiOperation("生成音频")
|
||||||
|
public ResponseResult<AudioGenerateRecordVO> generateAudio(@Valid @RequestBody GenerateAudioReqDTO request) {
|
||||||
|
AudioGenerateRecordVO record = audioGenerateRecordService.generateAudio(request, PartnerUserHolder.getUser().getPartnerId());
|
||||||
|
return ResponseResult.success(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询当前用户的音频生成记录
|
||||||
|
* @param request 请求参数
|
||||||
|
* @return 分页结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/recordList")
|
||||||
|
@ApiOperation("查询音频生成记录")
|
||||||
|
public ResponseResult<PageInfo<AudioGenerateRecordVO>> queryAudioRecords(@Valid @RequestBody PageBasicInfo request) {
|
||||||
|
PageInfo<AudioGenerateRecordVO> page = audioGenerateRecordService.queryUserAudioRecords(
|
||||||
|
request.getPageNum(), request.getPageSize(), PartnerUserHolder.getUser().getPartnerId());
|
||||||
|
return ResponseResult.success(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除音频生成记录
|
||||||
|
* @param request 请求参数
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/delete")
|
||||||
|
@ApiOperation("删除音频生成记录")
|
||||||
|
public ResponseResult<Boolean> deleteAudioRecord(@Valid @RequestBody DeleteAudioRecordReqDTO request) {
|
||||||
|
return ResponseResult.success(audioGenerateRecordService.deleteAudioRecord(request.getId(), PartnerUserHolder.getUser().getPartnerId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -187,4 +187,7 @@ closeup.platform.secret=6ezC98lNx5b1IQt
|
|||||||
store.open.url=https://zhengxin.zhidiansoft.com:5943
|
store.open.url=https://zhengxin.zhidiansoft.com:5943
|
||||||
store.open.appId=289704779317445
|
store.open.appId=289704779317445
|
||||||
store.open.appKey=IGSAEQoakR2HEaYx
|
store.open.appKey=IGSAEQoakR2HEaYx
|
||||||
store.open.secret=aPsA99K1obFeFm3m
|
store.open.secret=aPsA99K1obFeFm3m
|
||||||
|
|
||||||
|
audio.api.url=https://zx-agent.zhidiansoft.com:6443
|
||||||
|
audio.api.secret=12b538d018c396f0a50cb3560d9ba103578f378c7807660b7fc42843382ae03d
|
||||||
@@ -185,4 +185,7 @@ closeup.platform.secret=6ezC98lNx5b1IQt
|
|||||||
store.open.url=https://zhengxin.zhidiansoft.com:5943
|
store.open.url=https://zhengxin.zhidiansoft.com:5943
|
||||||
store.open.appId=289704779317445
|
store.open.appId=289704779317445
|
||||||
store.open.appKey=IGSAEQoakR2HEaYx
|
store.open.appKey=IGSAEQoakR2HEaYx
|
||||||
store.open.secret=aPsA99K1obFeFm3m
|
store.open.secret=aPsA99K1obFeFm3m
|
||||||
|
|
||||||
|
audio.api.url=https://zx-agent.zhidiansoft.com:6443
|
||||||
|
audio.api.secret=12b538d018c396f0a50cb3560d9ba103578f378c7807660b7fc42843382ae03d
|
||||||
@@ -189,4 +189,7 @@ liePin.secretKey=dns6x4f1p14a36u4t22xvteppmz07ir2
|
|||||||
liePin.aesSecretKey=_nkULTpkBHHZeWgQ
|
liePin.aesSecretKey=_nkULTpkBHHZeWgQ
|
||||||
liePin.baseUrl=https://open-xhopen-qa53.qa.xunhou.cn
|
liePin.baseUrl=https://open-xhopen-qa53.qa.xunhou.cn
|
||||||
liePin.tenantId=12833
|
liePin.tenantId=12833
|
||||||
liePin.mobile=13345565081
|
liePin.mobile=13345565081
|
||||||
|
|
||||||
|
audio.api.url=https://zx-agent.zhidiansoft.com:6443
|
||||||
|
audio.api.secret=12b538d018c396f0a50cb3560d9ba103578f378c7807660b7fc42843382ae03d
|
||||||
@@ -188,3 +188,6 @@ store.open.url=https://zhengxin.zhidiansoft.com:5943
|
|||||||
store.open.appId=289704779317445
|
store.open.appId=289704779317445
|
||||||
store.open.appKey=IGSAEQoakR2HEaYx
|
store.open.appKey=IGSAEQoakR2HEaYx
|
||||||
store.open.secret=aPsA99K1obFeFm3m
|
store.open.secret=aPsA99K1obFeFm3m
|
||||||
|
|
||||||
|
audio.api.url=https://zx-agent.zhidiansoft.com:6443
|
||||||
|
audio.api.secret=12b538d018c396f0a50cb3560d9ba103578f378c7807660b7fc42843382ae03d
|
||||||
|
|||||||
Reference in New Issue
Block a user