diff --git a/.gitignore b/.gitignore index 698d638c..d0709f97 100644 --- a/.gitignore +++ b/.gitignore @@ -141,13 +141,17 @@ music/ # Cython debug symbols cython_debug/ *.iml -model.pt tmp +.history .DS_Store main/xiaozhi-server/data +main/xiaozhi-server/config/assets/wakeup_words.* main/manager-web/node_modules .config.yaml .secrets.yaml .private_config.yaml .env.development +# model files +main/xiaozhi-server/models/SenseVoiceSmall/model.pt +main/xiaozhi-server/models/sherpa-onnx* diff --git a/README.md b/README.md index cdf31847..191790bc 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ - + 控制家电开关 @@ -95,6 +95,11 @@ + + + 播报新闻 + + @@ -185,7 +190,6 @@ server: | LLM | FastgptLLM | fastgpt 接口调用 | 免费/消耗 token | 本地化部署,注意配置提示词需在 Fastgpt 控制台设置 | | LLM | GeminiLLM | gemini 接口调用 | 免费 | [点击申请密钥](https://aistudio.google.com/apikey) | | LLM | CozeLLM | coze 接口调用 | 消耗 token | 需提供 bot_id、user_id 及个人令牌 | -| LLM | Home Assistant | homeassistant语音助手接口调用 | 免费 | 需提供home assistant令牌 | 实际上,任何支持 openai 接口调用的 LLM 均可接入使用。 @@ -201,6 +205,7 @@ server: | TTS | CosyVoiceSiliconflow | 接口调用 | 消耗 token | 需申请硅基流动 API 密钥;输出格式为 wav | | TTS | TTS302AI | 接口调用 | 消耗 token | [点击创建密钥](https://dash.302.ai/apis/list) | | TTS | CozeCnTTS | 接口调用 | 消耗 token | 需提供 Coze API key;输出格式为 wav | +| TTS | GizwitsTTS | 接口调用 | 消耗 token | [点击创建密钥](https://agentrouter.gizwitsapi.com) | | TTS | ACGNTTS | 接口调用 | 消耗 token | [联系网站管理员购买密钥](www.ttson.cn) | | TTS | OpenAITTS | 接口调用 | 消耗 token | 境外使用,境外购买 | | TTS | FishSpeech | 接口调用 | 免费/自定义 | 本地启动 TTS 服务;启动方法见配置文件内说明 | @@ -223,8 +228,10 @@ server: | 类型 | 平台名称 | 使用方式 | 收费模式 | 备注 | |:---:|:---------:|:----:|:----:|:--:| | ASR | FunASR | 本地使用 | 免费 | | +| ASR | SherpaASR | 本地使用 | 免费 | | | ASR | DoubaoASR | 接口调用 | 收费 | | + --- ### Memory 记忆存储 @@ -367,7 +374,41 @@ VAD: ### 6、我想通过小智控制电灯、空调、远程开关机等操作 💡 -建议:在配置文件中将 `LLM` 设置为 `HomeAssistant`,通过 调用`HomeAssistant`接口实现相关控制。 +本项目,支持以工具调用的方式控制HomeAssistant设备 + +1、首先选择一款支持function call支持的LLM,例如`ChatGLMLLM`。 + +2、在配置文件中,将 `selected_module.Intent` 设置为 `function_call`。 + +3、登录`HomeAssistant`,点击`左下角个人`,切换`安全`导航栏,划到底部`长期访问令牌`生成api_key。 + +在配置文件中,配置好你的home assistant的`devices`(被控制的设备)和`api_key`和`base_url`等信息。例如: + +``` yaml +plugins + home_assistant: + devices: + - 客厅,玩具灯,switch.cuco_cn_460494544_cp1_on_p_2_1 + - 卧室,台灯,switch.iot_cn_831898993_socn1_on_p_2_1 + base_url: http://你的homeassistant地址:8123 + api_key: 你的home assistant api访问令牌 +``` + +最后,允许function_call 插件在配置文件中启用`hass_get_state`(必须)、`hass_set_state`(必须)、`hass_play_music`(不想用ha听音乐可以不启动),例如: + +``` yaml +Intent: + ... + function_call: + type: nointent + functions: + - change_role + - get_weather + - get_news + - hass_get_state + - hass_set_state + - hass_play_music +``` ### 7、更多问题,可联系我们反馈 💬 diff --git a/README_en.md b/README_en.md index 8c251a44..88306675 100644 --- a/README_en.md +++ b/README_en.md @@ -165,6 +165,7 @@ In fact, any LLM that supports OpenAI API calls can be integrated. | Type | Platform Name | Usage Method | Pricing Model | Remarks | |:----:|:-------------------:|:------------:|:-------------:|:-------:| | ASR | FunASR | Local | Free | | +| ASR | SherpaASR | Local | Free | | | ASR | DoubaoASR | API call | Paid | | --- diff --git a/docs/images/demo0.png b/docs/images/demo0.png new file mode 100644 index 00000000..99592be6 Binary files /dev/null and b/docs/images/demo0.png differ diff --git a/docs/images/demo5.png b/docs/images/demo5.png index 8e03685b..c6da2997 100644 Binary files a/docs/images/demo5.png and b/docs/images/demo5.png differ diff --git a/main/manager-api/src/main/java/xiaozhi/common/aspect/DataFilterAspect.java b/main/manager-api/src/main/java/xiaozhi/common/aspect/DataFilterAspect.java deleted file mode 100644 index db75689d..00000000 --- a/main/manager-api/src/main/java/xiaozhi/common/aspect/DataFilterAspect.java +++ /dev/null @@ -1,99 +0,0 @@ -package xiaozhi.common.aspect; - -import cn.hutool.core.collection.CollUtil; -import xiaozhi.common.annotation.DataFilter; -import xiaozhi.common.constant.Constant; -import xiaozhi.common.exception.ErrorCode; -import xiaozhi.common.exception.RenException; -import xiaozhi.common.interceptor.DataScope; -import xiaozhi.common.user.UserDetail; -import xiaozhi.modules.security.user.SecurityUser; -import xiaozhi.modules.sys.enums.SuperAdminEnum; -import org.apache.commons.lang3.StringUtils; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; - -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; - -/** - * 数据过滤,切面处理类 - * Copyright (c) 人人开源 All rights reserved. - * Website: https://www.renren.io - */ -@Aspect -@Component -public class DataFilterAspect { - - @Pointcut("@annotation(xiaozhi.common.annotation.DataFilter)") - public void dataFilterCut() { - - } - - @Before("dataFilterCut()") - public void dataFilter(JoinPoint point) { - Object params = point.getArgs()[0]; - if (params != null && params instanceof Map) { - UserDetail user = SecurityUser.getUser(); - - //如果是超级管理员,则不进行数据过滤 - if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) { - return; - } - - try { - //否则进行数据过滤 - Map map = (Map) params; - String sqlFilter = getSqlFilter(user, point); - map.put(Constant.SQL_FILTER, new DataScope(sqlFilter)); - } catch (Exception e) { - - } - - return; - } - - throw new RenException(ErrorCode.DATA_SCOPE_PARAMS_ERROR); - } - - /** - * 获取数据过滤的SQL - */ - private String getSqlFilter(UserDetail user, JoinPoint point) throws Exception { - MethodSignature signature = (MethodSignature) point.getSignature(); - Method method = point.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes()); - DataFilter dataFilter = method.getAnnotation(DataFilter.class); - - //获取表的别名 - String tableAlias = dataFilter.tableAlias(); - if (StringUtils.isNotBlank(tableAlias)) { - tableAlias += "."; - } - - StringBuilder sqlFilter = new StringBuilder(); - sqlFilter.append(" ("); - - //部门ID列表 - List deptIdList = user.getDeptIdList(); - if (CollUtil.isNotEmpty(deptIdList)) { - sqlFilter.append(tableAlias).append(dataFilter.deptId()); - - sqlFilter.append(" in(").append(StringUtils.join(deptIdList, ",")).append(")"); - } - - //查询本人数据 - if (CollUtil.isNotEmpty(deptIdList)) { - sqlFilter.append(" or "); - } - sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getId()); - - sqlFilter.append(")"); - - return sqlFilter.toString(); - } -} \ No newline at end of file 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 10135cef..3738498b 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 @@ -73,10 +73,6 @@ public interface Constant { * 排序方式 */ String ORDER = "order"; - /** - * token header - */ - String TOKEN_HEADER = "token"; String AUTHORIZATION = "Authorization"; diff --git a/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java b/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java index fbb75322..20371fd6 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java +++ b/main/manager-api/src/main/java/xiaozhi/common/handler/FieldMetaObjectHandler.java @@ -34,9 +34,6 @@ public class FieldMetaObjectHandler implements MetaObjectHandler { //创建时间 strictInsertFill(metaObject, CREATE_DATE, Date.class, date); - //创建者所属部门 - strictInsertFill(metaObject, DEPT_ID, Long.class, user.getDeptId()); - //更新者 strictInsertFill(metaObject, UPDATER, Long.class, user.getId()); //更新时间 diff --git a/main/manager-api/src/main/java/xiaozhi/common/user/UserDetail.java b/main/manager-api/src/main/java/xiaozhi/common/user/UserDetail.java index 163982de..2ad023d7 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/user/UserDetail.java +++ b/main/manager-api/src/main/java/xiaozhi/common/user/UserDetail.java @@ -3,7 +3,6 @@ package xiaozhi.common.user; import lombok.Data; import java.io.Serializable; -import java.util.List; /** * 登录用户信息 @@ -14,19 +13,7 @@ import java.util.List; public class UserDetail implements Serializable { private Long id; private String username; - private String realName; - private String headUrl; - private Integer gender; - private String email; - private String mobile; - private Long deptId; - private String password; - private Integer status; private Integer superAdmin; private String token; - /** - * 部门数据权限 - */ - private List deptIdList; - + private Integer status; } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/common/utils/HttpContextUtils.java b/main/manager-api/src/main/java/xiaozhi/common/utils/HttpContextUtils.java index 3629d553..8d76434c 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/utils/HttpContextUtils.java +++ b/main/manager-api/src/main/java/xiaozhi/common/utils/HttpContextUtils.java @@ -1,6 +1,5 @@ package xiaozhi.common.utils; -import xiaozhi.common.constant.Constant; import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpHeaders; @@ -8,6 +7,8 @@ import org.springframework.util.DigestUtils; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import xiaozhi.common.exception.ErrorCode; +import xiaozhi.common.exception.RenException; import java.util.Date; import java.util.Enumeration; @@ -30,13 +31,14 @@ public class HttpContextUtils { return ((ServletRequestAttributes) requestAttributes).getRequest(); } - public static String getToken() { - HttpServletRequest httpRequest = getHttpServletRequest(); - String token = httpRequest.getHeader(Constant.TOKEN_HEADER); - - //如果header中不存在token,则从参数中获取token + public static String getToken(String authorization) { + String token; + if (StringUtils.isBlank(authorization) && authorization.contains("Bearer ")) { + throw new RenException(ErrorCode.UNAUTHORIZED); + } + token = authorization.replace("Bearer ", ""); if (StringUtils.isBlank(token)) { - token = httpRequest.getParameter(Constant.TOKEN_HEADER); + throw new RenException(ErrorCode.TOKEN_NOT_EMPTY); } return token; } diff --git a/main/manager-api/src/main/java/xiaozhi/common/utils/Result.java b/main/manager-api/src/main/java/xiaozhi/common/utils/Result.java index c21bdbf9..65841b7d 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/utils/Result.java +++ b/main/manager-api/src/main/java/xiaozhi/common/utils/Result.java @@ -1,16 +1,10 @@ package xiaozhi.common.utils; -import xiaozhi.common.exception.ErrorCode; -import xiaozhi.common.page.PageData; -import xiaozhi.modules.security.user.SecurityUser; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import org.apache.commons.lang3.StringUtils; +import xiaozhi.common.exception.ErrorCode; import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Set; /** * 响应数据 @@ -42,9 +36,6 @@ public class Result implements Serializable { return this; } - public boolean success() { - return code == 0; - } public Result error() { this.code = ErrorCode.INTERNAL_SERVER_ERROR; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java index 1974689c..d458e9f9 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java @@ -25,11 +25,10 @@ import xiaozhi.modules.security.user.SecurityUser; import java.util.List; import java.util.Map; +@Tag(name = "设备管理") @AllArgsConstructor @RestController @RequestMapping("/device") -@Tag(name = "设备管理") - public class DeviceController { private final DeviceService deviceService; private final RedisUtils redisUtils; 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 35cde8aa..de25d80e 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 @@ -70,7 +70,9 @@ public class ShiroConfig { filterMap.put("/v3/api-docs/**", "anon"); filterMap.put("/doc.html", "anon"); filterMap.put("/favicon.ico", "anon"); - filterMap.put("/user/**", "anon"); + filterMap.put("/user/captcha", "anon"); + filterMap.put("/user/login", "anon"); + filterMap.put("/user/register", "anon"); filterMap.put("/**", "oauth2"); shiroFilter.setFilterChainDefinitionMap(filterMap); 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 af3f451c..6ab9d1b9 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 @@ -4,20 +4,21 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.page.TokenDTO; +import xiaozhi.common.user.UserDetail; import xiaozhi.common.utils.Result; import xiaozhi.common.validator.AssertUtils; -import xiaozhi.modules.security.dao.SysUserTokenDao; import xiaozhi.modules.security.dto.LoginDTO; import xiaozhi.modules.security.password.PasswordUtils; import xiaozhi.modules.security.service.CaptchaService; import xiaozhi.modules.security.service.SysUserTokenService; +import xiaozhi.modules.security.user.SecurityUser; +import xiaozhi.modules.sys.dto.PasswordDTO; import xiaozhi.modules.sys.dto.SysUserDTO; import xiaozhi.modules.sys.service.SysUserService; @@ -26,7 +27,6 @@ import java.io.IOException; /** * 登录控制层 */ -@Tag(name = "登录管理") @AllArgsConstructor @RestController @RequestMapping("/user") @@ -36,7 +36,6 @@ public class LoginController { private final SysUserTokenService sysUserTokenService; private final CaptchaService captchaService; - private static final Logger logger = LoggerFactory.getLogger(LoginController.class); @GetMapping("/captcha") @Operation(summary = "验证码") @@ -79,32 +78,31 @@ public class LoginController { } // 按照用户名获取用户 SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername()); - if (userDTO != null){ + if (userDTO != null) { throw new RenException("此手机号码已经注册过"); } userDTO = new SysUserDTO(); userDTO.setUsername(login.getUsername()); userDTO.setPassword(login.getPassword()); sysUserService.save(userDTO); - return new Result(); + return new Result<>(); } @GetMapping("/info") @Operation(summary = "用户信息获取") - public Result info(@RequestHeader("Authorization")String authorization) { - logger.info("the authorization:{}", authorization); + public Result info() { + UserDetail user = SecurityUser.getUser(); + Result result = new Result<>(); + result.setData(user); + return result; + } - String token; - if (StringUtils.isBlank(authorization) && authorization.contains("Bearer ")) { - throw new RenException(ErrorCode.UNAUTHORIZED); - } - token = authorization.replace("Bearer ", ""); - if (StringUtils.isBlank(token)) { - throw new RenException(ErrorCode.UNAUTHORIZED); - } - SysUserDTO sysUserDTO = sysUserTokenService.getUserByToken(token); - Result result = new Result(); - return result.ok(sysUserDTO); + @PutMapping("/change-password") + @Operation(summary = "修改用户密码") + public Result changePassword(@RequestBody PasswordDTO passwordDTO) { + Long userId = SecurityUser.getUserId(); + sysUserTokenService.changePassword(userId, passwordDTO); + return new Result<>(); } } \ No newline at end of file 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 26486b7b..1520a850 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 @@ -11,7 +11,6 @@ import org.apache.shiro.web.filter.authc.AuthenticatingFilter; import org.springframework.web.bind.annotation.RequestMethod; import xiaozhi.common.constant.Constant; import xiaozhi.common.exception.ErrorCode; -import xiaozhi.common.exception.RenException; import xiaozhi.common.utils.HttpContextUtils; import xiaozhi.common.utils.JsonUtils; import xiaozhi.common.utils.Result; @@ -90,21 +89,10 @@ public class Oauth2Filter extends AuthenticatingFilter { * 获取请求的token */ private String getRequestToken(HttpServletRequest httpRequest) { - String token; + String token = null; //从header中获取token String authorization = httpRequest.getHeader(Constant.AUTHORIZATION); - if (StringUtils.isBlank(authorization) && authorization.contains("Bearer ")) { - throw new RenException(ErrorCode.UNAUTHORIZED); - } - token = authorization.replace("Bearer ", ""); - - //如果header中不存在token,则从参数中获取token - if (StringUtils.isBlank(token)) { - authorization = httpRequest.getParameter(Constant.AUTHORIZATION); - - if (StringUtils.isBlank(authorization) && authorization.contains("Bearer ")) { - throw new RenException(ErrorCode.UNAUTHORIZED); - } + if (StringUtils.isNotBlank(authorization) && authorization.startsWith("Bearer ")) { token = authorization.replace("Bearer ", ""); } return token; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java index 8c297e17..6b04bb08 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java @@ -14,12 +14,12 @@ import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.user.UserDetail; import xiaozhi.common.utils.ConvertUtils; import xiaozhi.common.utils.MessageUtils; -import xiaozhi.modules.security.controller.LoginController; import xiaozhi.modules.security.entity.SysUserTokenEntity; import xiaozhi.modules.security.service.ShiroService; import xiaozhi.modules.sys.entity.SysUserEntity; import xiaozhi.modules.sys.enums.SuperAdminEnum; +import java.util.HashSet; import java.util.Set; /** @@ -48,7 +48,7 @@ public class Oauth2Realm extends AuthorizingRealm { UserDetail user = (UserDetail) principals.getPrimaryPrincipal(); //用户权限列表 - Set permsSet = shiroService.getUserPermissions(user); + Set permsSet = new HashSet<>(); if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) { permsSet.add("sys:role:superAdmin"); @@ -82,8 +82,6 @@ public class Oauth2Realm extends AuthorizingRealm { //转换成UserDetail对象 UserDetail userDetail = ConvertUtils.sourceToTarget(userEntity, UserDetail.class); - //获取用户对应的部门数据权限 - userDetail.setDeptIdList(null); userDetail.setToken(accessToken); //账号锁定 diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java b/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java index 980645d6..b9d18889 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java @@ -1,22 +1,14 @@ package xiaozhi.modules.security.service; -import xiaozhi.common.user.UserDetail; import xiaozhi.modules.security.entity.SysUserTokenEntity; import xiaozhi.modules.sys.entity.SysUserEntity; -import java.util.List; -import java.util.Set; - /** * shiro相关接口 * Copyright (c) 人人开源 All rights reserved. * Website: https://www.renren.io */ public interface ShiroService { - /** - * 获取用户权限列表 - */ - Set getUserPermissions(UserDetail user); SysUserTokenEntity getByToken(String token); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/service/SysUserTokenService.java b/main/manager-api/src/main/java/xiaozhi/modules/security/service/SysUserTokenService.java index 74882dea..d1d094d4 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/service/SysUserTokenService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/service/SysUserTokenService.java @@ -1,14 +1,12 @@ package xiaozhi.modules.security.service; -import xiaozhi.common.page.PageData; import xiaozhi.common.page.TokenDTO; import xiaozhi.common.service.BaseService; import xiaozhi.common.utils.Result; import xiaozhi.modules.security.entity.SysUserTokenEntity; +import xiaozhi.modules.sys.dto.PasswordDTO; import xiaozhi.modules.sys.dto.SysUserDTO; -import java.util.Map; - /** * 用户Token * Copyright (c) 人人开源 All rights reserved. @@ -32,4 +30,12 @@ public interface SysUserTokenService extends BaseService { */ void logout(Long userId); + /** + * 修改密码 + * + * @param userId + * @param passwordDTO + */ + void changePassword(Long userId, PasswordDTO passwordDTO); + } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java index 128d9b9d..97d16eaa 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java @@ -19,22 +19,6 @@ public class ShiroServiceImpl implements ShiroService { private final SysUserDao sysUserDao; private final SysUserTokenDao sysUserTokenDao; - @Override - public Set getUserPermissions(UserDetail user) { - //系统管理员,拥有最高权限 - // TODO: 暂时写死,后续改成从数据库查询 - List permissionsList = new ArrayList<>(); - //用户权限列表 - Set permsSet = new HashSet<>(); - for (String permissions : permissionsList) { - if (StringUtils.isBlank(permissions)) { - continue; - } - permsSet.addAll(Arrays.asList(permissions.trim().split(","))); - } - - return permsSet; - } @Override public SysUserTokenEntity getByToken(String token) { diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/SysUserTokenServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/SysUserTokenServiceImpl.java index caa24801..40ee7957 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/SysUserTokenServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/SysUserTokenServiceImpl.java @@ -2,6 +2,7 @@ package xiaozhi.modules.security.service.impl; import cn.hutool.core.date.DateUtil; import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; import xiaozhi.common.page.TokenDTO; @@ -12,7 +13,7 @@ import xiaozhi.modules.security.dao.SysUserTokenDao; import xiaozhi.modules.security.entity.SysUserTokenEntity; import xiaozhi.modules.security.oauth2.TokenGenerator; import xiaozhi.modules.security.service.SysUserTokenService; -import org.springframework.stereotype.Service; +import xiaozhi.modules.sys.dto.PasswordDTO; import xiaozhi.modules.sys.dto.SysUserDTO; import xiaozhi.modules.sys.service.SysUserService; @@ -81,6 +82,9 @@ public class SysUserTokenServiceImpl extends BaseServiceImpl { void delete(Long[] ids); + void changePassword(Long userId, PasswordDTO passwordDTO); } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysUserServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysUserServiceImpl.java index 8f576137..17d1939c 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysUserServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysUserServiceImpl.java @@ -10,6 +10,7 @@ import xiaozhi.common.service.impl.BaseServiceImpl; import xiaozhi.common.utils.ConvertUtils; import xiaozhi.modules.security.password.PasswordUtils; import xiaozhi.modules.sys.dao.SysUserDao; +import xiaozhi.modules.sys.dto.PasswordDTO; import xiaozhi.modules.sys.dto.SysUserDTO; import xiaozhi.modules.sys.entity.SysUserEntity; import xiaozhi.modules.sys.enums.SuperAdminEnum; @@ -81,6 +82,31 @@ public class SysUserServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); return baseDao.selectCount(queryWrapper); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java new file mode 100644 index 00000000..dc6ccca7 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java @@ -0,0 +1,85 @@ +package xiaozhi.modules.timbre.controller; + +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.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.page.PageData; +import xiaozhi.common.utils.Result; +import xiaozhi.common.validator.ValidatorUtils; +import xiaozhi.modules.timbre.dto.TimbreDataDTO; +import xiaozhi.modules.timbre.dto.TimbrePageDTO; +import xiaozhi.modules.timbre.service.TimbreService; +import xiaozhi.modules.timbre.vo.TimbreDetailsVO; + +import java.util.Map; + +/** + * 音色控制层 + * + * @author zjy + * @since 2025-3-21 + */ +@AllArgsConstructor +@RestController +@RequestMapping("/ttsVoice") +@Tag(name = "音色管理") +public class TimbreController { + private final TimbreService timbreService; + + @GetMapping + @Operation(summary = "分页查找") + @RequiresPermissions("sys:role:superAdmin") + @Parameters({ + @Parameter(name = "ttsModelId", description = "对应 TTS 模型主键", required = true), + @Parameter(name = "name", description = "音色名称"), + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true), + }) + public Result> page( + @Parameter(hidden = true) @RequestParam Map params) { + TimbrePageDTO dto = new TimbrePageDTO(); + dto.setTtsModelId((String) params.get("ttsModelId")); + dto.setName((String) params.get("name")); + dto.setLimit((String) params.get(Constant.LIMIT)); + dto.setPage((String) params.get(Constant.PAGE)); + + ValidatorUtils.validateEntity(dto); + PageData page = timbreService.page(dto); + return new Result>().ok(page); + } + + @PostMapping + @Operation(summary = "音色保存") + @RequiresPermissions("sys:role:superAdmin") + public Result save(@RequestBody TimbreDataDTO dto) { + ValidatorUtils.validateEntity(dto); + timbreService.save(dto); + return new Result<>(); + } + + @PutMapping("/{id}") + @Operation(summary = "音色修改") + @RequiresPermissions("sys:role:superAdmin") + public Result update( + @PathVariable Long id, + @RequestBody TimbreDataDTO dto) { + ValidatorUtils.validateEntity(dto); + timbreService.update(id, dto); + return new Result<>(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "音色删除") + @RequiresPermissions("sys:role:superAdmin") + public Result delete(@PathVariable Long id) { + timbreService.delete(new Long[]{id}); + return new Result<>(); + } + + +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dao/TimbreDao.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dao/TimbreDao.java new file mode 100644 index 00000000..62afa358 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dao/TimbreDao.java @@ -0,0 +1,14 @@ +package xiaozhi.modules.timbre.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import xiaozhi.modules.timbre.entity.TimbreEntity; + +/** + * 音色持久层定义 + * @author zjy + * @since 2025-3-21 + */ +@Mapper +public interface TimbreDao extends BaseMapper { +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java new file mode 100644 index 00000000..08ed9b18 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java @@ -0,0 +1,45 @@ +package xiaozhi.modules.timbre.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + + +/** + * 音色表数据DTO + * @author zjy + * @since 2025-3-21 + */ +@Data +@Schema(description = "音色表信息") +public class TimbreDataDTO { + + @Schema(description = "语言") + @NotBlank(message = "{timbre.languages.require}") + private String languages; + + @Schema(description = "音色名称") + @NotBlank(message = "{timbre.name.require}") + private String name; + + @Schema(description = "备注") + @NotBlank(message = "{timbre.remark.require}") + private String remark; + + @Schema(description = "排序") + @Min(value = 0, message = "{sort.number}") + private long sort; + + @Schema(description = "对应 TTS 模型主键") + @NotBlank(message = "{timbre.ttsModelId.require}") + private String ttsModelId; + + @Schema(description = "音色编码") + @NotBlank(message = "{timbre.ttsVoice.require}") + private String ttsVoice; + + @Schema(description = "音频播放地址") + @NotBlank(message = "{timbre.voiceDemo.require}") + private String voiceDemo; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbrePageDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbrePageDTO.java new file mode 100644 index 00000000..72ed68b1 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbrePageDTO.java @@ -0,0 +1,28 @@ +package xiaozhi.modules.timbre.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 音色分页参数DTO + * @author zjy + * @since 2025-3-21 + */ +@Data +@Schema(description = "音色分页参数") +public class TimbrePageDTO { + + @Schema(description = "对应 TTS 模型主键") + @NotBlank(message = "{timbre.ttsModelId.require}") + private String ttsModelId; + + @Schema(description = "音色名称") + private String name; + + @Schema(description = "页数") + private String page; + + @Schema(description = "显示列数") + private String limit; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java new file mode 100644 index 00000000..71bd58a9 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java @@ -0,0 +1,48 @@ +package xiaozhi.modules.timbre.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import xiaozhi.common.entity.BaseEntity; + +import java.util.Date; + +/** + * 音色表实体类 + * @author zjy + * @since 2025-3-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("ai_tts_voice") +@Schema(description = "音色信息") +public class TimbreEntity extends BaseEntity { + + @Schema(description = "语言") + private String languages; + + @Schema(description = "音色名称") + private String name; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + private long sort; + + @Schema(description = "对应 TTS 模型主键") + private String ttsModelId; + + @Schema(description = "音色编码") + private String ttsVoice; + + @Schema(description = "音频播放地址") + private String voiceDemo; + + @Schema(description = "更新者") + private Long updater; + + @Schema(description = "更新时间") + private Date updateDate; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/TimbreService.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/TimbreService.java new file mode 100644 index 00000000..9b6c73eb --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/TimbreService.java @@ -0,0 +1,49 @@ +package xiaozhi.modules.timbre.service; + +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.BaseService; +import xiaozhi.modules.timbre.dto.TimbreDataDTO; +import xiaozhi.modules.timbre.dto.TimbrePageDTO; +import xiaozhi.modules.timbre.entity.TimbreEntity; +import xiaozhi.modules.timbre.vo.TimbreDetailsVO; + + +/** + * 音色的业务层的定义 + * @author zjy + * @since 2025-3-21 + */ +public interface TimbreService extends BaseService { + /** + * 分页获取音色指定tts的下的音色 + * @param dto 分页查找参数 + * @return 音色列表分页数据 + */ + PageData page(TimbrePageDTO dto); + + /** + * 获取音色指定id的详情信息 + * @param timbreId 音色表id + * @return 音色信息 + */ + TimbreDetailsVO get(Long timbreId); + + /** + * 保存音色信息 + * @param dto 需要保存数据 + */ + void save(TimbreDataDTO dto); + + /** + * 保存音色信息 + * @param timbreId 需要修改的id + * @param dto 需要修改的数据 + */ + void update(Long timbreId,TimbreDataDTO dto); + + /** + * 批量删除音色 + * @param ids 需要被删除的音色id列表 + */ + void delete(Long[] ids); +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java new file mode 100644 index 00000000..ce3c2b7b --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java @@ -0,0 +1,85 @@ +package xiaozhi.modules.timbre.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.impl.BaseServiceImpl; +import xiaozhi.common.utils.ConvertUtils; +import xiaozhi.modules.timbre.dao.TimbreDao; +import xiaozhi.modules.timbre.dto.TimbreDataDTO; +import xiaozhi.modules.timbre.dto.TimbrePageDTO; +import xiaozhi.modules.timbre.service.TimbreService; +import xiaozhi.modules.timbre.entity.TimbreEntity; +import xiaozhi.modules.timbre.vo.TimbreDetailsVO; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * 音色的业务层的实现 + * @author zjy + * @since 2025-3-21 + */ +@Service +public class TimbreServiceImpl extends BaseServiceImpl implements TimbreService { + + + @Override + public PageData page(TimbrePageDTO dto) { + Map params = new HashMap(); + params.put(Constant.PAGE, dto.getPage()); + params.put(Constant.LIMIT,dto.getLimit()); + IPage page = baseDao.selectPage( + getPage(params, "sort", true), + //定义查询条件 + new QueryWrapper() + //必须按照ttsID查找 + .eq("tts_model_id",dto.getTtsModelId()) + //如果有音色名字,按照音色名模糊查找 + .like(StringUtils.isNotBlank(dto.getName()),"name",dto.getName()) + ); + + return getPageData(page, TimbreDetailsVO.class); + } + + @Override + public TimbreDetailsVO get(Long timbreId) { + TimbreEntity entity = baseDao.selectById(timbreId); + return ConvertUtils.sourceToTarget(entity, TimbreDetailsVO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(TimbreDataDTO dto) { + isTtsModelId(dto.getTtsModelId()); + TimbreEntity timbreEntity = ConvertUtils.sourceToTarget(dto, TimbreEntity.class); + baseDao.insert(timbreEntity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Long timbreId, TimbreDataDTO dto) { + isTtsModelId(dto.getTtsModelId()); + TimbreEntity timbreEntity = ConvertUtils.sourceToTarget(dto, TimbreEntity.class); + timbreEntity.setId(timbreId); + baseDao.updateById(timbreEntity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long[] ids) { + baseDao.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 处理是不是tts模型的id + */ + private void isTtsModelId(String ttsModelId){ + //等模型配置那边写好调用方法判断 + } +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java new file mode 100644 index 00000000..fc82a5d0 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java @@ -0,0 +1,39 @@ +package xiaozhi.modules.timbre.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 音色详情展示VO + * @author zjy + * @since 2025-3-21 + */ +@Data +public class TimbreDetailsVO implements Serializable { + @Schema(description = "音色id") + private Long id; + + @Schema(description = "语言") + private String languages; + + @Schema(description = "音色名称") + private String name; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + private long sort; + + @Schema(description = "对应 TTS 模型主键") + private String ttsModelId; + + @Schema(description = "音色编码") + private String ttsVoice; + + @Schema(description = "音频播放地址") + private String voiceDemo; + +} diff --git a/main/manager-api/src/main/resources/i18n/validation.properties b/main/manager-api/src/main/resources/i18n/validation.properties index 947f89cc..e7452e47 100644 --- a/main/manager-api/src/main/resources/i18n/validation.properties +++ b/main/manager-api/src/main/resources/i18n/validation.properties @@ -20,3 +20,12 @@ sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A + + +timbre.languages.require=\u97F3\u8272\u7684\u8BED\u8A00\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.name.require=\u97F3\u8272\u7684\u540D\u79F0\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.remark.require=\u97F3\u8272\u7684\u5907\u6CE8\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u952E\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsVoice.require=\u97F3\u8272\u7684\u7F16\u7801\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653EDemo\u4E0D\u53EF\u4EE5\u4E3A\u7A7A + diff --git a/main/manager-api/src/main/resources/i18n/validation_en_US.properties b/main/manager-api/src/main/resources/i18n/validation_en_US.properties index f8bb6e94..37bebf18 100644 --- a/main/manager-api/src/main/resources/i18n/validation_en_US.properties +++ b/main/manager-api/src/main/resources/i18n/validation_en_US.properties @@ -20,3 +20,11 @@ sysuser.deptId.require=Departments cannot be empty sysuser.status.range=State ranges from 0 to 1 sysuser.captcha.require=The captcha cannot be empty sysuser.uuid.require=The unique identifier cannot be empty + +timbre.languages.require=The language of the timbre cannot be empty +timbre.name.require=The name of the timbre cannot be empty +timbre.remark.require=The remark of the timbre cannot be empty +timbre.ttsModelId.require=The TTS model ID of the timbre cannot be empty +timbre.ttsVoice.require=The TTS voice of the timbre cannot be empty +timbre.voiceDemo.require=The voice demo of the timbre cannot be empty + diff --git a/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties b/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties index ba350d05..41bf1e69 100644 --- a/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties +++ b/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties @@ -21,3 +21,10 @@ sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A +timbre.languages.require=\u97F3\u8272\u7684\u8A9E\u8A00\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.name.require=\u97F3\u8272\u7684\u540D\u7A31\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.remark.require=\u97F3\u8272\u7684\u5099\u6CE8\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u9375\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.ttsVoice.require=\u97F3\u8272\u7684\u7DE8\u78BC\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653E\u5730\u5740\u4E0D\u53EF\u4EE5\u70BA\u7A7A + diff --git a/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties b/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties index 947f89cc..9241c97a 100644 --- a/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties +++ b/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties @@ -20,3 +20,10 @@ sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A + +timbre.languages.require=\u97F3\u8272\u7684\u8BED\u8A00\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.name.require=\u97F3\u8272\u7684\u540D\u79F0\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.remark.require=\u97F3\u8272\u7684\u5907\u6CE8\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u952E\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsVoice.require=\u97F3\u8272\u7684\u7F16\u7801\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653EDemo\u4E0D\u53EF\u4EE5\u4E3A\u7A7A diff --git a/main/manager-web/src/apis/module/user.js b/main/manager-web/src/apis/module/user.js index 444d5d76..bf3eea34 100755 --- a/main/manager-web/src/apis/module/user.js +++ b/main/manager-web/src/apis/module/user.js @@ -18,20 +18,6 @@ export default { }) }).send() }, - // 获取用户信息 - getUserInfo(callback) { - RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/info`) - .method('GET') - .success((res) => { - RequestService.clearRequestTime() - callback(res) - }) - .fail(() => { - RequestService.reAjaxFun(() => { - this.getUserInfo() - }) - }).send() - }, // 获取设备信息 getHomeList(callback) { RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/device/bind`) @@ -173,5 +159,52 @@ export default { }); }).send(); }, + // 获取智能体列表 + getAgentList(callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/api/v1/user/agent`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .fail(() => { + RequestService.reAjaxFun(() => { + this.getAgentList(callback); + }); + }).send(); + }, + + getUserInfo(callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/api/v1/user/info`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime() + callback(res) + }) + .fail((err) => { + console.error('接口请求失败:', err) + RequestService.reAjaxFun(() => { + this.getUserInfo(callback) + }) + }).send() + }, + // 添加智能体 + addAgent(agentName, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/api/v1/user/agent`) + .method('POST') + .data({ name: agentName }) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .fail(() => { + RequestService.reAjaxFun(() => { + this.addAgent(agentName, callback); + }); + }).send(); + }, } diff --git a/main/manager-web/src/components/AddDeviceDialog.vue b/main/manager-web/src/components/AddDeviceDialog.vue index a9eec57c..e7ba492e 100644 --- a/main/manager-web/src/components/AddDeviceDialog.vue +++ b/main/manager-web/src/components/AddDeviceDialog.vue @@ -1,21 +1,22 @@