From 34d7bd92ca0177e05988f9f57d6fa7512f349d6f Mon Sep 17 00:00:00 2001 From: rainv123 <2148537152@qq.com> Date: Wed, 17 Sep 2025 11:36:25 +0800 Subject: [PATCH 1/4] =?UTF-8?q?updata:=E5=AE=9E=E7=8E=B0=E5=90=8E=E7=AB=AF?= =?UTF-8?q?msg=E7=9A=84=E5=9B=BD=E9=99=85=E5=8C=96=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=94=A8=E6=88=B7=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=92=8C=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=9A=84=E7=A1=AC=E7=BC=96=E7=A0=81=E4=B8=BA?= =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96=E9=94=AE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xiaozhi/common/exception/ErrorCode.java | 109 +++++++++++ .../common/exception/RenExceptionHandler.java | 5 +- .../xiaozhi/common/utils/ResourcesUtils.java | 3 +- .../controller/AgentVoicePrintController.java | 9 +- .../agent/service/impl/AgentServiceImpl.java | 7 +- .../impl/AgentVoicePrintServiceImpl.java | 27 +-- .../service/impl/ConfigServiceImpl.java | 4 +- .../service/impl/DeviceServiceImpl.java | 15 +- .../service/impl/ModelConfigServiceImpl.java | 15 +- .../impl/ModelProviderServiceImpl.java | 9 +- .../modules/security/config/WebMvcConfig.java | 47 +++++ .../security/controller/LoginController.java | 28 +-- .../modules/security/oauth2/Oauth2Filter.java | 5 +- .../security/oauth2/TokenGenerator.java | 3 +- .../service/impl/CaptchaServiceImpl.java | 5 +- .../sms/service/imp/ALiYunSmsService.java | 5 +- .../ServerSideManageController.java | 9 +- .../sys/controller/SysParamsController.java | 57 +++--- .../service/impl/SysDictDataServiceImpl.java | 3 +- .../service/impl/SysDictTypeServiceImpl.java | 5 +- .../sys/service/impl/SysUserServiceImpl.java | 2 +- .../main/resources/i18n/messages.properties | 143 ++++++++++----- .../resources/i18n/messages_en_US.properties | 93 +++++++++- .../resources/i18n/messages_zh_CN.properties | 169 +++++++++++++---- .../resources/i18n/messages_zh_TW.properties | 170 ++++++++++++++---- main/manager-web/src/apis/httpRequest.js | 16 +- .../src/components/AddModelDialog.vue | 2 +- main/manager-web/src/i18n/en.js | 39 ++++ main/manager-web/src/i18n/zh_CN.js | 39 ++++ main/manager-web/src/i18n/zh_TW.js | 39 ++++ main/manager-web/src/views/login.vue | 21 ++- main/manager-web/src/views/register.vue | 12 +- 32 files changed, 875 insertions(+), 240 deletions(-) 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 6a9af011..e84fbba8 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 @@ -55,4 +55,113 @@ public interface ErrorCode { int OTA_DEVICE_NOT_FOUND = 10041; int OTA_DEVICE_NEED_BIND = 10042; + + // 新增错误编码 + int DELETE_DATA_FAILED = 10043; + int USER_NOT_LOGIN = 10044; + int WEB_SOCKET_CONNECT_FAILED = 10045; + int VOICE_PRINT_SAVE_ERROR = 10046; + int TODAY_SMS_LIMIT_REACHED = 10047; + int OLD_PASSWORD_ERROR = 10048; + int INVALID_LLM_TYPE = 10049; + int TOKEN_GENERATE_ERROR = 10050; + int RESOURCE_NOT_FOUND = 10051; + + // 新增错误编码 + int DEFAULT_AGENT_NOT_FOUND = 10052; + int AGENT_NOT_FOUND = 10053; + int VOICEPRINT_API_NOT_CONFIGURED = 10054; + int SMS_SEND_FAILED = 10055; + int SMS_CONNECTION_FAILED = 10056; + int AGENT_VOICEPRINT_CREATE_FAILED = 10057; + int AGENT_VOICEPRINT_UPDATE_FAILED = 10058; + int AGENT_VOICEPRINT_DELETE_FAILED = 10059; + int SMS_SEND_TOO_FREQUENTLY = 10060; + int ACTIVATION_CODE_EMPTY = 10061; + int ACTIVATION_CODE_ERROR = 10062; + int DEVICE_ALREADY_ACTIVATED = 10063; + // 默认模型删除错误 + int DEFAULT_MODEL_DELETE_ERROR = 10064; + // 设备相关错误码 + int MAC_ADDRESS_ALREADY_EXISTS = 10090; // Mac地址已存在 + // 模型相关错误码 + int MODEL_PROVIDER_NOT_EXIST = 10091; // 供应器不存在 + int LLM_NOT_EXIST = 10092; // 设置的LLM不存在 + int MODEL_REFERENCED_BY_AGENT = 10093; // 该模型配置已被智能体引用,无法删除 + int LLM_REFERENCED_BY_INTENT = 10094; // 该LLM模型已被意图识别配置引用,无法删除 + + // 登录相关错误码 + int ADD_DATA_FAILED = 10065; // 新增数据失败 + int UPDATE_DATA_FAILED = 10066; // 修改数据失败 + int SMS_CAPTCHA_ERROR = 10067; // 短信验证码错误 + int MOBILE_REGISTER_DISABLED = 10068; // 未开启手机注册 + int USERNAME_NOT_PHONE = 10069; // 用户名不是手机号码 + int PHONE_ALREADY_REGISTERED = 10070; // 手机号码已注册 + int PHONE_NOT_REGISTERED = 10071; // 手机号码未注册 + int USER_REGISTER_DISABLED = 10072; // 不允许用户注册 + int RETRIEVE_PASSWORD_DISABLED = 10073; // 未开启找回密码功能 + int PHONE_FORMAT_ERROR = 10074; // 手机号码格式不正确 + int SMS_CODE_ERROR = 10075; // 手机验证码错误 + + // 字典类型相关错误码 + int DICT_TYPE_NOT_EXIST = 10076; // 字典类型不存在 + int DICT_TYPE_DUPLICATE = 10077; // 字典类型编码重复 + + // 资源处理相关错误码 + int RESOURCE_READ_ERROR = 10078; // 读取资源失败 + + // 智能体相关错误码 + int LLM_INTENT_PARAMS_MISMATCH = 10079; // LLM大模型和Intent意图识别,选择参数不匹配 + + // 声纹相关错误码 + int VOICEPRINT_ALREADY_REGISTERED = 10080; // 此声音声纹已经注册 + int VOICEPRINT_DELETE_ERROR = 10081; // 删除声纹出现错误 + int VOICEPRINT_UPDATE_NOT_ALLOWED = 10082; // 声纹修改不允许,声音已注册 + int VOICEPRINT_UPDATE_ADMIN_ERROR = 10083; // 修改声纹错误,请联系管理员 + int VOICEPRINT_API_URI_ERROR = 10084; // 声纹接口地址错误 + int VOICEPRINT_AUDIO_NOT_BELONG_AGENT = 10085; // 音频数据不属于智能体 + int VOICEPRINT_AUDIO_EMPTY = 10086; // 音频数据为空 + int VOICEPRINT_REGISTER_REQUEST_ERROR = 10087; // 声纹保存请求失败 + int VOICEPRINT_REGISTER_PROCESS_ERROR = 10088; // 声纹保存处理失败 + int VOICEPRINT_UNREGISTER_REQUEST_ERROR = 10089; // 声纹注销请求失败 + int VOICEPRINT_UNREGISTER_PROCESS_ERROR = 10090; // 声纹注销处理失败 + int VOICEPRINT_IDENTIFY_REQUEST_ERROR = 10091; // 声纹识别请求失败 + + // 服务端管理相关错误码 + int INVALID_SERVER_ACTION = 10095; // 无效服务端操作 + int SERVER_WEBSOCKET_NOT_CONFIGURED = 10096; // 未配置服务端WebSocket地址 + int TARGET_WEBSOCKET_NOT_EXIST = 10097; // 目标WebSocket地址不存在 + + // 参数验证相关错误码 + int WEBSOCKET_URLS_EMPTY = 10098; // WebSocket地址列表不能为空 + int WEBSOCKET_URL_LOCALHOST = 10099; // WebSocket地址不能使用localhost或127.0.0.1 + int WEBSOCKET_URL_FORMAT_ERROR = 10100; // WebSocket地址格式不正确 + int WEBSOCKET_CONNECTION_FAILED = 10101; // WebSocket连接测试失败 + int OTA_URL_EMPTY = 10102; // OTA地址不能为空 + int OTA_URL_LOCALHOST = 10103; // OTA地址不能使用localhost或127.0.0.1 + int OTA_URL_PROTOCOL_ERROR = 10104; // OTA地址必须以http或https开头 + int OTA_URL_FORMAT_ERROR = 10105; // OTA地址必须以/ota/结尾 + int OTA_INTERFACE_ACCESS_FAILED = 10106; // OTA接口访问失败 + int OTA_INTERFACE_FORMAT_ERROR = 10107; // OTA接口返回内容格式不正确 + int OTA_INTERFACE_VALIDATION_FAILED = 10108; // OTA接口验证失败 + int MCP_URL_EMPTY = 10109; // MCP地址不能为空 + int MCP_URL_LOCALHOST = 10110; // MCP地址不能使用localhost或127.0.0.1 + int MCP_URL_INVALID = 10111; // 不是正确的MCP地址 + int MCP_INTERFACE_ACCESS_FAILED = 10112; // MCP接口访问失败 + int MCP_INTERFACE_FORMAT_ERROR = 10113; // MCP接口返回内容格式不正确 + int MCP_INTERFACE_VALIDATION_FAILED = 10114; // MCP接口验证失败 + int VOICEPRINT_URL_EMPTY = 10115; // 声纹接口地址不能为空 + int VOICEPRINT_URL_LOCALHOST = 10116; // 声纹接口地址不能使用localhost或127.0.0.1 + int VOICEPRINT_URL_INVALID = 10117; // 不是正确的声纹接口地址 + int VOICEPRINT_URL_PROTOCOL_ERROR = 10118; // 声纹接口地址必须以http或https开头 + int VOICEPRINT_INTERFACE_ACCESS_FAILED = 10119; // 声纹接口访问失败 + int VOICEPRINT_INTERFACE_FORMAT_ERROR = 10120; // 声纹接口返回内容格式不正确 + int VOICEPRINT_INTERFACE_VALIDATION_FAILED = 10121; // 声纹接口验证失败 + int MQTT_SECRET_EMPTY = 10122; // mqtt密钥不能为空 + int MQTT_SECRET_LENGTH_INSECURE = 10123; // mqtt密钥长度不安全 + int MQTT_SECRET_CHARACTER_INSECURE = 10124; // mqtt密钥必须同时包含大小写字母 + int MQTT_SECRET_WEAK_PASSWORD = 10125; // mqtt密钥包含弱密码 + + // 字典相关错误码 + int DICT_LABEL_DUPLICATE = 10128; // 字典标签重复 } diff --git a/main/manager-api/src/main/java/xiaozhi/common/exception/RenExceptionHandler.java b/main/manager-api/src/main/java/xiaozhi/common/exception/RenExceptionHandler.java index 01f1ccf2..e016bc09 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/exception/RenExceptionHandler.java +++ b/main/manager-api/src/main/java/xiaozhi/common/exception/RenExceptionHandler.java @@ -13,6 +13,7 @@ import org.springframework.web.servlet.resource.NoResourceFoundException; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import xiaozhi.common.utils.MessageUtils; import xiaozhi.common.utils.Result; /** @@ -62,7 +63,7 @@ public class RenExceptionHandler { @ExceptionHandler(NoResourceFoundException.class) public Result handleNoResourceFoundException(NoResourceFoundException ex) { log.warn("Resource not found: {}", ex.getMessage()); - return new Result().error(404, "资源不存在"); + return new Result().error(404, MessageUtils.getMessage(ErrorCode.RESOURCE_NOT_FOUND)); } @ExceptionHandler(MethodArgumentNotValidException.class) @@ -76,7 +77,7 @@ public class RenExceptionHandler { }) .filter(Objects::nonNull) .findFirst() - .orElse("请求参数错误!"); + .orElse(MessageUtils.getMessage(ErrorCode.PARAM_VALUE_NULL)); return new Result().error(ErrorCode.PARAM_VALUE_NULL, errorMsg); } diff --git a/main/manager-api/src/main/java/xiaozhi/common/utils/ResourcesUtils.java b/main/manager-api/src/main/java/xiaozhi/common/utils/ResourcesUtils.java index 49d9a727..cf2d0bcc 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/utils/ResourcesUtils.java +++ b/main/manager-api/src/main/java/xiaozhi/common/utils/ResourcesUtils.java @@ -6,6 +6,7 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; import xiaozhi.common.exception.RenException; +import xiaozhi.common.exception.ErrorCode; import java.io.BufferedReader; @@ -37,7 +38,7 @@ public class ResourcesUtils { } } catch (IOException e){ log.error("方法:loadString()读取资源失败--{}",e.getMessage()); - throw new RenException("读取资源失败"); + throw new RenException(ErrorCode.RESOURCE_READ_ERROR); } return luaScriptBuilder.toString(); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentVoicePrintController.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentVoicePrintController.java index 1615cee5..9b7555eb 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentVoicePrintController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentVoicePrintController.java @@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.AllArgsConstructor; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.utils.Result; import xiaozhi.modules.agent.dto.AgentVoicePrintSaveDTO; @@ -42,7 +43,7 @@ public class AgentVoicePrintController { if (b) { return new Result<>(); } - return new Result().error("智能体的声纹创建失败"); + return new Result().error(ErrorCode.AGENT_VOICEPRINT_CREATE_FAILED); } @PutMapping @@ -54,7 +55,7 @@ public class AgentVoicePrintController { if (b) { return new Result<>(); } - return new Result().error("智能体的对应声纹更新失败"); + return new Result().error(ErrorCode.AGENT_VOICEPRINT_UPDATE_FAILED); } @DeleteMapping("/{id}") @@ -67,7 +68,7 @@ public class AgentVoicePrintController { if (delete) { return new Result<>(); } - return new Result().error("智能体的对应声纹删除失败"); + return new Result().error(ErrorCode.AGENT_VOICEPRINT_DELETE_FAILED); } @GetMapping("/list/{id}") @@ -76,7 +77,7 @@ public class AgentVoicePrintController { public Result> list(@PathVariable String id) { String voiceprintUrl = sysParamsService.getValue("server.voice_print", true); if (StringUtils.isBlank(voiceprintUrl) || "null".equals(voiceprintUrl)) { - throw new RenException("声纹接口未配置,请先在参数配置中配置声纹接口地址(server.voice_print)"); + throw new RenException(ErrorCode.VOICEPRINT_API_NOT_CONFIGURED); } Long userId = SecurityUser.getUserId(); List list = agentVoicePrintService.list(userId, id); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java index 4f5681e2..9ec04a4e 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java @@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.AllArgsConstructor; import xiaozhi.common.constant.Constant; import xiaozhi.common.exception.RenException; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.page.PageData; import xiaozhi.common.redis.RedisKeys; import xiaozhi.common.redis.RedisUtils; @@ -74,7 +75,7 @@ public class AgentServiceImpl extends BaseServiceImpl imp AgentInfoVO agent = agentDao.selectAgentInfoById(id); if (agent == null) { - throw new RenException("智能体不存在"); + throw new RenException(ErrorCode.AGENT_NOT_FOUND); } if (agent.getMemModelId() != null && agent.getMemModelId().equals(Constant.MEMORY_NO_MEM)) { @@ -204,7 +205,7 @@ public class AgentServiceImpl extends BaseServiceImpl imp // 先查询现有实体 AgentEntity existingEntity = this.getAgentById(agentId); if (existingEntity == null) { - throw new RuntimeException("智能体不存在"); + throw new RenException(ErrorCode.AGENT_NOT_FOUND); } // 只更新提供的非空字段 @@ -328,7 +329,7 @@ public class AgentServiceImpl extends BaseServiceImpl imp boolean b = validateLLMIntentParams(dto.getLlmModelId(), dto.getIntentModelId()); if (!b) { - throw new RenException("LLM大模型和Intent意图识别,选择参数不匹配"); + throw new RenException(ErrorCode.LLM_INTENT_PARAMS_MISMATCH); } this.updateById(existingEntity); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java index 31accbab..088e4663 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java @@ -26,6 +26,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import xiaozhi.common.constant.Constant; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.utils.ConvertUtils; import xiaozhi.common.utils.JsonUtils; @@ -78,7 +79,7 @@ public class AgentVoicePrintServiceImpl extends ServiceImpl @Override public Boolean deviceActivation(String agentId, String activationCode) { if (StringUtils.isBlank(activationCode)) { - throw new RenException("激活码不能为空"); + throw new RenException(ErrorCode.ACTIVATION_CODE_EMPTY); } String deviceKey = "ota:activation:code:" + activationCode; Object cacheDeviceId = redisUtils.get(deviceKey); if (cacheDeviceId == null) { - throw new RenException("激活码错误"); + throw new RenException(ErrorCode.ACTIVATION_CODE_ERROR); } String deviceId = (String) cacheDeviceId; String safeDeviceId = deviceId.replace(":", "_").toLowerCase(); String cacheDeviceKey = String.format("ota:activation:data:%s", safeDeviceId); Map cacheMap = (Map) redisUtils.get(cacheDeviceKey); if (cacheMap == null) { - throw new RenException("激活码错误"); + throw new RenException(ErrorCode.ACTIVATION_CODE_ERROR); } String cachedCode = (String) cacheMap.get("activation_code"); if (!activationCode.equals(cachedCode)) { - throw new RenException("激活码错误"); + throw new RenException(ErrorCode.ACTIVATION_CODE_ERROR); } // 检查设备有没有被激活 if (selectById(deviceId) != null) { - throw new RenException("设备已激活"); + throw new RenException(ErrorCode.DEVICE_ALREADY_ACTIVATED); } String macAddress = (String) cacheMap.get("mac_address"); @@ -111,7 +112,7 @@ public class DeviceServiceImpl extends BaseServiceImpl String appVersion = (String) cacheMap.get("app_version"); UserDetail user = SecurityUser.getUser(); if (user.getId() == null) { - throw new RenException("用户未登录"); + throw new RenException(ErrorCode.USER_NOT_LOGIN); } Date currentTime = new Date(); @@ -441,7 +442,7 @@ public class DeviceServiceImpl extends BaseServiceImpl wrapper.eq("mac_address", dto.getMacAddress()); DeviceEntity exist = baseDao.selectOne(wrapper); if (exist != null) { - throw new RenException("该Mac地址已存在"); + throw new RenException(ErrorCode.MAC_ADDRESS_ALREADY_EXISTS); } Date now = new Date(); DeviceEntity entity = new DeviceEntity(); 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 c156b408..936e67f3 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 @@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import cn.hutool.core.collection.CollectionUtil; import lombok.AllArgsConstructor; 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; @@ -94,7 +95,7 @@ public class ModelConfigServiceImpl extends BaseServiceImpl providerList = modelProviderService.getList(modelType, provideCode); if (CollectionUtil.isEmpty(providerList)) { - throw new RenException("供应器不存在"); + throw new RenException(ErrorCode.MODEL_PROVIDER_NOT_EXIST); } // 再保存供应器提供的模型 @@ -113,7 +114,7 @@ public class ModelConfigServiceImpl extends BaseServiceImpl providerList = modelProviderService.getList(modelType, provideCode); if (CollectionUtil.isEmpty(providerList)) { - throw new RenException("供应器不存在"); + throw new RenException(ErrorCode.MODEL_PROVIDER_NOT_EXIST); } if (modelConfigBodyDTO.getConfigJson().containsKey("llm")) { String llm = modelConfigBodyDTO.getConfigJson().get("llm").toString(); @@ -122,12 +123,12 @@ public class ModelConfigServiceImpl extends BaseServiceImpl ids) { if (modelProviderDao.deleteBatchIds(ids) == 0) { - throw new RenException("删除数据失败"); + throw new RenException(ErrorCode.DELETE_DATA_FAILED); } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/config/WebMvcConfig.java b/main/manager-api/src/main/java/xiaozhi/modules/security/config/WebMvcConfig.java index 02538caf..f13194b1 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/config/WebMvcConfig.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/config/WebMvcConfig.java @@ -2,8 +2,11 @@ package xiaozhi.modules.security.config; import java.text.SimpleDateFormat; import java.util.List; +import java.util.Locale; import java.util.TimeZone; +import jakarta.servlet.http.HttpServletRequest; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.ByteArrayHttpMessageConverter; @@ -12,8 +15,10 @@ import org.springframework.http.converter.ResourceHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; +import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -95,5 +100,47 @@ public class WebMvcConfig implements WebMvcConfigurer { converter.setObjectMapper(mapper); return converter; } + + /** + * 国际化配置 - 根据请求头中的Accept-Language设置语言环境 + */ + @Bean + public LocaleResolver localeResolver() { + return new AcceptHeaderLocaleResolver() { + @Override + public Locale resolveLocale(HttpServletRequest request) { + String acceptLanguage = request.getHeader("Accept-Language"); + if (acceptLanguage == null || acceptLanguage.isEmpty()) { + return Locale.getDefault(); + } + + // 解析Accept-Language请求头中的首选语言 + String[] languages = acceptLanguage.split(","); + if (languages.length > 0) { + // 提取第一个语言代码,去除可能的质量值(q=...) + String[] parts = languages[0].split(";" + "\\s*"); + String primaryLanguage = parts[0].trim(); + + // 根据前端发送的语言代码直接创建Locale对象 + if (primaryLanguage.equals("zh-CN")) { + return Locale.SIMPLIFIED_CHINESE; + } else if (primaryLanguage.equals("zh-TW")) { + return Locale.TRADITIONAL_CHINESE; + } else if (primaryLanguage.equals("en-US")) { + return Locale.US; + } else if (primaryLanguage.startsWith("zh")) { + // 对于其他中文变体,默认使用简体中文 + return Locale.SIMPLIFIED_CHINESE; + } else if (primaryLanguage.startsWith("en")) { + // 对于其他英文变体,默认使用美式英语 + return Locale.US; + } + } + + // 如果没有匹配的语言,使用默认语言 + return Locale.getDefault(); + } + }; + } } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java b/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java index 0215cf7e..d7333273 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/controller/LoginController.java @@ -68,12 +68,12 @@ public class LoginController { // 验证图形验证码 boolean validate = captchaService.validate(dto.getCaptchaId(), dto.getCaptcha(), true); if (!validate) { - throw new RenException("图形验证码错误"); + throw new RenException(ErrorCode.SMS_CAPTCHA_ERROR); } Boolean isMobileRegister = sysParamsService .getValueObject(Constant.SysMSMParam.SERVER_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class); if (!isMobileRegister) { - throw new RenException("没有开启手机注册,没法使用短信验证码功能"); + throw new RenException(ErrorCode.MOBILE_REGISTER_DISABLED); } // 发送短信验证码 captchaService.sendSMSValidateCode(dto.getPhone()); @@ -86,17 +86,17 @@ public class LoginController { // 验证是否正确输入验证码 boolean validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha(), true); if (!validate) { - throw new RenException("图形验证码错误,请重新获取"); + throw new RenException(ErrorCode.SMS_CAPTCHA_ERROR); } // 按照用户名获取用户 SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername()); // 判断用户是否存在 if (userDTO == null) { - throw new RenException("请检测用户和密码是否输入错误"); + throw new RenException(ErrorCode.ACCOUNT_PASSWORD_ERROR); } // 判断密码是否正确,不一样则进入if if (!PasswordUtils.matches(login.getPassword(), userDTO.getPassword())) { - throw new RenException("请检测用户和密码是否输入错误"); + throw new RenException(ErrorCode.ACCOUNT_PASSWORD_ERROR); } return sysUserTokenService.createToken(userDTO.getId()); } @@ -105,7 +105,7 @@ public class LoginController { @Operation(summary = "注册") public Result register(@RequestBody LoginDTO login) { if (!sysUserService.getAllowUserRegister()) { - throw new RenException("当前不允许普通用户注册"); + throw new RenException(ErrorCode.USER_REGISTER_DISABLED); } // 是否开启手机注册 Boolean isMobileRegister = sysParamsService @@ -115,25 +115,25 @@ public class LoginController { // 验证用户是否是手机号码 boolean validPhone = ValidatorUtils.isValidPhone(login.getUsername()); if (!validPhone) { - throw new RenException("用户名不是手机号码,请重新输入"); + throw new RenException(ErrorCode.USERNAME_NOT_PHONE); } // 验证短信验证码是否正常 validate = captchaService.validateSMSValidateCode(login.getUsername(), login.getMobileCaptcha(), false); if (!validate) { - throw new RenException("手机验证码错误,请重新获取"); + throw new RenException(ErrorCode.SMS_CODE_ERROR); } } else { // 验证是否正确输入验证码 validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha(), true); if (!validate) { - throw new RenException("图形验证码错误,请重新获取"); + throw new RenException(ErrorCode.SMS_CAPTCHA_ERROR); } } // 按照用户名获取用户 SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername()); if (userDTO != null) { - throw new RenException("此手机号码已经注册过"); + throw new RenException(ErrorCode.PHONE_ALREADY_REGISTERED); } userDTO = new SysUserDTO(); userDTO.setUsername(login.getUsername()); @@ -168,26 +168,26 @@ public class LoginController { Boolean isMobileRegister = sysParamsService .getValueObject(Constant.SysMSMParam.SERVER_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class); if (!isMobileRegister) { - throw new RenException("没有开启手机注册,没法使用找回密码功能"); + throw new RenException(ErrorCode.RETRIEVE_PASSWORD_DISABLED); } // 判断非空 ValidatorUtils.validateEntity(dto); // 验证用户是否是手机号码 boolean validPhone = ValidatorUtils.isValidPhone(dto.getPhone()); if (!validPhone) { - throw new RenException("输入的手机号码格式不正确"); + throw new RenException(ErrorCode.PHONE_FORMAT_ERROR); } // 按照用户名获取用户 SysUserDTO userDTO = sysUserService.getByUsername(dto.getPhone()); if (userDTO == null) { - throw new RenException("输入的手机号码未注册"); + throw new RenException(ErrorCode.PHONE_NOT_REGISTERED); } // 验证短信验证码是否正常 boolean validate = captchaService.validateSMSValidateCode(dto.getPhone(), dto.getCode(), false); // 判断是否通过验证 if (!validate) { - throw new RenException("输入的手机验证码错误"); + throw new RenException(ErrorCode.SMS_CODE_ERROR); } sysUserService.changePasswordDirectly(userDTO.getId(), dto.getPassword()); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Filter.java b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Filter.java index aad888df..59d7e09e 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Filter.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Filter.java @@ -18,6 +18,7 @@ import xiaozhi.common.constant.Constant; import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.utils.HttpContextUtils; import xiaozhi.common.utils.JsonUtils; +import xiaozhi.common.utils.MessageUtils; import xiaozhi.common.utils.Result; /** @@ -82,8 +83,8 @@ public class Oauth2Filter extends AuthenticatingFilter { httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin()); try { - Throwable throwable = e.getCause() == null ? e : e.getCause(); - Result r = new Result().error(ErrorCode.UNAUTHORIZED, throwable.getMessage()); + // 使用国际化消息替代直接使用异常消息 + Result r = new Result().error(ErrorCode.UNAUTHORIZED); String json = JsonUtils.toJsonString(r); httpResponse.getWriter().print(json); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/TokenGenerator.java b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/TokenGenerator.java index 6d7be47a..17ea9beb 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/TokenGenerator.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/TokenGenerator.java @@ -3,6 +3,7 @@ package xiaozhi.modules.security.oauth2; import java.security.MessageDigest; import java.util.UUID; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; /** @@ -38,7 +39,7 @@ public class TokenGenerator { byte[] messageDigest = algorithm.digest(); return toHexString(messageDigest); } catch (Exception e) { - throw new RenException("token invalid", e); + throw new RenException(ErrorCode.TOKEN_GENERATE_ERROR, e); } } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/CaptchaServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/CaptchaServiceImpl.java index e823d70e..0d3666db 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/CaptchaServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/CaptchaServiceImpl.java @@ -16,6 +16,7 @@ import com.wf.captcha.base.Captcha; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import xiaozhi.common.constant.Constant; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.redis.RedisKeys; import xiaozhi.common.redis.RedisUtils; @@ -88,7 +89,7 @@ public class CaptchaServiceImpl implements CaptchaService { long currentTime = System.currentTimeMillis(); long timeDiff = currentTime - lastSendTimeLong; if (timeDiff < 60000) { - throw new RenException("发送太频繁,请" + (60000 - timeDiff) / 1000 + "秒后再试"); + throw new RenException(ErrorCode.SMS_SEND_TOO_FREQUENTLY, String.valueOf((60000 - timeDiff) / 1000)); } } @@ -108,7 +109,7 @@ public class CaptchaServiceImpl implements CaptchaService { } if (todayCount >= maxSendCount) { - throw new RenException("今日发送次数已达上限"); + throw new RenException(ErrorCode.TODAY_SMS_LIMIT_REACHED); } String key = RedisKeys.getSMSValidateCodeKey(phone); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/sms/service/imp/ALiYunSmsService.java b/main/manager-api/src/main/java/xiaozhi/modules/sms/service/imp/ALiYunSmsService.java index e0ebb523..a8a378f0 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/sms/service/imp/ALiYunSmsService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/sms/service/imp/ALiYunSmsService.java @@ -9,6 +9,7 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import xiaozhi.common.constant.Constant; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.redis.RedisKeys; import xiaozhi.common.redis.RedisUtils; @@ -45,7 +46,7 @@ public class ALiYunSmsService implements SmsService { redisUtils.delete(todayCountKey); // 错误 message log.error(e.getMessage()); - throw new RenException("短信发送失败"); + throw new RenException(ErrorCode.SMS_SEND_FAILED); } } @@ -70,7 +71,7 @@ public class ALiYunSmsService implements SmsService { }catch (Exception e){ // 错误 message log.error(e.getMessage()); - throw new RenException("短信连接建立失败"); + throw new RenException(ErrorCode.SMS_CONNECTION_FAILED); } } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/ServerSideManageController.java b/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/ServerSideManageController.java index 0b6b6a5b..893ea8e2 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/ServerSideManageController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/ServerSideManageController.java @@ -22,6 +22,7 @@ import jakarta.validation.Valid; import lombok.AllArgsConstructor; import xiaozhi.common.annotation.LogOperation; import xiaozhi.common.constant.Constant; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.utils.Result; import xiaozhi.modules.sys.dto.EmitSeverActionDTO; @@ -64,17 +65,17 @@ public class ServerSideManageController { @RequiresPermissions("sys:role:superAdmin") public Result emitServerAction(@RequestBody @Valid EmitSeverActionDTO emitSeverActionDTO) { if (emitSeverActionDTO.getAction() == null) { - throw new RenException("无效服务端操作"); + throw new RenException(ErrorCode.INVALID_SERVER_ACTION); } String wsText = sysParamsService.getValue(Constant.SERVER_WEBSOCKET, true); if (StringUtils.isBlank(wsText)) { - throw new RenException("未配置服务端WebSocket地址"); + throw new RenException(ErrorCode.SERVER_WEBSOCKET_NOT_CONFIGURED); } String targetWs = emitSeverActionDTO.getTargetWs(); String[] wsList = wsText.split(";"); // 找到需要发起的 if (StringUtils.isBlank(targetWs) || !Arrays.asList(wsList).contains(targetWs)) { - throw new RenException("目标WebSocket地址不存在"); + throw new RenException(ErrorCode.TARGET_WEBSOCKET_NOT_EXIST); } return new Result().ok(emitServerActionByWs(targetWs, emitSeverActionDTO.getAction())); } @@ -114,7 +115,7 @@ public class ServerSideManageController { }); } catch (Exception e) { // 捕获全部错误,由全局异常处理器返回 - throw new RenException("WebSocket连接失败或连接超时"); + throw new RenException(ErrorCode.WEB_SOCKET_CONNECT_FAILED); } return true; } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java b/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java index d1c116c3..24b070c0 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java @@ -25,6 +25,7 @@ import lombok.AllArgsConstructor; import xiaozhi.common.annotation.LogOperation; import xiaozhi.common.constant.Constant; import xiaozhi.common.exception.RenException; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.page.PageData; import xiaozhi.common.utils.Result; import xiaozhi.common.validator.AssertUtils; @@ -130,23 +131,23 @@ public class SysParamsController { } String[] wsUrls = urls.split("\\;"); if (wsUrls.length == 0) { - throw new RenException("WebSocket地址列表不能为空"); + throw new RenException(ErrorCode.WEBSOCKET_URLS_EMPTY); } for (String url : wsUrls) { if (StringUtils.isNotBlank(url)) { // 检查是否包含localhost或127.0.0.1 if (url.contains("localhost") || url.contains("127.0.0.1")) { - throw new RenException("WebSocket地址不能使用localhost或127.0.0.1"); + throw new RenException(ErrorCode.WEBSOCKET_URL_LOCALHOST); } // 验证WebSocket地址格式 if (!WebSocketValidator.validateUrlFormat(url)) { - throw new RenException("WebSocket地址格式不正确: " + url); + throw new RenException(ErrorCode.WEBSOCKET_URL_FORMAT_ERROR); } // 测试WebSocket连接 if (!WebSocketValidator.testConnection(url)) { - throw new RenException("WebSocket连接测试失败: " + url); + throw new RenException(ErrorCode.WEBSOCKET_CONNECTION_FAILED); } } } @@ -173,35 +174,35 @@ public class SysParamsController { return; } if (StringUtils.isBlank(url) || url.equals("null")) { - throw new RenException("OTA地址不能为空"); + throw new RenException(ErrorCode.OTA_URL_EMPTY); } // 检查是否包含localhost或127.0.0.1 if (url.contains("localhost") || url.contains("127.0.0.1")) { - throw new RenException("OTA地址不能使用localhost或127.0.0.1"); + throw new RenException(ErrorCode.OTA_URL_LOCALHOST); } // 验证URL格式 if (!url.toLowerCase().startsWith("http")) { - throw new RenException("OTA地址必须以http或https开头"); + throw new RenException(ErrorCode.OTA_URL_PROTOCOL_ERROR); } if (!url.endsWith("/ota/")) { - throw new RenException("OTA地址必须以/ota/结尾"); + throw new RenException(ErrorCode.OTA_URL_FORMAT_ERROR); } try { // 发送GET请求 ResponseEntity response = restTemplate.getForEntity(url, String.class); if (response.getStatusCode() != HttpStatus.OK) { - throw new RenException("OTA接口访问失败,状态码:" + response.getStatusCode()); + throw new RenException(ErrorCode.OTA_INTERFACE_ACCESS_FAILED); } // 检查响应内容是否包含OTA相关信息 String body = response.getBody(); if (body == null || !body.contains("OTA")) { - throw new RenException("OTA接口返回内容格式不正确,可能不是一个真实的OTA接口"); + throw new RenException(ErrorCode.OTA_INTERFACE_FORMAT_ERROR); } } catch (Exception e) { - throw new RenException("OTA接口验证失败:" + e.getMessage()); + throw new RenException(ErrorCode.OTA_INTERFACE_VALIDATION_FAILED); } } @@ -210,28 +211,28 @@ public class SysParamsController { return; } if (StringUtils.isBlank(url) || url.equals("null")) { - throw new RenException("MCP地址不能为空"); + throw new RenException(ErrorCode.MCP_URL_EMPTY); } if (url.contains("localhost") || url.contains("127.0.0.1")) { - throw new RenException("MCP地址不能使用localhost或127.0.0.1"); + throw new RenException(ErrorCode.MCP_URL_LOCALHOST); } if (!url.toLowerCase().contains("key")) { - throw new RenException("不是正确的MCP地址"); + throw new RenException(ErrorCode.MCP_URL_INVALID); } try { // 发送GET请求 ResponseEntity response = restTemplate.getForEntity(url, String.class); if (response.getStatusCode() != HttpStatus.OK) { - throw new RenException("MCP接口访问失败,状态码:" + response.getStatusCode()); + throw new RenException(ErrorCode.MCP_INTERFACE_ACCESS_FAILED); } // 检查响应内容是否包含mcp相关信息 String body = response.getBody(); if (body == null || !body.contains("success")) { - throw new RenException("MCP接口返回内容格式不正确,可能不是一个真实的MCP接口"); + throw new RenException(ErrorCode.MCP_INTERFACE_FORMAT_ERROR); } } catch (Exception e) { - throw new RenException("MCP接口验证失败:" + e.getMessage()); + throw new RenException(ErrorCode.MCP_INTERFACE_VALIDATION_FAILED); } } @@ -241,31 +242,31 @@ public class SysParamsController { return; } if (StringUtils.isBlank(url) || url.equals("null")) { - throw new RenException("声纹接口地址不能为空"); + throw new RenException(ErrorCode.VOICEPRINT_URL_EMPTY); } if (url.contains("localhost") || url.contains("127.0.0.1")) { - throw new RenException("声纹接口地址不能使用localhost或127.0.0.1"); + throw new RenException(ErrorCode.VOICEPRINT_URL_LOCALHOST); } if (!url.toLowerCase().contains("key")) { - throw new RenException("不是正确的声纹接口地址"); + throw new RenException(ErrorCode.VOICEPRINT_URL_INVALID); } // 验证URL格式 if (!url.toLowerCase().startsWith("http")) { - throw new RenException("声纹接口地址必须以http或https开头"); + throw new RenException(ErrorCode.VOICEPRINT_URL_PROTOCOL_ERROR); } try { // 发送GET请求 ResponseEntity response = restTemplate.getForEntity(url, String.class); if (response.getStatusCode() != HttpStatus.OK) { - throw new RenException("声纹接口访问失败,状态码:" + response.getStatusCode()); + throw new RenException(ErrorCode.VOICEPRINT_INTERFACE_ACCESS_FAILED); } // 检查响应内容 String body = response.getBody(); if (body == null || !body.contains("healthy")) { - throw new RenException("声纹接口返回内容格式不正确,可能不是一个真实的MCP接口"); + throw new RenException(ErrorCode.VOICEPRINT_INTERFACE_FORMAT_ERROR); } } catch (Exception e) { - throw new RenException("声纹接口验证失败:" + e.getMessage()); + throw new RenException(ErrorCode.VOICEPRINT_INTERFACE_VALIDATION_FAILED); } } @@ -275,20 +276,20 @@ public class SysParamsController { return; } if (StringUtils.isBlank(secret) || secret.equals("null")) { - throw new RenException("mqtt密钥不能为空"); + throw new RenException(ErrorCode.MQTT_SECRET_EMPTY); } if (secret.length() < 8) { - throw new RenException("您的mqtt密钥长度不安全,字符数需要至少8个字符且必须同时包含大小写字母"); + throw new RenException(ErrorCode.MQTT_SECRET_LENGTH_INSECURE); } // 检查是否同时包含大小写字母 if (!secret.matches(".*[a-z].*") || !secret.matches(".*[A-Z].*")) { - throw new RenException("您的mqtt密钥长度不安全,mqtt密钥必须同时包含大小写字母"); + throw new RenException(ErrorCode.MQTT_SECRET_CHARACTER_INSECURE); } // 不允许包含弱密码 String[] weakPasswords = { "test", "1234", "admin", "password", "qwerty", "xiaozhi" }; for (String weakPassword : weakPasswords) { if (secret.toLowerCase().contains(weakPassword)) { - throw new RenException("您的mqtt密钥包含弱密码:" + weakPassword); + throw new RenException(ErrorCode.MQTT_SECRET_WEAK_PASSWORD); } } } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysDictDataServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysDictDataServiceImpl.java index ffe88986..a2adb150 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysDictDataServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysDictDataServiceImpl.java @@ -17,6 +17,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.AllArgsConstructor; import xiaozhi.common.exception.RenException; +import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.page.PageData; import xiaozhi.common.redis.RedisKeys; import xiaozhi.common.redis.RedisUtils; @@ -153,7 +154,7 @@ public class SysDictDataServiceImpl extends BaseServiceImpl { - showSuccess("登录成功!"); + showSuccess(this.$t('login.loginSuccess')); this.$store.commit("setToken", JSON.stringify(data.data)); goToPage("/home"); }, (err) => { - showDanger(err.data.msg || "登录失败"); + // 直接使用后端返回的国际化消息 + let errorMessage = err.data.msg || "登录失败"; + + showDanger(errorMessage); if ( err.data != null && err.data.msg != null && - err.data.msg.indexOf("图形验证码") > -1 + err.data.msg.indexOf("图形验证码") > -1 || err.data.msg.indexOf("Captcha") > -1 ) { this.fetchCaptcha(); } diff --git a/main/manager-web/src/views/register.vue b/main/manager-web/src/views/register.vue index 873cc9a6..c839abc8 100644 --- a/main/manager-web/src/views/register.vue +++ b/main/manager-web/src/views/register.vue @@ -47,7 +47,7 @@ - 验证码 @@ -61,7 +61,7 @@ - {{ countdown > 0 ? `${countdown}秒后重试` : $t('register.sendCaptcha') }} + {{ countdown > 0 ? `${countdown}${$t('register.secondsLater')}` : $t('register.sendCaptcha') }} @@ -248,18 +248,18 @@ export default { return; } if (!this.form.mobileCaptcha) { - showDanger('请输入手机验证码'); + showDanger(this.$t('register.requiredMobileCaptcha')); return; } } else { // 用户名注册验证 - if (!this.validateInput(this.form.username, '用户名不能为空')) { + if (!this.validateInput(this.form.username, this.$t('register.requiredUsername'))) { return; } } // 验证密码 - if (!this.validateInput(this.form.password, '密码不能为空')) { + if (!this.validateInput(this.form.password, this.$t('register.requiredPassword'))) { return; } if (this.form.password !== this.form.confirmPassword) { @@ -267,7 +267,7 @@ export default { return } // 验证验证码 - if (!this.validateInput(this.form.captcha, '验证码不能为空')) { + if (!this.validateInput(this.form.captcha, this.$t('register.requiredCaptcha'))) { return; } From 300a33ddc28224726e61947b61d989cc6c5a9823 Mon Sep 17 00:00:00 2001 From: rainv123 <2148537152@qq.com> Date: Wed, 17 Sep 2025 14:10:07 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix=EF=BC=9A=E6=99=BA=E8=83=BD=E4=BD=93?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AE=BE=E5=A4=87=E9=A1=B5=E9=9D=A2=E7=9A=84?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E6=96=87=E5=AD=97=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/manager-web/src/i18n/en.js | 2 +- main/manager-web/src/i18n/zh_CN.js | 2 +- main/manager-web/src/i18n/zh_TW.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main/manager-web/src/i18n/en.js b/main/manager-web/src/i18n/en.js index d7ebfd3b..54d25ccb 100644 --- a/main/manager-web/src/i18n/en.js +++ b/main/manager-web/src/i18n/en.js @@ -324,7 +324,7 @@ export default { 'device.search': 'Search', 'device.selectAll': 'Select All/Deselect All', 'deviceManagement.loading': 'Loading...', - 'device.bindWithCode': 'Bind with Verification Code', + 'device.bindWithCode': '6-digit Verification Code Binding', 'device.manualAdd': 'Manual Add', 'device.unbind': 'Unbind', 'device.selectAtLeastOne': 'Please select at least one record', diff --git a/main/manager-web/src/i18n/zh_CN.js b/main/manager-web/src/i18n/zh_CN.js index 892898d2..ee338f6b 100644 --- a/main/manager-web/src/i18n/zh_CN.js +++ b/main/manager-web/src/i18n/zh_CN.js @@ -325,7 +325,7 @@ export default { 'device.search': '搜索', 'device.selectAll': '全选/取消全选', 'deviceManagement.loading': '拼命加载中', - 'device.bindWithCode': '扫码绑定', + 'device.bindWithCode': '6位验证码绑定', 'device.manualAdd': '手动添加', 'device.unbind': '解绑', 'device.selectAtLeastOne': '请至少选择一条记录', diff --git a/main/manager-web/src/i18n/zh_TW.js b/main/manager-web/src/i18n/zh_TW.js index d5b91421..97cccba6 100644 --- a/main/manager-web/src/i18n/zh_TW.js +++ b/main/manager-web/src/i18n/zh_TW.js @@ -324,7 +324,7 @@ export default { 'device.search': '搜索', 'device.selectAll': '全選/取消全選', 'deviceManagement.loading': '拼命加載中', - 'device.bindWithCode': '驗證碼綁定', + 'device.bindWithCode': '6位驗證碼綁定', 'device.manualAdd': '手動添加', 'device.unbind': '解綁', 'device.selectAtLeastOne': '請至少選擇一條記錄', From 3767bf8c8153c40f47a7a0a36db3988373dfab6a Mon Sep 17 00:00:00 2001 From: FAN-yeB <1442100690@qq.com> Date: Wed, 17 Sep 2025 15:31:54 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20messages.properties?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/i18n/messages.properties | 93 +++++++++++++------ 1 file changed, 64 insertions(+), 29 deletions(-) diff --git a/main/manager-api/src/main/resources/i18n/messages.properties b/main/manager-api/src/main/resources/i18n/messages.properties index e65f9b3e..30bdb8d1 100644 --- a/main/manager-api/src/main/resources/i18n/messages.properties +++ b/main/manager-api/src/main/resources/i18n/messages.properties @@ -1,7 +1,8 @@ -#Default +#简体中文 500=服务器内部异常 401=未授权 403=拒绝访问,没有权限 + 10001={0}不能为空 10002=数据库中已存在该记录 10003=获取参数失败 @@ -9,9 +10,10 @@ 10005=账号已被停用 10006=唯一标识不能为空 10007=验证码不正确 -10008=手机号不能为空 +10008=先删除子菜单或按钮 10009=原密码不正确 10010=账号或密码不正确,您还有可以尝试{0}次 + 10011=上级部门选择错误 10012=上级菜单不能为自身 10013=数据权限接口,只能是Map类型参数 @@ -20,19 +22,22 @@ 10016=部署失败,没有流程 10017=模型图不正确,请检查 10018=导出失败,模型ID为{0} + 10019=请上传文件 10020=token不能为空 10021=token失效,请重新登录 10022=账号已被锁定 10023=请上传zip、bar、bpmn、bpmn20.xml格式文件 + 10024=上传文件失败{0} 10025=发送短信失败{0} 10026=邮件模板不存在 + 10027=Redis服务异常 10028=定时任务失败 10029=不能包含非法字符 10030=密码长度不足{0}位 -10031=弱密码 +10031=密码必须同时包含数字、大小写字母和特殊字符组成 10032=删除本数据异常 10033=设备验证码错误 @@ -50,7 +55,7 @@ 10044=用户未登录 10045=WebSocket连接失败或连接超时 10046=保存声纹错误,请联系管理员 -10047=今日发送次数已达上限 +10047=每日发送次数已达上限 10048=旧密码输入错误 10049=设置的LLM不是openai和ollama 10050=token生成失败 @@ -63,7 +68,7 @@ 10057=智能体的声纹创建失败 10058=智能体的对应声纹更新失败 10059=智能体的对应声纹删除失败 -10060=发送太频繁,请{0}秒后再试 +10060=发送太频繁,请{0}秒后再试 10061=激活码不能为空 10062=激活码错误 10063=设备已激活 @@ -72,31 +77,61 @@ 10066=修改数据失败 10067=图形验证码错误 10068=没有开启手机注册,没法使用短信验证码功能 -10067=用户名不是手机号码,请重新输入 -10068=此手机号码已经注册过 -10069=输入的手机号码未注册 -10070=当前不允许普通用户注册 -10071=没有开启手机注册,没法使用找回密码功能 -10072=输入的手机号码格式不正确 -10073=输入的手机验证码错误 -10074=字典类型不存在 -10075=字典类型编码重复 -10076=读取资源失败 -10077=LLM大模型和Intent意图识别,选择参数不匹配 -10078=此声音声纹对应的人({0})已经注册,请选择其他声音注册 -10079=删除声纹出现错误 -10080=此次修改不允许,此声音已经注册为声纹了({0}) -10081=修改声纹错误,请联系管理员 -10082=声纹接口地址存在错误,请进入参数管理修改声纹接口地址 -10083=音频数据不属于这个智能体 -10084=音频数据是空的请检查上传数据 -10085=声纹保存失败,请求不成功 -10086=声纹保存失败,请求处理失败 -10087=声纹注销失败,请求不成功 -10088=声纹注销失败,请求处理失败 -10089=声纹识别失败,请求不成功 -10090=该Mac地址已存在 +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=字典标签重复 \ No newline at end of file From 62eaf46f343103569581430de7f7152e8bdda911 Mon Sep 17 00:00:00 2001 From: rainv123 <2148537152@qq.com> Date: Wed, 17 Sep 2025 15:35:21 +0800 Subject: [PATCH 4/4] =?UTF-8?q?updata:=E5=AE=9E=E7=8E=B0=E5=90=8E=E7=AB=AF?= =?UTF-8?q?msg=E7=9A=84=E5=9B=BD=E9=99=85=E5=8C=96=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=94=A8=E6=88=B7=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=92=8C=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=9A=84=E7=A1=AC=E7=BC=96=E7=A0=81=E4=B8=BA?= =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96=E9=94=AE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/i18n/messages_zh_TW.properties | 1 - 1 file changed, 1 deletion(-) 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 87a73075..eb4e4ae5 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 @@ -73,7 +73,6 @@ 10062=激活碼錯誤 10063=設備已激活 10064=該模型為預設模型,請先設置其他模型為預設模型 - 10065=新增數據失敗 10066=更新數據失敗 10067=圖形驗證碼錯誤