From 3249970b7b38a752e5e65c3b25397be5f0f72417 Mon Sep 17 00:00:00 2001 From: hrz <1710360675@qq.com> Date: Tue, 7 Oct 2025 23:54:42 +0800 Subject: [PATCH] =?UTF-8?q?update:=E6=99=BA=E6=8E=A7=E5=8F=B0=E9=9F=B3?= =?UTF-8?q?=E8=89=B2=E5=85=8B=E9=9A=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xiaozhi/common/constant/Constant.java | 2 +- .../xiaozhi/common/exception/ErrorCode.java | 13 + .../java/xiaozhi/common/redis/RedisKeys.java | 6 + .../AgentChatHistoryController.java | 3 - .../modules/model/dao/ModelConfigDao.java | 6 + .../model/service/ModelConfigService.java | 10 +- .../service/impl/ModelConfigServiceImpl.java | 8 + .../modules/security/config/ShiroConfig.java | 1 + .../controller/VoiceCloneController.java | 190 +++++ .../controller/VoiceResourceController.java | 114 +++ .../modules/voiceclone/dao/VoiceCloneDao.java | 15 + .../modules/voiceclone/dto/VoiceCloneDTO.java | 20 + .../voiceclone/dto/VoiceCloneResponseDTO.java | 48 ++ .../voiceclone/entity/VoiceCloneEntity.java | 53 ++ .../voiceclone/service/VoiceCloneService.java | 68 ++ .../service/impl/VoiceCloneServiceImpl.java | 210 ++++++ .../resources/db/changelog/202510071521.sql | 15 + .../db/changelog/db.changelog-master.yaml | 7 + .../main/resources/i18n/messages.properties | 287 +++---- .../resources/i18n/messages_en_US.properties | 13 +- .../resources/i18n/messages_zh_CN.properties | 291 ++++---- .../resources/i18n/messages_zh_TW.properties | 291 ++++---- .../resources/mapper/model/ModelConfigDao.xml | 7 + main/manager-mobile/src/i18n/en.ts | 2 +- main/manager-mobile/src/i18n/zh_TW.ts | 2 +- .../src/pages/settings/index.vue | 2 +- main/manager-web/src/apis/api.js | 8 +- .../manager-web/src/apis/module/voiceClone.js | 98 +++ .../src/apis/module/voiceResource.js | 103 +++ .../src/assets/header/firmware_update.png | Bin 7738 -> 0 bytes main/manager-web/src/assets/header/voice.png | Bin 0 -> 1813 bytes .../src/components/FirmwareDialog.vue | 25 +- main/manager-web/src/components/HeaderBar.vue | 224 +++--- .../src/components/VoiceCloneDialog.vue | 694 +++++++++++++++++ .../src/components/VoiceResourceDialog.vue | 154 ++++ main/manager-web/src/i18n/en.js | 86 ++- main/manager-web/src/i18n/zh_CN.js | 84 ++- main/manager-web/src/i18n/zh_TW.js | 84 ++- main/manager-web/src/router/index.js | 24 +- .../src/views/VoiceCloneManagement.vue | 697 +++++++++++++++++ .../src/views/VoiceResourceManagement.vue | 704 ++++++++++++++++++ main/xiaozhi-server/config/logger.py | 2 +- 42 files changed, 4140 insertions(+), 531 deletions(-) create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceCloneController.java create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceResourceController.java create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dao/VoiceCloneDao.java create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneDTO.java create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneResponseDTO.java create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/entity/VoiceCloneEntity.java create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/VoiceCloneService.java create mode 100644 main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/impl/VoiceCloneServiceImpl.java create mode 100644 main/manager-api/src/main/resources/db/changelog/202510071521.sql create mode 100644 main/manager-web/src/apis/module/voiceClone.js create mode 100644 main/manager-web/src/apis/module/voiceResource.js delete mode 100644 main/manager-web/src/assets/header/firmware_update.png create mode 100644 main/manager-web/src/assets/header/voice.png create mode 100644 main/manager-web/src/components/VoiceCloneDialog.vue create mode 100644 main/manager-web/src/components/VoiceResourceDialog.vue create mode 100644 main/manager-web/src/views/VoiceCloneManagement.vue create mode 100644 main/manager-web/src/views/VoiceResourceManagement.vue diff --git a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java index b80ad6bb..febe12ff 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java +++ b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java @@ -257,7 +257,7 @@ public interface Constant { /** * 版本号 */ - public static final String VERSION = "0.8.3"; + public static final String VERSION = "0.8.4"; /** * 无效固件URL diff --git a/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java b/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java index 10144db4..573269b8 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java +++ b/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java @@ -175,4 +175,17 @@ public interface ErrorCode { int DOWNLOAD_LINK_INVALID = 10137; // 下载链接无效 int CHAT_ROLE_USER = 10138; // 用户角色 int CHAT_ROLE_AGENT = 10139; // 智能体角色 + + // 声音克隆相关错误码 + int VOICE_CLONE_AUDIO_EMPTY = 10140; // 音频文件不能为空 + int VOICE_CLONE_NOT_AUDIO_FILE = 10141; // 只支持音频文件 + int VOICE_CLONE_AUDIO_TOO_LARGE = 10142; // 音频文件大小不能超过10MB + int VOICE_CLONE_UPLOAD_FAILED = 10143; // 上传失败 + int VOICE_CLONE_RECORD_NOT_EXIST = 10144; // 声音克隆记录不存在 + int VOICE_RESOURCE_INFO_EMPTY = 10145; // 音色资源信息不能为空 + int VOICE_RESOURCE_PLATFORM_NAME_EMPTY = 10146; // 平台名称不能为空 + int VOICE_RESOURCE_ID_EMPTY = 10147; // 音色ID不能为空 + int VOICE_RESOURCE_ACCOUNT_EMPTY = 10148; // 归属账号不能为空 + int VOICE_RESOURCE_DELETE_ID_EMPTY = 10149; // 删除的音色资源ID不能为空 + int VOICE_RESOURCE_NO_PERMISSION = 10150; // 您没有权限操作该记录 } diff --git a/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java b/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java index 751cc601..d25c72b6 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java +++ b/main/manager-api/src/main/java/xiaozhi/common/redis/RedisKeys.java @@ -146,4 +146,10 @@ public class RedisKeys { return "agent:chat:history:" + uuid; } + /** + * 获取音色克隆音频ID的缓存key + */ + public static String getVoiceCloneAudioIdKey(String uuid) { + return "voiceClone:audio:id:" + uuid; + } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentChatHistoryController.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentChatHistoryController.java index 810c2fc1..53c85d72 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentChatHistoryController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentChatHistoryController.java @@ -12,8 +12,6 @@ import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -49,7 +47,6 @@ import xiaozhi.modules.security.user.SecurityUser; @RestController @RequestMapping("/agent/chat-history") public class AgentChatHistoryController { - private static final Logger logger = LoggerFactory.getLogger(AgentChatHistoryController.class); private final AgentChatHistoryBizService agentChatHistoryBizService; private final AgentChatHistoryService agentChatHistoryService; private final AgentService agentService; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/model/dao/ModelConfigDao.java b/main/manager-api/src/main/java/xiaozhi/modules/model/dao/ModelConfigDao.java index 79c526f0..70c6abc4 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/model/dao/ModelConfigDao.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/model/dao/ModelConfigDao.java @@ -1,6 +1,7 @@ package xiaozhi.modules.model.dao; import java.util.List; +import java.util.Map; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -15,4 +16,9 @@ public interface ModelConfigDao extends BaseDao { * get model_code list */ List getModelCodeList(@Param("modelType") String modelType, @Param("modelName") String modelName); + + /** + * 获取符合条件的TTS平台列表(id和modelName) + */ + List> getTtsPlatformList(); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/model/service/ModelConfigService.java b/main/manager-api/src/main/java/xiaozhi/modules/model/service/ModelConfigService.java index 7788cb20..aa2631fc 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/model/service/ModelConfigService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/model/service/ModelConfigService.java @@ -1,6 +1,7 @@ package xiaozhi.modules.model.service; import java.util.List; +import java.util.Map; import xiaozhi.common.page.PageData; import xiaozhi.common.service.BaseService; @@ -53,9 +54,16 @@ public interface ModelConfigService extends BaseService { /** * 设置默认模型 - * + * * @param modelType 模型类型 * @param isDefault 是否默认(1:是,0:否) */ void setDefaultModel(String modelType, int isDefault); + + /** + * 获取符合条件的TTS平台列表 + * + * @return TTS平台列表(id和modelName) + */ + List> getTtsPlatformList(); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java index cee88568..ccda1af4 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/model/service/impl/ModelConfigServiceImpl.java @@ -516,4 +516,12 @@ public class ModelConfigServiceImpl extends BaseServiceImpl> getTtsPlatformList() { + return modelConfigDao.getTtsPlatformList(); + } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java b/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java index 290a279d..051cbc29 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/config/ShiroConfig.java @@ -91,6 +91,7 @@ public class ShiroConfig { filterMap.put("/agent/chat-history/download/**", "anon"); filterMap.put("/agent/saveMemory/**", "server"); filterMap.put("/agent/play/**", "anon"); + filterMap.put("/voiceClone/play/**", "anon"); filterMap.put("/**", "oauth2"); shiroFilter.setFilterChainDefinitionMap(filterMap); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceCloneController.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceCloneController.java new file mode 100644 index 00000000..5e166b65 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceCloneController.java @@ -0,0 +1,190 @@ +package xiaozhi.modules.voiceclone.controller; + +import java.util.Map; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.exception.ErrorCode; +import xiaozhi.common.exception.RenException; +import xiaozhi.common.page.PageData; +import xiaozhi.common.redis.RedisKeys; +import xiaozhi.common.redis.RedisUtils; +import xiaozhi.common.user.UserDetail; +import xiaozhi.common.utils.Result; +import xiaozhi.common.validator.ValidatorUtils; +import xiaozhi.modules.security.user.SecurityUser; +import xiaozhi.modules.voiceclone.dto.VoiceCloneResponseDTO; +import xiaozhi.modules.voiceclone.entity.VoiceCloneEntity; +import xiaozhi.modules.voiceclone.service.VoiceCloneService; + +@Tag(name = "音色资源管理", description = "音色资源开通相关接口") +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/voiceClone") +public class VoiceCloneController { + + private final VoiceCloneService voiceCloneService; + private final RedisUtils redisUtils; + + @GetMapping + @Operation(summary = "分页查询音色资源") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true) + }) + @RequiresPermissions("sys:role:normal") + public Result> page( + @Parameter(hidden = true) @RequestParam Map params) { + ValidatorUtils.validateEntity(params); + UserDetail user = SecurityUser.getUser(); + params.put("userId", user.getId().toString()); + PageData page = voiceCloneService.pageWithNames(params); + return new Result>().ok(page); + } + + @PostMapping("/upload") + @Operation(summary = "上传音频进行声音克隆") + @Parameters({ + @Parameter(name = "id", description = "声音克隆记录ID", required = true), + @Parameter(name = "voiceFile", description = "音频文件", required = true) + }) + @RequiresPermissions("sys:role:normal") + public Result uploadVoice( + @RequestParam("id") String id, + @RequestParam("voiceFile") MultipartFile voiceFile) { + try { + // 验证文件 + if (voiceFile == null || voiceFile.isEmpty()) { + return new Result().error(ErrorCode.VOICE_CLONE_AUDIO_EMPTY); + } + + // 验证文件类型 + String contentType = voiceFile.getContentType(); + if (contentType == null || !contentType.startsWith("audio/")) { + return new Result().error(ErrorCode.VOICE_CLONE_NOT_AUDIO_FILE); + } + + // 验证文件大小 (最大10MB) + if (voiceFile.getSize() > 10 * 1024 * 1024) { + return new Result().error(ErrorCode.VOICE_CLONE_AUDIO_TOO_LARGE); + } + // 检查权限 + checkPermission(id); + // 调用服务层处理 + voiceCloneService.uploadVoice(id, voiceFile); + + return new Result(); + } catch (Exception e) { + return new Result().error(ErrorCode.VOICE_CLONE_UPLOAD_FAILED, e.getMessage()); + } + } + + @PostMapping("/updateName") + @Operation(summary = "更新声音克隆名称") + @RequiresPermissions("sys:role:normal") + public Result updateName(@RequestBody Map params) { + try { + String id = params.get("id"); + String name = params.get("name"); + + if (id == null || id.isEmpty()) { + return new Result().error(ErrorCode.IDENTIFIER_NOT_NULL, "唯一标识不能为空"); + } + if (name == null) { + return new Result().error(ErrorCode.NOT_NULL, "名称不能为空"); + } + // 检查权限 + checkPermission(id); + + voiceCloneService.updateName(id, name); + return new Result(); + } catch (Exception e) { + return new Result().error(ErrorCode.UPDATE_DATA_FAILED, "更新失败: " + e.getMessage()); + } + } + + @PostMapping("/audio/{id}") + @Operation(summary = "获取音频下载ID") + @RequiresPermissions("sys:role:normal") + public Result getAudioId(@PathVariable("id") String id) { + // 检查权限 + checkPermission(id); + byte[] audioData = voiceCloneService.getVoiceData(id); + if (audioData == null) { + return new Result().error(ErrorCode.RESOURCE_NOT_FOUND, "音频不存在"); + } + String uuid = UUID.randomUUID().toString(); + redisUtils.set(RedisKeys.getVoiceCloneAudioIdKey(uuid), id); + return new Result().ok(uuid); + } + + @GetMapping("/play/{uuid}") + @Operation(summary = "播放音频") + public void playVoice(@PathVariable("uuid") String uuid, HttpServletResponse response) { + try { + String id = (String) redisUtils.get(RedisKeys.getVoiceCloneAudioIdKey(uuid)); + redisUtils.delete(RedisKeys.getVoiceCloneAudioIdKey(uuid)); + if (StringUtils.isBlank(id)) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } + // 获取音频数据 + byte[] voiceData = voiceCloneService.getVoiceData(id); + + if (voiceData == null || voiceData.length == 0) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } + + // 设置响应头 + response.setContentType("audio/wav"); + response.setContentLength(voiceData.length); + response.setHeader("Content-Disposition", "inline; filename=voice.wav"); + + // 写入音频数据 + response.getOutputStream().write(voiceData); + response.getOutputStream().flush(); + } catch (Exception e) { + log.error("播放音频失败", e); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + @PostMapping("/cloneAudio") + @Operation(summary = "复刻音频") + @RequiresPermissions("sys:role:normal") + public Result cloneAudio(@RequestBody Map params) { + String cloneId = params.get("cloneId"); + checkPermission(cloneId); + return new Result(); + } + + private void checkPermission(String id) { + VoiceCloneEntity voiceClone = voiceCloneService.selectById(id); + if (voiceClone == null) { + throw new RenException(ErrorCode.VOICE_CLONE_RECORD_NOT_EXIST); + } + if (!voiceClone.getUserId().equals(SecurityUser.getUser().getId())) { + throw new RenException(ErrorCode.VOICE_RESOURCE_NO_PERMISSION); + } + } +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceResourceController.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceResourceController.java new file mode 100644 index 00000000..eff10c18 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/controller/VoiceResourceController.java @@ -0,0 +1,114 @@ +package xiaozhi.modules.voiceclone.controller; + +import java.util.List; +import java.util.Map; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.exception.ErrorCode; +import xiaozhi.common.page.PageData; +import xiaozhi.common.utils.Result; +import xiaozhi.common.validator.ValidatorUtils; +import xiaozhi.modules.model.service.ModelConfigService; +import xiaozhi.modules.voiceclone.dto.VoiceCloneDTO; +import xiaozhi.modules.voiceclone.dto.VoiceCloneResponseDTO; +import xiaozhi.modules.voiceclone.service.VoiceCloneService; + +@Tag(name = "音色资源管理", description = "音色资源开通相关接口") +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/voiceResource") +public class VoiceResourceController { + + private final VoiceCloneService voiceCloneService; + private final ModelConfigService modelConfigService; + + @GetMapping + @Operation(summary = "分页查询音色资源") + @Parameters({ + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true) + }) + @RequiresPermissions("sys:role:superAdmin") + public Result> page( + @Parameter(hidden = true) @RequestParam Map params) { + ValidatorUtils.validateEntity(params); + PageData page = voiceCloneService.pageWithNames(params); + return new Result>().ok(page); + } + + @GetMapping("{id}") + @Operation(summary = "获取音色资源详情") + @RequiresPermissions("sys:role:superAdmin") + public Result get(@PathVariable("id") String id) { + VoiceCloneResponseDTO data = voiceCloneService.getByIdWithNames(id); + return new Result().ok(data); + } + + @PostMapping + @Operation(summary = "新增音色资源") + @RequiresPermissions("sys:role:superAdmin") + public Result save(@RequestBody VoiceCloneDTO dto) { + if (dto == null) { + return new Result().error(ErrorCode.VOICE_RESOURCE_INFO_EMPTY); + } + if (dto.getModelId() == null || dto.getModelId().isEmpty()) { + return new Result().error(ErrorCode.VOICE_RESOURCE_PLATFORM_NAME_EMPTY); + } + if (dto.getVoiceIds() == null || dto.getVoiceIds().isEmpty()) { + return new Result().error(ErrorCode.VOICE_RESOURCE_ID_EMPTY); + } + if (dto.getUserId() == null) { + return new Result().error(ErrorCode.VOICE_RESOURCE_ACCOUNT_EMPTY); + } + try { + voiceCloneService.save(dto); + return new Result(); + } catch (RuntimeException e) { + return new Result().error(ErrorCode.ADD_DATA_FAILED, e.getMessage()); + } + } + + @DeleteMapping("/{id}") + @Operation(summary = "删除音色资源") + @RequiresPermissions("sys:role:superAdmin") + public Result delete(@PathVariable("id") String[] ids) { + if (ids == null || ids.length == 0) { + return new Result().error(ErrorCode.VOICE_RESOURCE_DELETE_ID_EMPTY); + } + voiceCloneService.delete(ids); + return new Result(); + } + + @GetMapping("/user/{userId}") + @Operation(summary = "根据用户ID获取音色资源列表") + @RequiresPermissions("sys:role:normal") + public Result> getByUserId(@PathVariable("userId") Long userId) { + List list = voiceCloneService.getByUserIdWithNames(userId); + return new Result>().ok(list); + } + + @GetMapping("/ttsPlatforms") + @Operation(summary = "获取TTS平台列表") + @RequiresPermissions("sys:role:superAdmin") + public Result>> getTtsPlatformList() { + List> list = modelConfigService.getTtsPlatformList(); + return new Result>>().ok(list); + } +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dao/VoiceCloneDao.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dao/VoiceCloneDao.java new file mode 100644 index 00000000..f866c46f --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dao/VoiceCloneDao.java @@ -0,0 +1,15 @@ +package xiaozhi.modules.voiceclone.dao; + +import org.apache.ibatis.annotations.Mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import xiaozhi.modules.voiceclone.entity.VoiceCloneEntity; + +/** + * 声音克隆 + */ +@Mapper +public interface VoiceCloneDao extends BaseMapper { + +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneDTO.java new file mode 100644 index 00000000..b65b3f4e --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneDTO.java @@ -0,0 +1,20 @@ +package xiaozhi.modules.voiceclone.dto; + +import java.util.List; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "声音克隆DTO") +public class VoiceCloneDTO { + + @Schema(description = "模型ID") + private String modelId; + + @Schema(description = "音色ID列表") + private List voiceIds; + + @Schema(description = "用户ID") + private Long userId; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneResponseDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneResponseDTO.java new file mode 100644 index 00000000..98e4ad7c --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/dto/VoiceCloneResponseDTO.java @@ -0,0 +1,48 @@ +package xiaozhi.modules.voiceclone.dto; + +import java.util.Date; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 声音克隆响应DTO + * 用于向前端展示声音克隆信息,包含模型名称和用户名称 + */ +@Data +@Schema(description = "声音克隆响应DTO") +public class VoiceCloneResponseDTO { + + @Schema(description = "唯一标识") + private String id; + + @Schema(description = "声音名称") + private String name; + + @Schema(description = "模型id") + private String modelId; + + @Schema(description = "模型名称") + private String modelName; + + @Schema(description = "声音id") + private String voiceId; + + @Schema(description = "用户ID(关联用户表)") + private Long userId; + + @Schema(description = "用户名称") + private String userName; + + @Schema(description = "训练状态:0待训练 1训练中 2训练成功 3训练失败") + private Integer trainStatus; + + @Schema(description = "训练错误原因") + private String trainError; + + @Schema(description = "创建时间") + private Date createDate; + + @Schema(description = "是否有音频数据") + private Boolean hasVoice; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/entity/VoiceCloneEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/entity/VoiceCloneEntity.java new file mode 100644 index 00000000..9ca1ab76 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/entity/VoiceCloneEntity.java @@ -0,0 +1,53 @@ +package xiaozhi.modules.voiceclone.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("ai_voice_clone") +@Schema(description = "声音克隆") +public class VoiceCloneEntity { + + @TableId(type = IdType.ASSIGN_UUID) + @Schema(description = "唯一标识") + private String id; + + @Schema(description = "声音名称") + private String name; + + @Schema(description = "模型id") + private String modelId; + + @Schema(description = "声音id") + private String voiceId; + + @Schema(description = "用户 ID(关联用户表)") + private Long userId; + + @Schema(description = "声音") + private byte[] voice; + + @Schema(description = "训练状态:0待训练 1训练中 2训练成功 3训练失败") + private Integer trainStatus; + + @Schema(description = "训练错误原因") + private String trainError; + + @Schema(description = "创建者") + @TableField(fill = FieldFill.INSERT) + private Long creator; + + @Schema(description = "创建时间") + @TableField(fill = FieldFill.INSERT) + private Date createDate; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/VoiceCloneService.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/VoiceCloneService.java new file mode 100644 index 00000000..bdfd5ed0 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/VoiceCloneService.java @@ -0,0 +1,68 @@ +package xiaozhi.modules.voiceclone.service; + +import java.util.List; +import java.util.Map; + +import org.springframework.web.multipart.MultipartFile; + +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.BaseService; +import xiaozhi.modules.voiceclone.dto.VoiceCloneDTO; +import xiaozhi.modules.voiceclone.dto.VoiceCloneResponseDTO; +import xiaozhi.modules.voiceclone.entity.VoiceCloneEntity; + +/** + * 声音克隆管理 + */ +public interface VoiceCloneService extends BaseService { + + /** + * 分页查询 + */ + PageData page(Map params); + + /** + * 保存声音克隆 + */ + void save(VoiceCloneDTO dto); + + /** + * 批量删除 + */ + void delete(String[] ids); + + /** + * 根据用户ID查询声音克隆列表 + */ + List getByUserId(Long userId); + + /** + * 分页查询带模型名称和用户名称的声音克隆列表 + */ + PageData pageWithNames(Map params); + + /** + * 根据ID查询带模型名称和用户名称的声音克隆信息 + */ + VoiceCloneResponseDTO getByIdWithNames(String id); + + /** + * 根据用户ID查询带模型名称的声音克隆列表 + */ + List getByUserIdWithNames(Long userId); + + /** + * 上传音频文件 + */ + void uploadVoice(String id, MultipartFile voiceFile) throws Exception; + + /** + * 更新声音克隆名称 + */ + void updateName(String id, String name); + + /** + * 获取音频数据 + */ + byte[] getVoiceData(String id); +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/impl/VoiceCloneServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/impl/VoiceCloneServiceImpl.java new file mode 100644 index 00000000..32b3c88f --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/voiceclone/service/impl/VoiceCloneServiceImpl.java @@ -0,0 +1,210 @@ +package xiaozhi.modules.voiceclone.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; + +import lombok.RequiredArgsConstructor; +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.impl.BaseServiceImpl; +import xiaozhi.common.utils.ConvertUtils; +import xiaozhi.common.utils.DateUtils; +import xiaozhi.common.exception.ErrorCode; +import xiaozhi.common.exception.RenException; +import xiaozhi.modules.model.service.ModelConfigService; +import xiaozhi.modules.sys.service.SysUserService; +import xiaozhi.modules.voiceclone.dao.VoiceCloneDao; +import xiaozhi.modules.voiceclone.dto.VoiceCloneDTO; +import xiaozhi.modules.voiceclone.dto.VoiceCloneResponseDTO; +import xiaozhi.modules.voiceclone.entity.VoiceCloneEntity; +import xiaozhi.modules.voiceclone.service.VoiceCloneService; + +@Service +@RequiredArgsConstructor +public class VoiceCloneServiceImpl extends BaseServiceImpl + implements VoiceCloneService { + + private final ModelConfigService modelConfigService; + private final SysUserService sysUserService; + + @Override + public PageData page(Map params) { + IPage page = baseDao.selectPage( + getPage(params, "create_date", true), + getWrapper(params)); + + return new PageData<>(page.getRecords(), page.getTotal()); + } + + private QueryWrapper getWrapper(Map params) { + String name = (String) params.get("name"); + String userId = (String) params.get("userId"); + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq(StringUtils.isNotBlank(userId), "user_id", userId); + if (StringUtils.isNotBlank(name)) { + wrapper.and(w -> w.like("name", name) + .or().eq("voice_id", name)); + } + return wrapper; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(VoiceCloneDTO dto) { + // 遍历选择的音色ID,为每个音色ID创建一条记录 + int index = 0; + String namePrefix = DateUtils.format(new java.util.Date(), "MMddHHmm"); + for (String voiceId : dto.getVoiceIds()) { + index++; + VoiceCloneEntity entity = new VoiceCloneEntity(); + entity.setModelId(dto.getModelId()); + entity.setVoiceId(voiceId); + entity.setName(namePrefix + "_" + index); + entity.setUserId(dto.getUserId()); + entity.setTrainStatus(0); // 默认训练中 + + baseDao.insert(entity); + } + } + + @Override + public void delete(String[] ids) { + baseDao.deleteBatchIds(Arrays.asList(ids)); + } + + @Override + public List getByUserId(Long userId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + wrapper.orderByDesc("created_at"); + return baseDao.selectList(wrapper); + } + + @Override + public PageData pageWithNames(Map params) { + // 先查询分页数据 + IPage page = baseDao.selectPage( + getPage(params, "create_date", true), + getWrapper(params)); + + // 将实体列表转换为DTO列表 + List dtoList = convertToResponseDTOList(page.getRecords()); + + return new PageData<>(dtoList, page.getTotal()); + } + + @Override + public VoiceCloneResponseDTO getByIdWithNames(String id) { + VoiceCloneEntity entity = baseDao.selectById(id); + if (entity == null) { + return null; + } + + VoiceCloneResponseDTO dto = ConvertUtils.sourceToTarget(entity, VoiceCloneResponseDTO.class); + + // 设置模型名称 + if (StringUtils.isNotBlank(entity.getModelId())) { + dto.setModelName(modelConfigService.getModelNameById(entity.getModelId())); + } + + // 设置用户名称 + if (entity.getUserId() != null) { + dto.setUserName(sysUserService.getByUserId(entity.getUserId()).getUsername()); + } + + return dto; + } + + @Override + public List getByUserIdWithNames(Long userId) { + List entityList = getByUserId(userId); + return convertToResponseDTOList(entityList); + } + + /** + * 将VoiceCloneEntity列表转换为VoiceCloneResponseDTO列表 + */ + private List convertToResponseDTOList(List entityList) { + if (entityList == null || entityList.isEmpty()) { + return new ArrayList<>(); + } + + List dtoList = new ArrayList<>(entityList.size()); + + // 转换每个实体为DTO + for (VoiceCloneEntity entity : entityList) { + VoiceCloneResponseDTO dto = ConvertUtils.sourceToTarget(entity, VoiceCloneResponseDTO.class); + + // 设置模型名称 + if (StringUtils.isNotBlank(entity.getModelId())) { + dto.setModelName(modelConfigService.getModelNameById(entity.getModelId())); + } + + // 设置用户名称 + if (entity.getUserId() != null) { + dto.setUserName(sysUserService.getByUserId(entity.getUserId()).getUsername()); + } + + // 设置是否有音频数据 + dto.setHasVoice(entity.getVoice() != null); + + dtoList.add(dto); + } + + return dtoList; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void uploadVoice(String id, MultipartFile voiceFile) throws Exception { + // 查询声音克隆记录 + VoiceCloneEntity entity = baseDao.selectById(id); + if (entity == null) { + throw new RenException(ErrorCode.VOICE_CLONE_RECORD_NOT_EXIST); + } + + // 读取音频文件并转为字节数组 + byte[] voiceData = voiceFile.getBytes(); + + // 更新voice字段 + entity.setVoice(voiceData); + // 更新训练状态为待训练 + entity.setTrainStatus(0); + + // 保存到数据库 + baseDao.updateById(entity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateName(String id, String name) { + // 查询声音克隆记录 + VoiceCloneEntity entity = baseDao.selectById(id); + if (entity == null) { + throw new RenException(ErrorCode.VOICE_CLONE_RECORD_NOT_EXIST); + } + + // 更新名称 + entity.setName(name); + baseDao.updateById(entity); + } + + @Override + public byte[] getVoiceData(String id) { + VoiceCloneEntity entity = baseDao.selectById(id); + if (entity == null) { + return null; + } + return entity.getVoice(); + } +} diff --git a/main/manager-api/src/main/resources/db/changelog/202510071521.sql b/main/manager-api/src/main/resources/db/changelog/202510071521.sql new file mode 100644 index 00000000..06ffa006 --- /dev/null +++ b/main/manager-api/src/main/resources/db/changelog/202510071521.sql @@ -0,0 +1,15 @@ +-- 声音克隆表 +DROP TABLE IF EXISTS `ai_voice_clone`; +CREATE TABLE `ai_voice_clone` ( + `id` VARCHAR(32) NOT NULL COMMENT '唯一标识', + `name` VARCHAR(64) COMMENT '声音名称', + `model_id` VARCHAR(32) COMMENT '模型id', + `voice_id` VARCHAR(32) COMMENT '声音id', + `user_id` BIGINT COMMENT '用户 ID(关联用户表)', + `voice` LONGBLOB COMMENT '声音', + `train_status` TINYINT(1) DEFAULT 0 COMMENT '训练状态:0待训练 1训练中 2训练成功 3训练失败', + `train_error` VARCHAR(255) COMMENT '训练错误原因', + `creator` BIGINT COMMENT '创建者 ID', + `create_date` DATETIME COMMENT '创建时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='声音克隆表'; \ No newline at end of file diff --git a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml index 3289d69f..b3845b4d 100755 --- a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml @@ -388,3 +388,10 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202509220958.sql + - changeSet: + id: 202510071521 + author: hrz + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202510071521.sql diff --git a/main/manager-api/src/main/resources/i18n/messages.properties b/main/manager-api/src/main/resources/i18n/messages.properties index 265ab0cf..816a1a8b 100644 --- a/main/manager-api/src/main/resources/i18n/messages.properties +++ b/main/manager-api/src/main/resources/i18n/messages.properties @@ -1,146 +1,157 @@ -#简体中文 -500=服务器内部异常 -401=未授权 -403=拒绝访问,没有权限 +#\u7B80\u4F53\u4E2D\u6587 +500=\u670D\u52A1\u5668\u5185\u90E8\u5F02\u5E38 +401=\u672A\u6388\u6743 +403=\u62D2\u7EDD\u8BBF\u95EE\uFF0C\u6CA1\u6709\u6743\u9650 -10001={0}不能为空 -10002=数据库中已存在该记录 -10003=获取参数失败 -10004=账号或密码错误 -10005=账号已被停用 -10006=唯一标识不能为空 -10007=验证码不正确 -10008=先删除子菜单或按钮 -10009=原密码不正确 -10010=账号或密码不正确,您还有可以尝试{0}次 +10001={0}\u4E0D\u80FD\u4E3A\u7A7A +10002=\u6570\u636E\u5E93\u4E2D\u5DF2\u5B58\u5728\u8BE5\u8BB0\u5F55 +10003=\u83B7\u53D6\u53C2\u6570\u5931\u8D25 +10004=\u8D26\u53F7\u6216\u5BC6\u7801\u9519\u8BEF +10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528 +10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A +10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E +10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE +10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E +10010=\u8D26\u53F7\u6216\u5BC6\u7801\u4E0D\u6B63\u786E,\u60A8\u8FD8\u6709\u53EF\u4EE5\u5C1D\u8BD5{0}\u6B21 -10011=上级部门选择错误 -10012=上级菜单不能为自身 -10013=数据权限接口,只能是Map类型参数 -10014=请先删除下级部门 -10015=请先删除部门下的用户 -10016=部署失败,没有流程 -10017=模型图不正确,请检查 -10018=导出失败,模型ID为{0} +10011=\u4E0A\u7EA7\u90E8\u95E8\u9009\u62E9\u9519\u8BEF +10012=\u4E0A\u7EA7\u83DC\u5355\u4E0D\u80FD\u4E3A\u81EA\u8EAB +10013=\u6570\u636E\u6743\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u7C7B\u578B\u53C2\u6570 +10014=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u90E8\u95E8 +10015=\u8BF7\u5148\u5220\u9664\u90E8\u95E8\u4E0B\u7684\u7528\u6237 +10016=\u90E8\u7F72\u5931\u8D25\uFF0C\u6CA1\u6709\u6D41\u7A0B +10017=\u6A21\u578B\u56FE\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5 +10018=\u5BFC\u51FA\u5931\u8D25\uFF0C\u6A21\u578BID\u4E3A{0} -10019=请上传文件 -10020=token不能为空 -10021=token失效,请重新登录 -10022=账号已被锁定 -10023=请上传zip、bar、bpmn、bpmn20.xml格式文件 +10019=\u8BF7\u4E0A\u4F20\u6587\u4EF6 +10020=token\u4E0D\u80FD\u4E3A\u7A7A +10021=token\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55 +10022=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A +10023=\u8BF7\u4E0A\u4F20zip\u3001bar\u3001bpmn\u3001bpmn20.xml\u683C\u5F0F\u6587\u4EF6 -10024=上传文件失败{0} -10025=发送短信失败{0} -10026=邮件模板不存在 +10024=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25{0} +10025=\u53D1\u9001\u77ED\u4FE1\u5931\u8D25{0} +10026=\u90AE\u4EF6\u6A21\u677F\u4E0D\u5B58\u5728 -10027=Redis服务异常 -10028=定时任务失败 -10029=不能包含非法字符 -10030=密码长度不足{0}位 -10031=密码必须同时包含数字、大小写字母和特殊字符组成 -10032=删除本数据异常 -10033=设备验证码错误 +10027=Redis\u670D\u52A1\u5F02\u5E38 +10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25 +10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26 +10030=\u5BC6\u7801\u957F\u5EA6\u4E0D\u8DB3{0}\u4F4D +10031=\u5BC6\u7801\u5FC5\u987B\u540C\u65F6\u5305\u542B\u6570\u5B57\u3001\u5927\u5C0F\u5199\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\u7EC4\u6210 +10032=\u5220\u9664\u672C\u6570\u636E\u5F02\u5E38 +10033=\u8BBE\u5907\u9A8C\u8BC1\u7801\u9519\u8BEF -10034=参数值不能为空 -10035=参数类型不能为空 -10036=不支持的参数类型 -10037=参数值必须是有效的数字 -10038=参数值必须是true或false -10039=参数值必须是有效的JSON数组格式 -10040=参数值必须是有效的JSON格式 +10034=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A +10035=\u53C2\u6570\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A +10036=\u4E0D\u652F\u6301\u7684\u53C2\u6570\u7C7B\u578B +10037=\u53C2\u6570\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684\u6570\u5B57 +10038=\u53C2\u6570\u503C\u5FC5\u987B\u662Ftrue\u6216false +10039=\u53C2\u6570\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684JSON\u6570\u7EC4\u683C\u5F0F +10040=\u53C2\u6570\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684JSON\u683C\u5F0F -10041=设备未找到 +10041=\u8BBE\u5907\u672A\u627E\u5230 10042={0} -10043=删除数据失败 -10044=用户未登录 -10045=WebSocket连接失败或连接超时 -10046=保存声纹错误,请联系管理员 -10047=每日发送次数已达上限 -10048=旧密码输入错误 -10049=设置的LLM不是openai和ollama -10050=token生成失败 -10051=资源不存在 -10052=默认智能体未找到 -10053=智能体未找到 -10054=声纹接口未配置,请先在参数配置中配置声纹接口地址(server.voice_print) -10055=短信发送失败 -10056=短信连接建立失败 -10057=智能体的声纹创建失败 -10058=智能体的对应声纹更新失败 -10059=智能体的对应声纹删除失败 -10060=发送太频繁,请{0}秒后再试 -10061=激活码不能为空 -10062=激活码错误 -10063=设备已激活 -10064=该模型为默认模型,请先设置其他模型为默认模型 -10065=新增数据失败 -10066=修改数据失败 -10067=图形验证码错误 -10068=没有开启手机注册,没法使用短信验证码功能 -10069=用户名不是手机号码,请重新输入 -10070=此手机号码已经注册过 -10071=输入的手机号码未注册 -10072=当前不允许普通用户注册 -10073=没有开启手机注册,没法使用找回密码功能 -10074=输入的手机号码格式不正确 -10075=输入的手机验证码错误 -10076=字典类型不存在 -10077=字典类型编码重复 -10078=读取资源失败 -10079=LLM大模型和Intent意图识别,选择参数不匹配 -10080=此声音声纹对应的人({0})已经注册,请选择其他声音注册 -10081=删除声纹出现错误 -10082=此次修改不允许,此声音已经注册为声纹了({0}) -10083=修改声纹错误,请联系管理员 -10084=声纹接口地址存在错误,请进入参数管理修改声纹接口地址 -10085=音频数据不属于这个智能体 -10086=音频数据是空的请检查上传数据 -10087=声纹保存失败,请求不成功 -10088=声纹保存失败,请求处理失败 -10089=声纹注销失败,请求不成功 -10090=声纹注销失败,请求处理失败 -10091=供应器不存在 -10092=设置的LLM不存在 -10093=该模型配置已被智能体{0}引用,无法删除 -10094=该LLM模型已被意图识别配置引用,无法删除 -10095=无效服务端操作 -10096=未配置服务端WebSocket地址 -10097=目标WebSocket地址不存在 -10098=WebSocket地址列表不能为空 -10099=WebSocket地址不能使用localhost或127.0.0.1 -10100=WebSocket地址格式不正确 -10101=WebSocket连接测试失败 -10102=OTA地址不能为空 -10103=OTA地址不能使用localhost或127.0.0.1 -10104=OTA地址必须以http或https开头 -10105=OTA地址必须以/ota/结尾 -10106=OTA接口访问失败 -10107=OTA接口返回内容格式不正确 -10108=OTA接口验证失败 -10109=MCP地址不能为空 -10110=MCP地址不能使用localhost或127.0.0.1 -10111=不是正确的MCP地址 -10112=MCP接口访问失败 -10113=MCP接口返回内容格式不正确 -10114=MCP接口验证失败 -10115=声纹接口地址不能为空 -10116=声纹接口地址不能使用localhost或127.0.0.1 -10117=不是正确的声纹接口地址 -10118=声纹接口地址必须以http或https开头 -10119=声纹接口访问失败 -10120=声纹接口返回内容格式不正确 -10121=声纹接口验证失败 -10122=mqtt密钥不能为空 -10123=您的mqtt密钥长度不安全,字符数需要至少8个字符且必须同时包含大小写字母 -10124=您的mqtt密钥长度不安全,mqtt密钥必须同时包含大小写字母 -10125=您的mqtt密钥包含弱密码 -10128=字典标签重复 -10129=modelType和provideCode不能为空 -10132=没有权限查看该智能体的聊天记录 -10133=会话ID不能为空 -10134=智能体ID不能为空 -10135=聊天记录下载失败 -10136=下载链接已过期或无效 -10137=下载链接无效 -10138=用户 -10139=智体 \ No newline at end of file +10043=\u5220\u9664\u6570\u636E\u5931\u8D25 +10044=\u7528\u6237\u672A\u767B\u5F55 +10045=WebSocket\u8FDE\u63A5\u5931\u8D25\u6216\u8FDE\u63A5\u8D85\u65F6 +10046=\u4FDD\u5B58\u58F0\u7EB9\u9519\u8BEF\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458 +10047=\u6BCF\u65E5\u53D1\u9001\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650 +10048=\u65E7\u5BC6\u7801\u8F93\u5165\u9519\u8BEF +10049=\u8BBE\u7F6E\u7684LLM\u4E0D\u662Fopenai\u548Collama +10050=token\u751F\u6210\u5931\u8D25 +10051=\u8D44\u6E90\u4E0D\u5B58\u5728 +10052=\u9ED8\u8BA4\u667A\u80FD\u4F53\u672A\u627E\u5230 +10053=\u667A\u80FD\u4F53\u672A\u627E\u5230 +10054=\u58F0\u7EB9\u63A5\u53E3\u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u53C2\u6570\u914D\u7F6E\u4E2D\u914D\u7F6E\u58F0\u7EB9\u63A5\u53E3\u5730\u5740(server.voice_print) +10055=\u77ED\u4FE1\u53D1\u9001\u5931\u8D25 +10056=\u77ED\u4FE1\u8FDE\u63A5\u5EFA\u7ACB\u5931\u8D25 +10057=\u667A\u80FD\u4F53\u7684\u58F0\u7EB9\u521B\u5EFA\u5931\u8D25 +10058=\u667A\u80FD\u4F53\u7684\u5BF9\u5E94\u58F0\u7EB9\u66F4\u65B0\u5931\u8D25 +10059=\u667A\u80FD\u4F53\u7684\u5BF9\u5E94\u58F0\u7EB9\u5220\u9664\u5931\u8D25 +10060=\u53D1\u9001\u592A\u9891\u7E41\uFF0C\u8BF7{0}\u79D2\u540E\u518D\u8BD5 +10061=\u6FC0\u6D3B\u7801\u4E0D\u80FD\u4E3A\u7A7A +10062=\u6FC0\u6D3B\u7801\u9519\u8BEF +10063=\u8BBE\u5907\u5DF2\u6FC0\u6D3B +10064=\u8BE5\u6A21\u578B\u4E3A\u9ED8\u8BA4\u6A21\u578B\uFF0C\u8BF7\u5148\u8BBE\u7F6E\u5176\u4ED6\u6A21\u578B\u4E3A\u9ED8\u8BA4\u6A21\u578B +10065=\u65B0\u589E\u6570\u636E\u5931\u8D25 +10066=\u4FEE\u6539\u6570\u636E\u5931\u8D25 +10067=\u56FE\u5F62\u9A8C\u8BC1\u7801\u9519\u8BEF +10068=\u6CA1\u6709\u5F00\u542F\u624B\u673A\u6CE8\u518C\uFF0C\u6CA1\u6CD5\u4F7F\u7528\u77ED\u4FE1\u9A8C\u8BC1\u7801\u529F\u80FD +10069=\u7528\u6237\u540D\u4E0D\u662F\u624B\u673A\u53F7\u7801\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165 +10070=\u6B64\u624B\u673A\u53F7\u7801\u5DF2\u7ECF\u6CE8\u518C\u8FC7 +10071=\u8F93\u5165\u7684\u624B\u673A\u53F7\u7801\u672A\u6CE8\u518C +10072=\u5F53\u524D\u4E0D\u5141\u8BB8\u666E\u901A\u7528\u6237\u6CE8\u518C +10073=\u6CA1\u6709\u5F00\u542F\u624B\u673A\u6CE8\u518C\uFF0C\u6CA1\u6CD5\u4F7F\u7528\u627E\u56DE\u5BC6\u7801\u529F\u80FD +10074=\u8F93\u5165\u7684\u624B\u673A\u53F7\u7801\u683C\u5F0F\u4E0D\u6B63\u786E +10075=\u8F93\u5165\u7684\u624B\u673A\u9A8C\u8BC1\u7801\u9519\u8BEF +10076=\u5B57\u5178\u7C7B\u578B\u4E0D\u5B58\u5728 +10077=\u5B57\u5178\u7C7B\u578B\u7F16\u7801\u91CD\u590D +10078=\u8BFB\u53D6\u8D44\u6E90\u5931\u8D25 +10079=LLM\u5927\u6A21\u578B\u548CIntent\u610F\u56FE\u8BC6\u522B\uFF0C\u9009\u62E9\u53C2\u6570\u4E0D\u5339\u914D +10080=\u6B64\u58F0\u97F3\u58F0\u7EB9\u5BF9\u5E94\u7684\u4EBA\uFF08{0}\uFF09\u5DF2\u7ECF\u6CE8\u518C\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u58F0\u97F3\u6CE8\u518C +10081=\u5220\u9664\u58F0\u7EB9\u51FA\u73B0\u9519\u8BEF +10082=\u6B64\u6B21\u4FEE\u6539\u4E0D\u5141\u8BB8\uFF0C\u6B64\u58F0\u97F3\u5DF2\u7ECF\u6CE8\u518C\u4E3A\u58F0\u7EB9\u4E86\uFF08{0}\uFF09 +10083=\u4FEE\u6539\u58F0\u7EB9\u9519\u8BEF\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458 +10084=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u5B58\u5728\u9519\u8BEF\uFF0C\u8BF7\u8FDB\u5165\u53C2\u6570\u7BA1\u7406\u4FEE\u6539\u58F0\u7EB9\u63A5\u53E3\u5730\u5740 +10085=\u97F3\u9891\u6570\u636E\u4E0D\u5C5E\u4E8E\u8FD9\u4E2A\u667A\u80FD\u4F53 +10086=\u97F3\u9891\u6570\u636E\u662F\u7A7A\u7684\u8BF7\u68C0\u67E5\u4E0A\u4F20\u6570\u636E +10087=\u58F0\u7EB9\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u6C42\u4E0D\u6210\u529F +10088=\u58F0\u7EB9\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u6C42\u5904\u7406\u5931\u8D25 +10089=\u58F0\u7EB9\u6CE8\u9500\u5931\u8D25\uFF0C\u8BF7\u6C42\u4E0D\u6210\u529F +10090=\u58F0\u7EB9\u6CE8\u9500\u5931\u8D25\uFF0C\u8BF7\u6C42\u5904\u7406\u5931\u8D25 +10091=\u4F9B\u5E94\u5668\u4E0D\u5B58\u5728 +10092=\u8BBE\u7F6E\u7684LLM\u4E0D\u5B58\u5728 +10093=\u8BE5\u6A21\u578B\u914D\u7F6E\u5DF2\u88AB\u667A\u80FD\u4F53{0}\u5F15\u7528\uFF0C\u65E0\u6CD5\u5220\u9664 +10094=\u8BE5LLM\u6A21\u578B\u5DF2\u88AB\u610F\u56FE\u8BC6\u522B\u914D\u7F6E\u5F15\u7528\uFF0C\u65E0\u6CD5\u5220\u9664 +10095=\u65E0\u6548\u670D\u52A1\u7AEF\u64CD\u4F5C +10096=\u672A\u914D\u7F6E\u670D\u52A1\u7AEFWebSocket\u5730\u5740 +10097=\u76EE\u6807WebSocket\u5730\u5740\u4E0D\u5B58\u5728 +10098=WebSocket\u5730\u5740\u5217\u8868\u4E0D\u80FD\u4E3A\u7A7A +10099=WebSocket\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10100=WebSocket\u5730\u5740\u683C\u5F0F\u4E0D\u6B63\u786E +10101=WebSocket\u8FDE\u63A5\u6D4B\u8BD5\u5931\u8D25 +10102=OTA\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A +10103=OTA\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10104=OTA\u5730\u5740\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934 +10105=OTA\u5730\u5740\u5FC5\u987B\u4EE5/ota/\u7ED3\u5C3E +10106=OTA\u63A5\u53E3\u8BBF\u95EE\u5931\u8D25 +10107=OTA\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u683C\u5F0F\u4E0D\u6B63\u786E +10108=OTA\u63A5\u53E3\u9A8C\u8BC1\u5931\u8D25 +10109=MCP\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A +10110=MCP\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10111=\u4E0D\u662F\u6B63\u786E\u7684MCP\u5730\u5740 +10112=MCP\u63A5\u53E3\u8BBF\u95EE\u5931\u8D25 +10113=MCP\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u683C\u5F0F\u4E0D\u6B63\u786E +10114=MCP\u63A5\u53E3\u9A8C\u8BC1\u5931\u8D25 +10115=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A +10116=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10117=\u4E0D\u662F\u6B63\u786E\u7684\u58F0\u7EB9\u63A5\u53E3\u5730\u5740 +10118=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934 +10119=\u58F0\u7EB9\u63A5\u53E3\u8BBF\u95EE\u5931\u8D25 +10120=\u58F0\u7EB9\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u683C\u5F0F\u4E0D\u6B63\u786E +10121=\u58F0\u7EB9\u63A5\u53E3\u9A8C\u8BC1\u5931\u8D25 +10122=mqtt\u5BC6\u94A5\u4E0D\u80FD\u4E3A\u7A7A +10123=\u60A8\u7684mqtt\u5BC6\u94A5\u957F\u5EA6\u4E0D\u5B89\u5168\uFF0C\u5B57\u7B26\u6570\u9700\u8981\u81F3\u5C118\u4E2A\u5B57\u7B26\u4E14\u5FC5\u987B\u540C\u65F6\u5305\u542B\u5927\u5C0F\u5199\u5B57\u6BCD +10124=\u60A8\u7684mqtt\u5BC6\u94A5\u957F\u5EA6\u4E0D\u5B89\u5168\uFF0Cmqtt\u5BC6\u94A5\u5FC5\u987B\u540C\u65F6\u5305\u542B\u5927\u5C0F\u5199\u5B57\u6BCD +10125=\u60A8\u7684mqtt\u5BC6\u94A5\u5305\u542B\u5F31\u5BC6\u7801 +10128=\u5B57\u5178\u6807\u7B7E\u91CD\u590D +10129=modelType\u548CprovideCode\u4E0D\u80FD\u4E3A\u7A7A +10132=\u6CA1\u6709\u6743\u9650\u67E5\u770B\u8BE5\u667A\u80FD\u4F53\u7684\u804A\u5929\u8BB0\u5F55 +10133=\u4F1A\u8BDDID\u4E0D\u80FD\u4E3A\u7A7A +10134=\u667A\u80FD\u4F53ID\u4E0D\u80FD\u4E3A\u7A7A +10135=\u804A\u5929\u8BB0\u5F55\u4E0B\u8F7D\u5931\u8D25 +10136=\u4E0B\u8F7D\u94FE\u63A5\u5DF2\u8FC7\u671F\u6216\u65E0\u6548 +10137=\u4E0B\u8F7D\u94FE\u63A5\u65E0\u6548 +10138=\u7528\u6237 +10139=\u667A\u4F53 +10140=\u97F3\u9891\u6587\u4EF6\u4E0D\u80FD\u4E3A\u7A7A +10141=\u53EA\u652F\u6301\u97F3\u9891\u6587\u4EF6 +10142=\u97F3\u9891\u6587\u4EF6\u5927\u5C0F\u4E0D\u80FD\u8D85\u8FC710MB +10143=\u4E0A\u4F20\u5931\u8D25 +10144=\u58F0\u97F3\u514B\u9686\u8BB0\u5F55\u4E0D\u5B58\u5728 +10145=\u97F3\u8272\u8D44\u6E90\u4FE1\u606F\u4E0D\u80FD\u4E3A\u7A7A +10146=\u5E73\u53F0\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A +10147=\u97F3\u8272ID\u4E0D\u80FD\u4E3A\u7A7A +10148=\u5F52\u5C5E\u8D26\u53F7\u4E0D\u80FD\u4E3A\u7A7A +10149=\u5220\u9664\u7684\u97F3\u8272\u8D44\u6E90ID\u4E0D\u80FD\u4E3A\u7A7A +10150=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55 \ No newline at end of file diff --git a/main/manager-api/src/main/resources/i18n/messages_en_US.properties b/main/manager-api/src/main/resources/i18n/messages_en_US.properties index 49fdc144..d338896c 100644 --- a/main/manager-api/src/main/resources/i18n/messages_en_US.properties +++ b/main/manager-api/src/main/resources/i18n/messages_en_US.properties @@ -145,4 +145,15 @@ 10136=Download link expired or invalid 10137=Download link invalid 10138=User -10139=Agent \ No newline at end of file +10139=Agent +10140=Audio file cannot be empty +10141=Only audio files are supported +10142=Audio file size cannot exceed 10MB +10143=Upload failed +10144=Voice clone record does not exist +10145=Voice resource information cannot be empty +10146=TTS platform name cannot be empty +10147=Voice ID cannot be empty +10148=Owner account cannot be empty +10149=Voice resource ID to delete cannot be empty +10150=You do not have permission to operate this record \ No newline at end of file diff --git a/main/manager-api/src/main/resources/i18n/messages_zh_CN.properties b/main/manager-api/src/main/resources/i18n/messages_zh_CN.properties index 7695fdf2..175de703 100644 --- a/main/manager-api/src/main/resources/i18n/messages_zh_CN.properties +++ b/main/manager-api/src/main/resources/i18n/messages_zh_CN.properties @@ -1,148 +1,159 @@ -#简体中文 -500=服务器内部异常 -401=未授权 -403=拒绝访问,没有权限 +#\u7B80\u4F53\u4E2D\u6587 +500=\u670D\u52A1\u5668\u5185\u90E8\u5F02\u5E38 +401=\u672A\u6388\u6743 +403=\u62D2\u7EDD\u8BBF\u95EE\uFF0C\u6CA1\u6709\u6743\u9650 -10001={0}不能为空 -10002=数据库中已存在该记录 -10003=获取参数失败 -10004=账号或密码错误 -10005=账号已被停用 -10006=唯一标识不能为空 -10007=验证码不正确 -10008=先删除子菜单或按钮 -10009=原密码不正确 -10010=账号或密码不正确,您还有可以尝试{0}次 +10001={0}\u4E0D\u80FD\u4E3A\u7A7A +10002=\u6570\u636E\u5E93\u4E2D\u5DF2\u5B58\u5728\u8BE5\u8BB0\u5F55 +10003=\u83B7\u53D6\u53C2\u6570\u5931\u8D25 +10004=\u8D26\u53F7\u6216\u5BC6\u7801\u9519\u8BEF +10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528 +10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A +10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E +10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE +10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E +10010=\u8D26\u53F7\u6216\u5BC6\u7801\u4E0D\u6B63\u786E,\u60A8\u8FD8\u6709\u53EF\u4EE5\u5C1D\u8BD5{0}\u6B21 -10011=上级部门选择错误 -10012=上级菜单不能为自身 -10013=数据权限接口,只能是Map类型参数 -10014=请先删除下级部门 -10015=请先删除部门下的用户 -10016=部署失败,没有流程 -10017=模型图不正确,请检查 -10018=导出失败,模型ID为{0} +10011=\u4E0A\u7EA7\u90E8\u95E8\u9009\u62E9\u9519\u8BEF +10012=\u4E0A\u7EA7\u83DC\u5355\u4E0D\u80FD\u4E3A\u81EA\u8EAB +10013=\u6570\u636E\u6743\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u7C7B\u578B\u53C2\u6570 +10014=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u90E8\u95E8 +10015=\u8BF7\u5148\u5220\u9664\u90E8\u95E8\u4E0B\u7684\u7528\u6237 +10016=\u90E8\u7F72\u5931\u8D25\uFF0C\u6CA1\u6709\u6D41\u7A0B +10017=\u6A21\u578B\u56FE\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5 +10018=\u5BFC\u51FA\u5931\u8D25\uFF0C\u6A21\u578BID\u4E3A{0} -10019=请上传文件 -10020=token不能为空 -10021=token失效,请重新登录 -10022=账号已被锁定 -10023=请上传zip、bar、bpmn、bpmn20.xml格式文件 +10019=\u8BF7\u4E0A\u4F20\u6587\u4EF6 +10020=token\u4E0D\u80FD\u4E3A\u7A7A +10021=token\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55 +10022=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A +10023=\u8BF7\u4E0A\u4F20zip\u3001bar\u3001bpmn\u3001bpmn20.xml\u683C\u5F0F\u6587\u4EF6 -10024=上传文件失败{0} -10025=发送短信失败{0} -10026=邮件模板不存在 +10024=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25{0} +10025=\u53D1\u9001\u77ED\u4FE1\u5931\u8D25{0} +10026=\u90AE\u4EF6\u6A21\u677F\u4E0D\u5B58\u5728 -10027=Redis服务异常 -10028=定时任务失败 -10029=不能包含非法字符 -10030=密码长度不足{0}位 -10031=密码必须同时包含数字、大小写字母和特殊字符组成 -10032=删除本数据异常 -10033=设备验证码错误 +10027=Redis\u670D\u52A1\u5F02\u5E38 +10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25 +10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26 +10030=\u5BC6\u7801\u957F\u5EA6\u4E0D\u8DB3{0}\u4F4D +10031=\u5BC6\u7801\u5FC5\u987B\u540C\u65F6\u5305\u542B\u6570\u5B57\u3001\u5927\u5C0F\u5199\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\u7EC4\u6210 +10032=\u5220\u9664\u672C\u6570\u636E\u5F02\u5E38 +10033=\u8BBE\u5907\u9A8C\u8BC1\u7801\u9519\u8BEF -10034=参数值不能为空 -10035=参数类型不能为空 -10036=不支持的参数类型 -10037=参数值必须是有效的数字 -10038=参数值必须是true或false -10039=参数值必须是有效的JSON数组格式 -10040=参数值必须是有效的JSON格式 +10034=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A +10035=\u53C2\u6570\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A +10036=\u4E0D\u652F\u6301\u7684\u53C2\u6570\u7C7B\u578B +10037=\u53C2\u6570\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684\u6570\u5B57 +10038=\u53C2\u6570\u503C\u5FC5\u987B\u662Ftrue\u6216false +10039=\u53C2\u6570\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684JSON\u6570\u7EC4\u683C\u5F0F +10040=\u53C2\u6570\u503C\u5FC5\u987B\u662F\u6709\u6548\u7684JSON\u683C\u5F0F -10041=设备未找到 +10041=\u8BBE\u5907\u672A\u627E\u5230 10042={0} -10043=删除数据失败 -10044=用户未登录 -10045=WebSocket连接失败或连接超时 -10046=保存声纹错误,请联系管理员 -10047=每日发送次数已达上限 -10048=旧密码输入错误 -10049=设置的LLM不是openai和ollama -10050=token生成失败 -10051=资源不存在 -10052=默认智能体未找到 -10053=智能体未找到 -10054=声纹接口未配置,请先在参数配置中配置声纹接口地址(server.voice_print) -10055=短信发送失败 -10056=短信连接建立失败 -10057=智能体的声纹创建失败 -10058=智能体的对应声纹更新失败 -10059=智能体的对应声纹删除失败 -10060=发送太频繁,请{0}秒后再试 -10061=激活码不能为空 -10062=激活码错误 -10063=设备已激活 -10064=该模型为默认模型,请先设置其他模型为默认模型 -10065=新增数据失败 -10066=修改数据失败 -10067=图形验证码错误 -10068=没有开启手机注册,没法使用短信验证码功能 -10069=用户名不是手机号码,请重新输入 -10070=此手机号码已经注册过 -10071=输入的手机号码未注册 -10072=当前不允许普通用户注册 -10073=没有开启手机注册,没法使用找回密码功能 -10074=输入的手机号码格式不正确 -10075=输入的手机验证码错误 -10076=字典类型不存在 -10077=字典类型编码重复 -10078=读取资源失败 -10079=LLM大模型和Intent意图识别,选择参数不匹配 -10080=此声音声纹对应的人({0})已经注册,请选择其他声音注册 -10081=删除声纹出现错误 -10082=此次修改不允许,此声音已经注册为声纹了({0}) -10083=修改声纹错误,请联系管理员 -10084=声纹接口地址存在错误,请进入参数管理修改声纹接口地址 -10085=音频数据不属于这个智能体 -10086=音频数据是空的请检查上传数据 -10087=声纹保存失败,请求不成功 -10088=声纹保存失败,请求处理失败 -10089=声纹注销失败,请求不成功 -10090=声纹注销失败,请求处理失败 -10091=供应器不存在 -10092=设置的LLM不存在 -10093=该模型配置已被智能体{0}引用,无法删除 -10094=该LLM模型已被意图识别配置引用,无法删除 -10095=无效服务端操作 -10096=未配置服务端WebSocket地址 -10097=目标WebSocket地址不存在 -10098=WebSocket地址列表不能为空 -10099=WebSocket地址不能使用localhost或127.0.0.1 -10100=WebSocket地址格式不正确 -10101=WebSocket连接测试失败 -10102=OTA地址不能为空 -10103=OTA地址不能使用localhost或127.0.0.1 -10104=OTA地址必须以http或https开头 -10105=OTA地址必须以/ota/结尾 -10106=OTA接口访问失败 -10107=OTA接口返回内容格式不正确 -10108=OTA接口验证失败 -10109=MCP地址不能为空 -10110=MCP地址不能使用localhost或127.0.0.1 -10111=不是正确的MCP地址 -10112=MCP接口访问失败 -10113=MCP接口返回内容格式不正确 -10114=MCP接口验证失败 -10115=声纹接口地址不能为空 -10116=声纹接口地址不能使用localhost或127.0.0.1 -10117=不是正确的声纹接口地址 -10118=声纹接口地址必须以http或https开头 -10119=声纹接口访问失败 -10120=声纹接口返回内容格式不正确 -10121=声纹接口验证失败 -10122=mqtt密钥不能为空 -10123=您的mqtt密钥长度不安全,字符数需要至少8个字符且必须同时包含大小写字母 -10124=您的mqtt密钥长度不安全,mqtt密钥必须同时包含大小写字母 -10125=您的mqtt密钥包含弱密码 -10128=字典标签重复 -10129=SM2密钥未配置 -10130=SM2解密失败 -10131=modelType和provideCode不能为空 -10132=没有权限查看该智能体的聊天记录 -10133=会话ID不能为空 -10134=智能体ID不能为空 -10135=聊天记录下载失败 -10136=下载链接已过期或无效 -10137=下载链接无效 -10138=用户 -10139=智体 \ No newline at end of file +10043=\u5220\u9664\u6570\u636E\u5931\u8D25 +10044=\u7528\u6237\u672A\u767B\u5F55 +10045=WebSocket\u8FDE\u63A5\u5931\u8D25\u6216\u8FDE\u63A5\u8D85\u65F6 +10046=\u4FDD\u5B58\u58F0\u7EB9\u9519\u8BEF\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458 +10047=\u6BCF\u65E5\u53D1\u9001\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650 +10048=\u65E7\u5BC6\u7801\u8F93\u5165\u9519\u8BEF +10049=\u8BBE\u7F6E\u7684LLM\u4E0D\u662Fopenai\u548Collama +10050=token\u751F\u6210\u5931\u8D25 +10051=\u8D44\u6E90\u4E0D\u5B58\u5728 +10052=\u9ED8\u8BA4\u667A\u80FD\u4F53\u672A\u627E\u5230 +10053=\u667A\u80FD\u4F53\u672A\u627E\u5230 +10054=\u58F0\u7EB9\u63A5\u53E3\u672A\u914D\u7F6E\uFF0C\u8BF7\u5148\u5728\u53C2\u6570\u914D\u7F6E\u4E2D\u914D\u7F6E\u58F0\u7EB9\u63A5\u53E3\u5730\u5740(server.voice_print) +10055=\u77ED\u4FE1\u53D1\u9001\u5931\u8D25 +10056=\u77ED\u4FE1\u8FDE\u63A5\u5EFA\u7ACB\u5931\u8D25 +10057=\u667A\u80FD\u4F53\u7684\u58F0\u7EB9\u521B\u5EFA\u5931\u8D25 +10058=\u667A\u80FD\u4F53\u7684\u5BF9\u5E94\u58F0\u7EB9\u66F4\u65B0\u5931\u8D25 +10059=\u667A\u80FD\u4F53\u7684\u5BF9\u5E94\u58F0\u7EB9\u5220\u9664\u5931\u8D25 +10060=\u53D1\u9001\u592A\u9891\u7E41\uFF0C\u8BF7{0}\u79D2\u540E\u518D\u8BD5 +10061=\u6FC0\u6D3B\u7801\u4E0D\u80FD\u4E3A\u7A7A +10062=\u6FC0\u6D3B\u7801\u9519\u8BEF +10063=\u8BBE\u5907\u5DF2\u6FC0\u6D3B +10064=\u8BE5\u6A21\u578B\u4E3A\u9ED8\u8BA4\u6A21\u578B\uFF0C\u8BF7\u5148\u8BBE\u7F6E\u5176\u4ED6\u6A21\u578B\u4E3A\u9ED8\u8BA4\u6A21\u578B +10065=\u65B0\u589E\u6570\u636E\u5931\u8D25 +10066=\u4FEE\u6539\u6570\u636E\u5931\u8D25 +10067=\u56FE\u5F62\u9A8C\u8BC1\u7801\u9519\u8BEF +10068=\u6CA1\u6709\u5F00\u542F\u624B\u673A\u6CE8\u518C\uFF0C\u6CA1\u6CD5\u4F7F\u7528\u77ED\u4FE1\u9A8C\u8BC1\u7801\u529F\u80FD +10069=\u7528\u6237\u540D\u4E0D\u662F\u624B\u673A\u53F7\u7801\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165 +10070=\u6B64\u624B\u673A\u53F7\u7801\u5DF2\u7ECF\u6CE8\u518C\u8FC7 +10071=\u8F93\u5165\u7684\u624B\u673A\u53F7\u7801\u672A\u6CE8\u518C +10072=\u5F53\u524D\u4E0D\u5141\u8BB8\u666E\u901A\u7528\u6237\u6CE8\u518C +10073=\u6CA1\u6709\u5F00\u542F\u624B\u673A\u6CE8\u518C\uFF0C\u6CA1\u6CD5\u4F7F\u7528\u627E\u56DE\u5BC6\u7801\u529F\u80FD +10074=\u8F93\u5165\u7684\u624B\u673A\u53F7\u7801\u683C\u5F0F\u4E0D\u6B63\u786E +10075=\u8F93\u5165\u7684\u624B\u673A\u9A8C\u8BC1\u7801\u9519\u8BEF +10076=\u5B57\u5178\u7C7B\u578B\u4E0D\u5B58\u5728 +10077=\u5B57\u5178\u7C7B\u578B\u7F16\u7801\u91CD\u590D +10078=\u8BFB\u53D6\u8D44\u6E90\u5931\u8D25 +10079=LLM\u5927\u6A21\u578B\u548CIntent\u610F\u56FE\u8BC6\u522B\uFF0C\u9009\u62E9\u53C2\u6570\u4E0D\u5339\u914D +10080=\u6B64\u58F0\u97F3\u58F0\u7EB9\u5BF9\u5E94\u7684\u4EBA\uFF08{0}\uFF09\u5DF2\u7ECF\u6CE8\u518C\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u58F0\u97F3\u6CE8\u518C +10081=\u5220\u9664\u58F0\u7EB9\u51FA\u73B0\u9519\u8BEF +10082=\u6B64\u6B21\u4FEE\u6539\u4E0D\u5141\u8BB8\uFF0C\u6B64\u58F0\u97F3\u5DF2\u7ECF\u6CE8\u518C\u4E3A\u58F0\u7EB9\u4E86\uFF08{0}\uFF09 +10083=\u4FEE\u6539\u58F0\u7EB9\u9519\u8BEF\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458 +10084=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u5B58\u5728\u9519\u8BEF\uFF0C\u8BF7\u8FDB\u5165\u53C2\u6570\u7BA1\u7406\u4FEE\u6539\u58F0\u7EB9\u63A5\u53E3\u5730\u5740 +10085=\u97F3\u9891\u6570\u636E\u4E0D\u5C5E\u4E8E\u8FD9\u4E2A\u667A\u80FD\u4F53 +10086=\u97F3\u9891\u6570\u636E\u662F\u7A7A\u7684\u8BF7\u68C0\u67E5\u4E0A\u4F20\u6570\u636E +10087=\u58F0\u7EB9\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u6C42\u4E0D\u6210\u529F +10088=\u58F0\u7EB9\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u6C42\u5904\u7406\u5931\u8D25 +10089=\u58F0\u7EB9\u6CE8\u9500\u5931\u8D25\uFF0C\u8BF7\u6C42\u4E0D\u6210\u529F +10090=\u58F0\u7EB9\u6CE8\u9500\u5931\u8D25\uFF0C\u8BF7\u6C42\u5904\u7406\u5931\u8D25 +10091=\u4F9B\u5E94\u5668\u4E0D\u5B58\u5728 +10092=\u8BBE\u7F6E\u7684LLM\u4E0D\u5B58\u5728 +10093=\u8BE5\u6A21\u578B\u914D\u7F6E\u5DF2\u88AB\u667A\u80FD\u4F53{0}\u5F15\u7528\uFF0C\u65E0\u6CD5\u5220\u9664 +10094=\u8BE5LLM\u6A21\u578B\u5DF2\u88AB\u610F\u56FE\u8BC6\u522B\u914D\u7F6E\u5F15\u7528\uFF0C\u65E0\u6CD5\u5220\u9664 +10095=\u65E0\u6548\u670D\u52A1\u7AEF\u64CD\u4F5C +10096=\u672A\u914D\u7F6E\u670D\u52A1\u7AEFWebSocket\u5730\u5740 +10097=\u76EE\u6807WebSocket\u5730\u5740\u4E0D\u5B58\u5728 +10098=WebSocket\u5730\u5740\u5217\u8868\u4E0D\u80FD\u4E3A\u7A7A +10099=WebSocket\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10100=WebSocket\u5730\u5740\u683C\u5F0F\u4E0D\u6B63\u786E +10101=WebSocket\u8FDE\u63A5\u6D4B\u8BD5\u5931\u8D25 +10102=OTA\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A +10103=OTA\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10104=OTA\u5730\u5740\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934 +10105=OTA\u5730\u5740\u5FC5\u987B\u4EE5/ota/\u7ED3\u5C3E +10106=OTA\u63A5\u53E3\u8BBF\u95EE\u5931\u8D25 +10107=OTA\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u683C\u5F0F\u4E0D\u6B63\u786E +10108=OTA\u63A5\u53E3\u9A8C\u8BC1\u5931\u8D25 +10109=MCP\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A +10110=MCP\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10111=\u4E0D\u662F\u6B63\u786E\u7684MCP\u5730\u5740 +10112=MCP\u63A5\u53E3\u8BBF\u95EE\u5931\u8D25 +10113=MCP\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u683C\u5F0F\u4E0D\u6B63\u786E +10114=MCP\u63A5\u53E3\u9A8C\u8BC1\u5931\u8D25 +10115=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u4E0D\u80FD\u4E3A\u7A7A +10116=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10117=\u4E0D\u662F\u6B63\u786E\u7684\u58F0\u7EB9\u63A5\u53E3\u5730\u5740 +10118=\u58F0\u7EB9\u63A5\u53E3\u5730\u5740\u5FC5\u987B\u4EE5http\u6216https\u5F00\u5934 +10119=\u58F0\u7EB9\u63A5\u53E3\u8BBF\u95EE\u5931\u8D25 +10120=\u58F0\u7EB9\u63A5\u53E3\u8FD4\u56DE\u5185\u5BB9\u683C\u5F0F\u4E0D\u6B63\u786E +10121=\u58F0\u7EB9\u63A5\u53E3\u9A8C\u8BC1\u5931\u8D25 +10122=mqtt\u5BC6\u94A5\u4E0D\u80FD\u4E3A\u7A7A +10123=\u60A8\u7684mqtt\u5BC6\u94A5\u957F\u5EA6\u4E0D\u5B89\u5168\uFF0C\u5B57\u7B26\u6570\u9700\u8981\u81F3\u5C118\u4E2A\u5B57\u7B26\u4E14\u5FC5\u987B\u540C\u65F6\u5305\u542B\u5927\u5C0F\u5199\u5B57\u6BCD +10124=\u60A8\u7684mqtt\u5BC6\u94A5\u957F\u5EA6\u4E0D\u5B89\u5168\uFF0Cmqtt\u5BC6\u94A5\u5FC5\u987B\u540C\u65F6\u5305\u542B\u5927\u5C0F\u5199\u5B57\u6BCD +10125=\u60A8\u7684mqtt\u5BC6\u94A5\u5305\u542B\u5F31\u5BC6\u7801 +10128=\u5B57\u5178\u6807\u7B7E\u91CD\u590D +10129=SM2\u5BC6\u94A5\u672A\u914D\u7F6E +10130=SM2\u89E3\u5BC6\u5931\u8D25 +10131=modelType\u548CprovideCode\u4E0D\u80FD\u4E3A\u7A7A +10132=\u6CA1\u6709\u6743\u9650\u67E5\u770B\u8BE5\u667A\u80FD\u4F53\u7684\u804A\u5929\u8BB0\u5F55 +10133=\u4F1A\u8BDDID\u4E0D\u80FD\u4E3A\u7A7A +10134=\u667A\u80FD\u4F53ID\u4E0D\u80FD\u4E3A\u7A7A +10135=\u804A\u5929\u8BB0\u5F55\u4E0B\u8F7D\u5931\u8D25 +10136=\u4E0B\u8F7D\u94FE\u63A5\u5DF2\u8FC7\u671F\u6216\u65E0\u6548 +10137=\u4E0B\u8F7D\u94FE\u63A5\u65E0\u6548 +10138=\u7528\u6237 +10139=\u667A\u4F53 +10140=\u97F3\u9891\u6587\u4EF6\u4E0D\u80FD\u4E3A\u7A7A +10141=\u53EA\u652F\u6301\u97F3\u9891\u6587\u4EF6 +10142=\u97F3\u9891\u6587\u4EF6\u5927\u5C0F\u4E0D\u80FD\u8D85\u8FC710MB +10143=\u4E0A\u4F20\u5931\u8D25 +10144=\u58F0\u97F3\u514B\u9686\u8BB0\u5F55\u4E0D\u5B58\u5728 +10145=\u97F3\u8272\u8D44\u6E90\u4FE1\u606F\u4E0D\u80FD\u4E3A\u7A7A +10146=\u5E73\u53F0\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A +10147=\u97F3\u8272ID\u4E0D\u80FD\u4E3A\u7A7A +10148=\u5F52\u5C5E\u8D26\u53F7\u4E0D\u80FD\u4E3A\u7A7A +10149=\u5220\u9664\u7684\u97F3\u8272\u8D44\u6E90ID\u4E0D\u80FD\u4E3A\u7A7A +10150=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55 \ No newline at end of file diff --git a/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties b/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties index ef66c2bb..3ed34742 100644 --- a/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties +++ b/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties @@ -1,148 +1,159 @@ -#繁體中文 -500=服務器內部異常 -401=未授權 -403=拒絕訪問,沒有权限 +#\u7E41\u9AD4\u4E2D\u6587 +500=\u670D\u52D9\u5668\u5167\u90E8\u7570\u5E38 +401=\u672A\u6388\u6B0A +403=\u62D2\u7D55\u8A2A\u554F\uFF0C\u6C92\u6709\u6743\u9650 -10001={0}不能為空 -10002=數據庫中已存在該記錄 -10003=獲取參數失敗 -10004=賬號或密碼錯誤 -10005=賬號已被停用 -10006=唯一標識不能為空 -10007=驗證碼不正確 -10008=先刪除子菜單或按鈕 -10009=原密碼不正確 -10010=帳號或密碼不正確,您還有可以嘗試{0}次 +10001={0}\u4E0D\u80FD\u70BA\u7A7A +10002=\u6578\u64DA\u5EAB\u4E2D\u5DF2\u5B58\u5728\u8A72\u8A18\u9304 +10003=\u7372\u53D6\u53C3\u6578\u5931\u6557 +10004=\u8CEC\u865F\u6216\u5BC6\u78BC\u932F\u8AA4 +10005=\u8CEC\u865F\u5DF2\u88AB\u505C\u7528 +10006=\u552F\u4E00\u6A19\u8B58\u4E0D\u80FD\u70BA\u7A7A +10007=\u9A57\u8B49\u78BC\u4E0D\u6B63\u78BA +10008=\u5148\u522A\u9664\u5B50\u83DC\u55AE\u6216\u6309\u9215 +10009=\u539F\u5BC6\u78BC\u4E0D\u6B63\u78BA +10010=\u5E33\u865F\u6216\u5BC6\u78BC\u4E0D\u6B63\u78BA,\u60A8\u9084\u6709\u53EF\u4EE5\u5617\u8A66{0}\u6B21 -10011=上級部門選擇錯誤 -10012=上級菜單不能為自身 -10013=數據權限接口,只能是Map類型參數 -10014=請先刪除下級部門 -10015=請先刪除部門下的用戶 -10016=部署失敗,沒有流程 -10017=模型圖不正確,請檢查 -10018=導出失敗,模型ID為{0} +10011=\u4E0A\u7D1A\u90E8\u9580\u9078\u64C7\u932F\u8AA4 +10012=\u4E0A\u7D1A\u83DC\u55AE\u4E0D\u80FD\u70BA\u81EA\u8EAB +10013=\u6578\u64DA\u6B0A\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u985E\u578B\u53C3\u6578 +10014=\u8ACB\u5148\u522A\u9664\u4E0B\u7D1A\u90E8\u9580 +10015=\u8ACB\u5148\u522A\u9664\u90E8\u9580\u4E0B\u7684\u7528\u6236 +10016=\u90E8\u7F72\u5931\u6557\uFF0C\u6C92\u6709\u6D41\u7A0B +10017=\u6A21\u578B\u5716\u4E0D\u6B63\u78BA\uFF0C\u8ACB\u6AA2\u67E5 +10018=\u5C0E\u51FA\u5931\u6557\uFF0C\u6A21\u578BID\u70BA{0} -10019=請上傳文件 -10020=token不能為空 -10021=token失效,請重新登錄 -10022=賬號已被鎖定 -10023=請上傳zip、bar、bpmn、bpmn20.xml格式文件 +10019=\u8ACB\u4E0A\u50B3\u6587\u4EF6 +10020=token\u4E0D\u80FD\u70BA\u7A7A +10021=token\u5931\u6548\uFF0C\u8ACB\u91CD\u65B0\u767B\u9304 +10022=\u8CEC\u865F\u5DF2\u88AB\u9396\u5B9A +10023=\u8ACB\u4E0A\u50B3zip\u3001bar\u3001bpmn\u3001bpmn20.xml\u683C\u5F0F\u6587\u4EF6 -10024=上傳文件失敗{0} -10025=發送短信失敗{0} -10026=郵件模板不存在 +10024=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557{0} +10025=\u767C\u9001\u77ED\u4FE1\u5931\u6557{0} +10026=\u90F5\u4EF6\u6A21\u677F\u4E0D\u5B58\u5728 -10027=Redis服務異常 -10028=定時任務失敗 -10029=不能包含非法字符 -10030=密碼長度不足{0}位 -10031=密碼必須同時包含數字、大小寫字母和特殊字符組成 -10032=刪除本數據異常 -10033=設備驗證碼錯誤 +10027=Redis\u670D\u52D9\u7570\u5E38 +10028=\u5B9A\u6642\u4EFB\u52D9\u5931\u6557 +10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26 +10030=\u5BC6\u78BC\u9577\u5EA6\u4E0D\u8DB3{0}\u4F4D +10031=\u5BC6\u78BC\u5FC5\u9808\u540C\u6642\u5305\u542B\u6578\u5B57\u3001\u5927\u5C0F\u5BEB\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\u7D44\u6210 +10032=\u522A\u9664\u672C\u6578\u64DA\u7570\u5E38 +10033=\u8A2D\u5099\u9A57\u8B49\u78BC\u932F\u8AA4 -10034=參數值不能為空 -10035=參數類型不能為空 -10036=不支持的參數類型 -10037=參數值必須是有效的數字 -10038=參數值必須是true或false -10039=參數值必須是有效的JSON數組格式 -10040=參數值必須是有效的JSON格式 +10034=\u53C3\u6578\u503C\u4E0D\u80FD\u70BA\u7A7A +10035=\u53C3\u6578\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A +10036=\u4E0D\u652F\u6301\u7684\u53C3\u6578\u985E\u578B +10037=\u53C3\u6578\u503C\u5FC5\u9808\u662F\u6709\u6548\u7684\u6578\u5B57 +10038=\u53C3\u6578\u503C\u5FC5\u9808\u662Ftrue\u6216false +10039=\u53C3\u6578\u503C\u5FC5\u9808\u662F\u6709\u6548\u7684JSON\u6578\u7D44\u683C\u5F0F +10040=\u53C3\u6578\u503C\u5FC5\u9808\u662F\u6709\u6548\u7684JSON\u683C\u5F0F -10041=設備未找到 +10041=\u8A2D\u5099\u672A\u627E\u5230 10042={0} -10043=刪除數據失敗 -10044=用戶未登錄 -10045=WebSocket連接失敗或連接超時 -10046=保存聲紋錯誤,請聯繫管理員 -10047=每日發送次數已達上限 -10048=舊密碼輸入錯誤 -10049=設置的LLM不是openai和ollama -10050=token生成失敗 -10051=資源不存在 -10052=默認智能體未找到 -10053=智能體未找到 -10054=聲紋接口未配置,請先在參數配置中配置聲紋接口地址(server.voice_print) -10055=短信發送失敗 -10056=短信連接建立失敗 -10057=智能體的聲紋創建失敗 -10058=智能體的對應聲紋更新失敗 -10059=智能體的對應聲紋刪除失敗 -10060=發送太頻繁,請{0}秒後再試 -10061=激活碼不能為空 -10062=激活碼錯誤 -10063=設備已激活 -10064=該模型為預設模型,請先設置其他模型為預設模型 -10065=新增數據失敗 -10066=更新數據失敗 -10067=圖形驗證碼錯誤 -10068=未開啟手機註冊,無法使用短信驗證碼功能 -10069=用戶名不是手機號碼,請重新輸入 -10070=該手機號碼已註冊 -10071=輸入的手機號碼未註冊 -10072=目前不允許普通用戶註冊 -10073=未開啟手機註冊,無法使用密碼找回功能 -10074=輸入的手機號碼格式不正確 -10075=輸入的短信驗證碼不正確 -10076=字典類型不存在 -10077=字典類型編碼重複 -10078=讀取資源失敗 -10079=LLM模型與意圖識別、參數選擇不匹配 -10080=此聲紋屬於已註冊的{0},請選擇其他聲音 -10081=刪除聲紋時發生錯誤 -10082=不允許修改,此聲音已註冊為聲紋({0}) -10083=修改聲紋錯誤,請聯繫管理員 -10084=聲紋接口地址錯誤,請前往參數管理修改聲紋接口地址 -10085=音頻數據不屬於此智能體 -10086=音頻數據為空,請檢查上傳數據 -10087=聲紋註冊失敗,請求未成功 -10088=聲紋註冊失敗,請求處理失敗 -10089=聲紋註銷失敗,請求未成功 -10090=聲紋註銷失敗,請求處理失敗 -10091=模型提供商不存在 -10092=配置的LLM不存在 -10093=此模型配置被智能體{0}引用,無法刪除 -10094=此LLM模型被意圖識別配置引用,無法刪除 -10095=無效的服務器操作 -10096=未配置服務器WebSocket地址 -10097=目標WebSocket地址不存在 -10098=WebSocket地址列表不能為空 -10099=WebSocket地址不能使用localhost或127.0.0.1 -10100=WebSocket地址格式不正確 -10101=WebSocket連接測試失敗 -10102=OTA地址不能為空 -10103=OTA地址不能使用localhost或127.0.0.1 -10104=OTA地址必須以http或https開頭 -10105=OTA地址必須以/ota/結尾 -10106=OTA接口訪問失敗 -10107=OTA接口返回內容格式不正確 -10108=OTA接口驗證失敗 -10109=MCP地址不能為空 -10110=MCP地址不能使用localhost或127.0.0.1 -10111=不是有效的MCP地址 -10112=MCP接口訪問失敗 -10113=MCP接口返回內容格式不正確 -10114=MCP接口驗證失敗 -10115=聲紋接口地址不能為空 -10116=聲紋接口地址不能使用localhost或127.0.0.1 -10117=不是有效的聲紋接口地址 -10118=聲紋接口地址必須以http或https開頭 -10119=聲紋接口訪問失敗 -10120=聲紋接口返回內容格式不正確 -10121=聲紋接口驗證失敗 -10122=MQTT密鑰不能為空 -10123=您的MQTT密鑰不安全,需至少8個字符且必須同時包含大小寫字母 -10124=您的MQTT密鑰不安全,MQTT密鑰必須同時包含大小寫字母 -10125=您的MQTT密鑰包含弱密碼 -10128=字典標籤重複 -10129=SM2密鑰未配置 -10130=SM2解密失敗 -10131=modelType和provideCode不能為空 -10132=沒有權限查看該智能體的聊天記錄 -10133=會話ID不能為空 -10134=智能體ID不能為空 -10135=聊天記錄下載失敗 -10136=下載鏈接已過期或無效 -10137=下載鏈接無效 -10138=用戶 -10139=智體 \ No newline at end of file +10043=\u522A\u9664\u6578\u64DA\u5931\u6557 +10044=\u7528\u6236\u672A\u767B\u9304 +10045=WebSocket\u9023\u63A5\u5931\u6557\u6216\u9023\u63A5\u8D85\u6642 +10046=\u4FDD\u5B58\u8072\u7D0B\u932F\u8AA4\uFF0C\u8ACB\u806F\u7E6B\u7BA1\u7406\u54E1 +10047=\u6BCF\u65E5\u767C\u9001\u6B21\u6578\u5DF2\u9054\u4E0A\u9650 +10048=\u820A\u5BC6\u78BC\u8F38\u5165\u932F\u8AA4 +10049=\u8A2D\u7F6E\u7684LLM\u4E0D\u662Fopenai\u548Collama +10050=token\u751F\u6210\u5931\u6557 +10051=\u8CC7\u6E90\u4E0D\u5B58\u5728 +10052=\u9ED8\u8A8D\u667A\u80FD\u9AD4\u672A\u627E\u5230 +10053=\u667A\u80FD\u9AD4\u672A\u627E\u5230 +10054=\u8072\u7D0B\u63A5\u53E3\u672A\u914D\u7F6E\uFF0C\u8ACB\u5148\u5728\u53C3\u6578\u914D\u7F6E\u4E2D\u914D\u7F6E\u8072\u7D0B\u63A5\u53E3\u5730\u5740(server.voice_print) +10055=\u77ED\u4FE1\u767C\u9001\u5931\u6557 +10056=\u77ED\u4FE1\u9023\u63A5\u5EFA\u7ACB\u5931\u6557 +10057=\u667A\u80FD\u9AD4\u7684\u8072\u7D0B\u5275\u5EFA\u5931\u6557 +10058=\u667A\u80FD\u9AD4\u7684\u5C0D\u61C9\u8072\u7D0B\u66F4\u65B0\u5931\u6557 +10059=\u667A\u80FD\u9AD4\u7684\u5C0D\u61C9\u8072\u7D0B\u522A\u9664\u5931\u6557 +10060=\u767C\u9001\u592A\u983B\u7E41\uFF0C\u8ACB{0}\u79D2\u5F8C\u518D\u8A66 +10061=\u6FC0\u6D3B\u78BC\u4E0D\u80FD\u70BA\u7A7A +10062=\u6FC0\u6D3B\u78BC\u932F\u8AA4 +10063=\u8A2D\u5099\u5DF2\u6FC0\u6D3B +10064=\u8A72\u6A21\u578B\u70BA\u9810\u8A2D\u6A21\u578B\uFF0C\u8ACB\u5148\u8A2D\u7F6E\u5176\u4ED6\u6A21\u578B\u70BA\u9810\u8A2D\u6A21\u578B +10065=\u65B0\u589E\u6578\u64DA\u5931\u6557 +10066=\u66F4\u65B0\u6578\u64DA\u5931\u6557 +10067=\u5716\u5F62\u9A57\u8B49\u78BC\u932F\u8AA4 +10068=\u672A\u958B\u555F\u624B\u6A5F\u8A3B\u518A\uFF0C\u7121\u6CD5\u4F7F\u7528\u77ED\u4FE1\u9A57\u8B49\u78BC\u529F\u80FD +10069=\u7528\u6236\u540D\u4E0D\u662F\u624B\u6A5F\u865F\u78BC\uFF0C\u8ACB\u91CD\u65B0\u8F38\u5165 +10070=\u8A72\u624B\u6A5F\u865F\u78BC\u5DF2\u8A3B\u518A +10071=\u8F38\u5165\u7684\u624B\u6A5F\u865F\u78BC\u672A\u8A3B\u518A +10072=\u76EE\u524D\u4E0D\u5141\u8A31\u666E\u901A\u7528\u6236\u8A3B\u518A +10073=\u672A\u958B\u555F\u624B\u6A5F\u8A3B\u518A\uFF0C\u7121\u6CD5\u4F7F\u7528\u5BC6\u78BC\u627E\u56DE\u529F\u80FD +10074=\u8F38\u5165\u7684\u624B\u6A5F\u865F\u78BC\u683C\u5F0F\u4E0D\u6B63\u78BA +10075=\u8F38\u5165\u7684\u77ED\u4FE1\u9A57\u8B49\u78BC\u4E0D\u6B63\u78BA +10076=\u5B57\u5178\u985E\u578B\u4E0D\u5B58\u5728 +10077=\u5B57\u5178\u985E\u578B\u7DE8\u78BC\u91CD\u8907 +10078=\u8B80\u53D6\u8CC7\u6E90\u5931\u6557 +10079=LLM\u6A21\u578B\u8207\u610F\u5716\u8B58\u5225\u3001\u53C3\u6578\u9078\u64C7\u4E0D\u5339\u914D +10080=\u6B64\u8072\u7D0B\u5C6C\u65BC\u5DF2\u8A3B\u518A\u7684{0}\uFF0C\u8ACB\u9078\u64C7\u5176\u4ED6\u8072\u97F3 +10081=\u522A\u9664\u8072\u7D0B\u6642\u767C\u751F\u932F\u8AA4 +10082=\u4E0D\u5141\u8A31\u4FEE\u6539\uFF0C\u6B64\u8072\u97F3\u5DF2\u8A3B\u518A\u70BA\u8072\u7D0B({0}) +10083=\u4FEE\u6539\u8072\u7D0B\u932F\u8AA4\uFF0C\u8ACB\u806F\u7E6B\u7BA1\u7406\u54E1 +10084=\u8072\u7D0B\u63A5\u53E3\u5730\u5740\u932F\u8AA4\uFF0C\u8ACB\u524D\u5F80\u53C3\u6578\u7BA1\u7406\u4FEE\u6539\u8072\u7D0B\u63A5\u53E3\u5730\u5740 +10085=\u97F3\u983B\u6578\u64DA\u4E0D\u5C6C\u65BC\u6B64\u667A\u80FD\u9AD4 +10086=\u97F3\u983B\u6578\u64DA\u70BA\u7A7A\uFF0C\u8ACB\u6AA2\u67E5\u4E0A\u50B3\u6578\u64DA +10087=\u8072\u7D0B\u8A3B\u518A\u5931\u6557\uFF0C\u8ACB\u6C42\u672A\u6210\u529F +10088=\u8072\u7D0B\u8A3B\u518A\u5931\u6557\uFF0C\u8ACB\u6C42\u8655\u7406\u5931\u6557 +10089=\u8072\u7D0B\u8A3B\u92B7\u5931\u6557\uFF0C\u8ACB\u6C42\u672A\u6210\u529F +10090=\u8072\u7D0B\u8A3B\u92B7\u5931\u6557\uFF0C\u8ACB\u6C42\u8655\u7406\u5931\u6557 +10091=\u6A21\u578B\u63D0\u4F9B\u5546\u4E0D\u5B58\u5728 +10092=\u914D\u7F6E\u7684LLM\u4E0D\u5B58\u5728 +10093=\u6B64\u6A21\u578B\u914D\u7F6E\u88AB\u667A\u80FD\u9AD4{0}\u5F15\u7528\uFF0C\u7121\u6CD5\u522A\u9664 +10094=\u6B64LLM\u6A21\u578B\u88AB\u610F\u5716\u8B58\u5225\u914D\u7F6E\u5F15\u7528\uFF0C\u7121\u6CD5\u522A\u9664 +10095=\u7121\u6548\u7684\u670D\u52D9\u5668\u64CD\u4F5C +10096=\u672A\u914D\u7F6E\u670D\u52D9\u5668WebSocket\u5730\u5740 +10097=\u76EE\u6A19WebSocket\u5730\u5740\u4E0D\u5B58\u5728 +10098=WebSocket\u5730\u5740\u5217\u8868\u4E0D\u80FD\u70BA\u7A7A +10099=WebSocket\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10100=WebSocket\u5730\u5740\u683C\u5F0F\u4E0D\u6B63\u78BA +10101=WebSocket\u9023\u63A5\u6E2C\u8A66\u5931\u6557 +10102=OTA\u5730\u5740\u4E0D\u80FD\u70BA\u7A7A +10103=OTA\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10104=OTA\u5730\u5740\u5FC5\u9808\u4EE5http\u6216https\u958B\u982D +10105=OTA\u5730\u5740\u5FC5\u9808\u4EE5/ota/\u7D50\u5C3E +10106=OTA\u63A5\u53E3\u8A2A\u554F\u5931\u6557 +10107=OTA\u63A5\u53E3\u8FD4\u56DE\u5167\u5BB9\u683C\u5F0F\u4E0D\u6B63\u78BA +10108=OTA\u63A5\u53E3\u9A57\u8B49\u5931\u6557 +10109=MCP\u5730\u5740\u4E0D\u80FD\u70BA\u7A7A +10110=MCP\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10111=\u4E0D\u662F\u6709\u6548\u7684MCP\u5730\u5740 +10112=MCP\u63A5\u53E3\u8A2A\u554F\u5931\u6557 +10113=MCP\u63A5\u53E3\u8FD4\u56DE\u5167\u5BB9\u683C\u5F0F\u4E0D\u6B63\u78BA +10114=MCP\u63A5\u53E3\u9A57\u8B49\u5931\u6557 +10115=\u8072\u7D0B\u63A5\u53E3\u5730\u5740\u4E0D\u80FD\u70BA\u7A7A +10116=\u8072\u7D0B\u63A5\u53E3\u5730\u5740\u4E0D\u80FD\u4F7F\u7528localhost\u6216127.0.0.1 +10117=\u4E0D\u662F\u6709\u6548\u7684\u8072\u7D0B\u63A5\u53E3\u5730\u5740 +10118=\u8072\u7D0B\u63A5\u53E3\u5730\u5740\u5FC5\u9808\u4EE5http\u6216https\u958B\u982D +10119=\u8072\u7D0B\u63A5\u53E3\u8A2A\u554F\u5931\u6557 +10120=\u8072\u7D0B\u63A5\u53E3\u8FD4\u56DE\u5167\u5BB9\u683C\u5F0F\u4E0D\u6B63\u78BA +10121=\u8072\u7D0B\u63A5\u53E3\u9A57\u8B49\u5931\u6557 +10122=MQTT\u5BC6\u9470\u4E0D\u80FD\u70BA\u7A7A +10123=\u60A8\u7684MQTT\u5BC6\u9470\u4E0D\u5B89\u5168\uFF0C\u9700\u81F3\u5C118\u500B\u5B57\u7B26\u4E14\u5FC5\u9808\u540C\u6642\u5305\u542B\u5927\u5C0F\u5BEB\u5B57\u6BCD +10124=\u60A8\u7684MQTT\u5BC6\u9470\u4E0D\u5B89\u5168\uFF0CMQTT\u5BC6\u9470\u5FC5\u9808\u540C\u6642\u5305\u542B\u5927\u5C0F\u5BEB\u5B57\u6BCD +10125=\u60A8\u7684MQTT\u5BC6\u9470\u5305\u542B\u5F31\u5BC6\u78BC +10128=\u5B57\u5178\u6A19\u7C64\u91CD\u8907 +10129=SM2\u5BC6\u9470\u672A\u914D\u7F6E +10130=SM2\u89E3\u5BC6\u5931\u6557 +10131=modelType\u548CprovideCode\u4E0D\u80FD\u70BA\u7A7A +10132=\u6C92\u6709\u6B0A\u9650\u67E5\u770B\u8A72\u667A\u80FD\u9AD4\u7684\u804A\u5929\u8A18\u9304 +10133=\u6703\u8A71ID\u4E0D\u80FD\u70BA\u7A7A +10134=\u667A\u80FD\u9AD4ID\u4E0D\u80FD\u70BA\u7A7A +10135=\u804A\u5929\u8A18\u9304\u4E0B\u8F09\u5931\u6557 +10136=\u4E0B\u8F09\u93C8\u63A5\u5DF2\u904E\u671F\u6216\u7121\u6548 +10137=\u4E0B\u8F09\u93C8\u63A5\u7121\u6548 +10138=\u7528\u6236 +10139=\u667A\u9AD4 +10140=\u97F3\u983B\u6587\u4EF6\u4E0D\u80FD\u70BA\u7A7A +10141=\u53EA\u652F\u6301\u97F3\u983B\u6587\u4EF6 +10142=\u97F3\u983B\u6587\u4EF6\u5927\u5C0F\u4E0D\u80FD\u8D85\u904E10MB +10143=\u4E0A\u50B3\u5931\u6557 +10144=\u8072\u97F3\u514B\u9686\u8A18\u9304\u4E0D\u5B58\u5728 +10145=\u97F3\u8272\u8CC7\u6E90\u4FE1\u606F\u4E0D\u80FD\u70BA\u7A7A +10146=\u5E73\u53F0\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A +10147=\u97F3\u8272ID\u4E0D\u80FD\u70BA\u7A7A +10148=\u6B78\u5C6C\u5E33\u865F\u4E0D\u80FD\u70BA\u7A7A +10149=\u522A\u9664\u7684\u97F3\u8272\u8CC7\u6E90ID\u4E0D\u80FD\u70BA\u7A7A +10150=\u60A8\u6C92\u6709\u6B0A\u9650\u64CD\u4F5C\u8A72\u8A18\u9304 \ No newline at end of file diff --git a/main/manager-api/src/main/resources/mapper/model/ModelConfigDao.xml b/main/manager-api/src/main/resources/mapper/model/ModelConfigDao.xml index 4f35f8d1..f6f8b3e7 100644 --- a/main/manager-api/src/main/resources/mapper/model/ModelConfigDao.xml +++ b/main/manager-api/src/main/resources/mapper/model/ModelConfigDao.xml @@ -23,4 +23,11 @@ select model_name from ai_model_config where model_type = #{modelType} and model_name = #{modelName} + + + \ No newline at end of file diff --git a/main/manager-mobile/src/i18n/en.ts b/main/manager-mobile/src/i18n/en.ts index fbc7be20..54b86c71 100644 --- a/main/manager-mobile/src/i18n/en.ts +++ b/main/manager-mobile/src/i18n/en.ts @@ -240,7 +240,7 @@ export default { 'settings.restartLater': 'Later', // About us 'settings.aboutApp': 'About XiaoZhi Console', - 'settings.aboutContent': 'XiaoZhi Console\n\nA cross-platform mobile management app built with Vue.js 3 + uni-app, providing device management, agent configuration and other functions for xiaozhi ESP32 smart hardware.\n\n© 2025 xiaozhi-esp32-server 0.8.3', + 'settings.aboutContent': 'XiaoZhi Console\n\nA cross-platform mobile management app built with Vue.js 3 + uni-app, providing device management, agent configuration and other functions for xiaozhi ESP32 smart hardware.\n\n© 2025 xiaozhi-esp32-server {version}', 'settings.restartSuccess': 'Saved, you can manually restart the app later', 'settings.serverUrlSavedAndCacheCleared': 'Server URL saved and cache cleared', 'settings.resetToDefaultAndCacheCleared': 'Reset to default and cache cleared', diff --git a/main/manager-mobile/src/i18n/zh_TW.ts b/main/manager-mobile/src/i18n/zh_TW.ts index 617aa5fb..fde04bc6 100644 --- a/main/manager-mobile/src/i18n/zh_TW.ts +++ b/main/manager-mobile/src/i18n/zh_TW.ts @@ -240,7 +240,7 @@ export default { 'settings.restartLater': '稍後', // 關於我們 'settings.aboutApp': '關於小智智控台', - 'settings.aboutContent': '小智智控台\n\n基於 Vue.js 3 + uni-app 構建的跨平台移動端管理應用,為小智ESP32智能硬體提供設備管理、智能體配置等功能。\n\n© 2025 xiaozhi-esp32-server 0.8.3', + 'settings.aboutContent': '小智智控台\n\n基於 Vue.js 3 + uni-app 構建的跨平台移動端管理應用,為小智ESP32智能硬體提供設備管理、智能體配置等功能。\n\n© 2025 xiaozhi-esp32-server {version}', 'settings.restartSuccess': '已保存,可稍後手動重啟應用', 'settings.serverUrlSavedAndCacheCleared': '服務端地址已保存,緩存已清除', 'settings.resetToDefaultAndCacheCleared': '已恢復默認設置,緩存已清除', diff --git a/main/manager-mobile/src/pages/settings/index.vue b/main/manager-mobile/src/pages/settings/index.vue index b5ad110a..348d0e43 100644 --- a/main/manager-mobile/src/pages/settings/index.vue +++ b/main/manager-mobile/src/pages/settings/index.vue @@ -235,7 +235,7 @@ function showAbout() { title: t('settings.aboutApp', { appName: import.meta.env.VITE_APP_TITLE }), content: t('settings.aboutContent', { appName: import.meta.env.VITE_APP_TITLE, - version: '0.8.3' + version: '0.8.4' }), showCancel: false, confirmText: t('common.confirm'), diff --git a/main/manager-web/src/apis/api.js b/main/manager-web/src/apis/api.js index 4d1d7d7d..3f2595b4 100755 --- a/main/manager-web/src/apis/api.js +++ b/main/manager-web/src/apis/api.js @@ -7,6 +7,10 @@ import model from './module/model.js' import ota from './module/ota.js' import timbre from "./module/timbre.js" import user from './module/user.js' +import voiceClone from './module/voiceClone.js' +import voiceResource from './module/voiceResource.js' + + /** * 接口地址 @@ -33,5 +37,7 @@ export default { model, timbre, ota, - dict + dict, + voiceResource, + voiceClone } diff --git a/main/manager-web/src/apis/module/voiceClone.js b/main/manager-web/src/apis/module/voiceClone.js new file mode 100644 index 00000000..ac661f2c --- /dev/null +++ b/main/manager-web/src/apis/module/voiceClone.js @@ -0,0 +1,98 @@ +import { getServiceUrl } from '../api'; +import RequestService from '../httpRequest'; + +export default { + // 分页查询音色资源 + getVoiceCloneList(params, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceClone`) + .method('GET') + .data(params) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('获取音色列表失败:', err); + RequestService.reAjaxFun(() => { + this.getVoiceCloneList(params, callback); + }); + }).send(); + }, + + // 上传音频文件 + uploadVoice(formData, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceClone/upload`) + .method('POST') + .data(formData) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('上传音频失败:', err); + RequestService.reAjaxFun(() => { + this.uploadVoice(formData, callback); + }); + }).send(); + }, + + // 更新音色名称 + updateName(params, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceClone/updateName`) + .method('POST') + .data(params) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('更新名称失败:', err); + RequestService.reAjaxFun(() => { + this.updateName(params, callback); + }); + }).send(); + }, + + // 获取音频下载ID + getAudioId(id, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceClone/audio/${id}`) + .method('POST') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('获取音频ID失败:', err); + RequestService.reAjaxFun(() => { + this.getAudioId(id, callback); + }); + }).send(); + }, + + // 获取音频播放URL + getPlayVoiceUrl(uuid) { + return `${getServiceUrl()}/voiceClone/play/${uuid}`; + }, + + // 复刻音频 + cloneAudio(params, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceClone/cloneAudio`) + .method('POST') + .data(params) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('上传失败:', err); + RequestService.reAjaxFun(() => { + this.cloneAudio(params, callback); + }); + }).send(); + } +} diff --git a/main/manager-web/src/apis/module/voiceResource.js b/main/manager-web/src/apis/module/voiceResource.js new file mode 100644 index 00000000..89762f2f --- /dev/null +++ b/main/manager-web/src/apis/module/voiceResource.js @@ -0,0 +1,103 @@ +import { getServiceUrl } from '../api'; +import RequestService from '../httpRequest'; + +export default { + // 分页查询音色资源 + getVoiceResourceList(params, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceResource`) + .method('GET') + .data(params) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('获取音色资源列表失败:', err); + RequestService.reAjaxFun(() => { + this.getVoiceResourceList(params, callback); + }); + }).send(); + }, + // 获取单个音色资源信息 + getVoiceResourceInfo(id, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceResource/${id}`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('获取音色资源信息失败:', err); + RequestService.reAjaxFun(() => { + this.getVoiceResourceInfo(id, callback); + }); + }).send(); + }, + // 保存音色资源 + saveVoiceResource(entity, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceResource`) + .method('POST') + .data(entity) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('保存音色资源失败:', err); + RequestService.reAjaxFun(() => { + this.saveVoiceResource(entity, callback); + }); + }).send(); + }, + // 删除音色资源 + deleteVoiceResource(ids, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceResource/${ids}`) + .method('DELETE') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('删除音色资源失败:', err); + RequestService.reAjaxFun(() => { + this.deleteVoiceResource(ids, callback); + }); + }).send(); + }, + // 根据用户ID获取音色资源列表 + getVoiceResourceByUserId(userId, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceResource/user/${userId}`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('获取用户音色资源列表失败:', err); + RequestService.reAjaxFun(() => { + this.getVoiceResourceByUserId(userId, callback); + }); + }).send(); + }, + // 获取TTS平台列表 + getTtsPlatformList(callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/voiceResource/ttsPlatforms`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail((err) => { + console.error('获取TTS平台列表失败:', err); + RequestService.reAjaxFun(() => { + this.getTtsPlatformList(callback); + }); + }).send(); + } +} diff --git a/main/manager-web/src/assets/header/firmware_update.png b/main/manager-web/src/assets/header/firmware_update.png deleted file mode 100644 index bd3d7396437a532046b4c4b60ede94acf2866648..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7738 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 as(pkE)#c}I>qtz78ANO^u`9CiqyGk4&grlK literal 0 HcmV?d00001 diff --git a/main/manager-web/src/components/FirmwareDialog.vue b/main/manager-web/src/components/FirmwareDialog.vue index 1e173101..657d21c9 100644 --- a/main/manager-web/src/components/FirmwareDialog.vue +++ b/main/manager-web/src/components/FirmwareDialog.vue @@ -1,11 +1,13 @@