From 19fe2d2f03e5b77799af6b4e1a091997d2f9f243 Mon Sep 17 00:00:00 2001 From: c1pher-cn Date: Tue, 18 Mar 2025 20:42:09 +0800 Subject: [PATCH 01/28] =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E7=AB=AF=E6=94=AF?= =?UTF-8?q?=E6=8C=81function=E7=9A=84=E5=BD=A2=E5=BC=8F=E8=B0=83=E7=94=A8h?= =?UTF-8?q?omeassistant=E6=8E=A7=E5=88=B6=E6=99=BA=E8=83=BD=E8=AE=BE?= =?UTF-8?q?=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- main/xiaozhi-server/config.yaml | 14 +- .../core/handle/functionHandler.py | 4 +- .../plugins_func/functions/hass_get_state.py | 70 +++++++ .../plugins_func/functions/hass_play_music.py | 85 +++++++++ .../plugins_func/functions/hass_set_state.py | 173 ++++++++++++++++++ 6 files changed, 346 insertions(+), 4 deletions(-) create mode 100644 main/xiaozhi-server/plugins_func/functions/hass_get_state.py create mode 100644 main/xiaozhi-server/plugins_func/functions/hass_play_music.py create mode 100644 main/xiaozhi-server/plugins_func/functions/hass_set_state.py diff --git a/README.md b/README.md index 121dfbe6..e00e7345 100644 --- a/README.md +++ b/README.md @@ -352,7 +352,9 @@ VAD: ### 6、我想通过小智控制电灯、空调、远程开关机等操作 💡 -建议:在配置文件中将 `LLM` 设置为 `HomeAssistant`,通过 调用`HomeAssistant`接口实现相关控制。 +方法1:在配置文件中将 `LLM` 设置为 `HomeAssistant`,通过 调用`HomeAssistant`接口实现相关控制。 + +方法2:以工具调用的方式控制HomeAssistant设备,LLM中配置HomeAssistant的api_key、base_url,不选择HomeAssistant做LLM,但必须配置一款支持tool调用的LLM,最后在提示词prompt里以示例的格式设置需要控制的设备,音乐播放需要在homeassistant中对接好musicassistant,同时音乐有削刮出媒体信息,对应的媒体播放器配置在设备列表中即可。 ### 7、更多问题,可联系我们反馈 💬 diff --git a/main/xiaozhi-server/config.yaml b/main/xiaozhi-server/config.yaml index 21f37c5b..e9ce5e17 100644 --- a/main/xiaozhi-server/config.yaml +++ b/main/xiaozhi-server/config.yaml @@ -53,6 +53,14 @@ prompt: | 请注意,要像一个人一样说话,请不要回复表情符号、代码、和xml标签。 现在我正在和你进行语音聊天,我们开始吧。 如果用户希望结束对话,请在最后说“拜拜”或“再见”。 + #-- hass 相关function的配置格式 请将你家需要控制的设备以下列格式追加在prompt里-- + # 下面是我家智能设备,可以通过homeassistant控制 + # 房间,设备别名,设备id + # 书房,吸顶灯,light.649e3159aa36_light + # 书房,homepod,media_player.shu_fang + # 书房,灯带,light.plug_158df955a6167a + # 书房,窗帘,cover.curtain_158d000710f507 + # 使用完声音文件后删除文件(Delete the sound file when you are done using it) delete_audio: true @@ -101,6 +109,10 @@ Intent: functions: - change_role - get_weather + - play_music + #- hass_play_music + #- hass_get_state + #- hass_set_state # 插件的基础配置 plugins: @@ -469,4 +481,4 @@ manager: enabled: false ip: 0.0.0.0 port: 8002 -use_private_config: false \ No newline at end of file +use_private_config: false diff --git a/main/xiaozhi-server/core/handle/functionHandler.py b/main/xiaozhi-server/core/handle/functionHandler.py index 8d54fe8a..36ac22f8 100644 --- a/main/xiaozhi-server/core/handle/functionHandler.py +++ b/main/xiaozhi-server/core/handle/functionHandler.py @@ -47,7 +47,7 @@ class FunctionHandler: def register_nessary_functions(self): """注册必要的函数""" self.function_registry.register_function("handle_exit_intent") - self.function_registry.register_function("play_music") + #self.function_registry.register_function("play_music") self.function_registry.register_function("plugin_loader") self.function_registry.register_function("get_time") @@ -80,4 +80,4 @@ class FunctionHandler: except Exception as e: logger.bind(tag=TAG).error(f"处理function call错误: {e}") - return None \ No newline at end of file + return None diff --git a/main/xiaozhi-server/plugins_func/functions/hass_get_state.py b/main/xiaozhi-server/plugins_func/functions/hass_get_state.py new file mode 100644 index 00000000..34634622 --- /dev/null +++ b/main/xiaozhi-server/plugins_func/functions/hass_get_state.py @@ -0,0 +1,70 @@ +from plugins_func.register import register_function,ToolType, ActionResponse, Action +from config.logger import setup_logging +import asyncio +import requests + +TAG = __name__ +logger = setup_logging() + +HASS_CACHE = {} + +hass_get_state_function_desc ={ + "type": "function", + "function": { + "name": "hass_get_state", + "description": "获取homeassistant里设备的状态,包括灯光亮度,媒体播放器的音量,设备的暂停、继续操作", + "parameters": { + "type": "object", + "properties": { + "entity_id": { + "type": "string", + "description": "需要操作的设备id,homeassistant里的entity_id" + } + }, + "required": ["entity_id"] + } + } + } + + + +@register_function("hass_get_state", hass_get_state_function_desc, ToolType.SYSTEM_CTL) +def hass_get_state(conn, entity_id=''): + try: + + future = asyncio.run_coroutine_threadsafe( + handle_hass_get_state(conn, entity_id), + conn.loop + ) + ha_response = future.result() + return ActionResponse(action=Action.REQLLM, result="执行成功", response=ha_response) + except Exception as e: + logger.bind(tag=TAG).error(f"处理设置属性意图错误: {e}") +def initialize_hass_handler(conn): + config = conn.config + global HASS_CACHE + if HASS_CACHE == {}: + logger.bind(tag=TAG).info(f"实例化HASS:") + if "HomeAssistant" in config["LLM"]: + HASS_CACHE['base_url'] = config["LLM"]['HomeAssistant']['base_url'] + HASS_CACHE['api_key'] = config["LLM"]['HomeAssistant']['api_key'] + else: + logger.bind(tag=TAG).error(f"使用前请在config文件中配置: LLM.HomeAssistant.base_url LLM.HomeAssistant.api_key") +async def handle_hass_get_state(conn, entity_id): + initialize_hass_handler(conn) + global HASS_CACHE + api_key = HASS_CACHE['api_key'] + base_url = HASS_CACHE['base_url'] + url = f"{base_url}/api/states/{entity_id}" + headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json" + } + response = requests.get(url, headers=headers) + #logger.bind(tag=TAG).info(f"获取状态: url:{url},return_code:{response.status_code},{response.json()}") + if response.status_code == 200: + return response.json()['state'] + #return response.json()['attributes'] + #response.attributes + else: + return f"切换失败,错误码: {response.status_code}" diff --git a/main/xiaozhi-server/plugins_func/functions/hass_play_music.py b/main/xiaozhi-server/plugins_func/functions/hass_play_music.py new file mode 100644 index 00000000..1a4fe74f --- /dev/null +++ b/main/xiaozhi-server/plugins_func/functions/hass_play_music.py @@ -0,0 +1,85 @@ +from plugins_func.register import register_function,ToolType, ActionResponse, Action +from config.logger import setup_logging +import asyncio +import requests + +TAG = __name__ +logger = setup_logging() + +HASS_CACHE = {} + +hass_play_music_function_desc = { + "type": "function", + "function": { + "name": "hass_play_music", + "description": "用户想听音乐、有声书的时候使用,在房间的媒体播放器(media_player)里播放对应音频", + "parameters": { + "type": "object", + "properties": { + "media_content_id": { + "type": "string", + "description": "可以是音乐或有声书的专辑名称、歌曲名、演唱者,如果未指定就填random" + }, + "entity_id": { + "type": "string", + "description": "需要操作的音箱的设备id,homeassistant里的entity_id,media_player开头" + } + }, + "required": ["media_content_id", "entity_id"] + } + } + } + + +@register_function('hass_play_music', hass_play_music_function_desc, ToolType.SYSTEM_CTL) + +def hass_play_music(conn, entity_id='', media_content_id='random'): + try: + #logger.bind(tag=TAG).error(f"arguments: {arguments}") + + #entity_id = arguments["entity_id"] + #media_content_id = arguments["media_content_id"] + + #logger.bind(tag=TAG).error(f"entity_id: {entity_id}") + + + # 执行音乐播放命令 + future = asyncio.run_coroutine_threadsafe( + handle_hass_play_music(conn, entity_id, media_content_id), + conn.loop + ) + ha_response = future.result() + return ActionResponse(action=Action.RESPONSE, result="退出意图已处理", response=ha_response) + except Exception as e: + logger.bind(tag=TAG).error(f"处理音乐意图错误: {e}") + +def initialize_hass_handler(conn): + config = conn.config + global HASS_CACHE + if HASS_CACHE == {}: + logger.bind(tag=TAG).info(f"实例化HASS:") + if "HomeAssistant" in config["LLM"]: + HASS_CACHE['base_url'] = config["LLM"]['HomeAssistant']['base_url'] + HASS_CACHE['api_key'] = config["LLM"]['HomeAssistant']['api_key'] + else: + logger.bind(tag=TAG).error(f"使用前请在config文件中配置: LLM.HomeAssistant.base_url LLM.HomeAssistant.api_key") + +async def handle_hass_play_music( conn, entity_id, media_content_id): + initialize_hass_handler(conn) + global HASS_CACHE + api_key = HASS_CACHE['api_key'] + base_url = HASS_CACHE['base_url'] + url = f"{base_url}/api/services/music_assistant/play_media" + headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json" + } + data = { + "entity_id": entity_id, + "media_id": media_content_id + } + response = requests.post(url, headers=headers, json=data) + if response.status_code == 200: + return f"正在播放{media_content_id}的音乐" + else: + return f"音乐播放失败,错误码: {response.status_code}" diff --git a/main/xiaozhi-server/plugins_func/functions/hass_set_state.py b/main/xiaozhi-server/plugins_func/functions/hass_set_state.py new file mode 100644 index 00000000..da5d1a28 --- /dev/null +++ b/main/xiaozhi-server/plugins_func/functions/hass_set_state.py @@ -0,0 +1,173 @@ +from plugins_func.register import register_function,ToolType, ActionResponse, Action +from config.logger import setup_logging +import asyncio +import requests +TAG = __name__ +logger = setup_logging() + +HASS_CACHE = {} + +hass_set_state_function_desc ={ + "type": "function", + "function": { + "name": "hass_set_state", + "description": "设置homeassistant里设备的状态,包括开、关,调整灯光亮度,调整播放器的音量,设备的暂停、继续、静音操作", + "parameters": { + "type": "object", + "properties": { + "state": { + "type": "object", + "properties": { + "type":{ + "type":"string", + "description":"需要操作的动作,打开设备:turn_on,关闭设备:turn_off,增加亮度:brightness_up,降低亮度:brightness_down,设置亮度:brightness_value,增加>音量:,volume_up降低音量:volume_down,设置音量:volume_set,设备暂停:pause,设备继续:continue,静音/取消静音:volume_mute" + }, + "input":{ + "type":"int", + "description": "只有在设置音量,设置亮度时候才需要,有效值为1-100,对应音量和亮度的1%-100%" + }, + "is_muted":{ + "type":"string", + "description": "只有在设置静音操作时才需要,设置静音的时候该值为true,取消静音时该值为false" + } + }, + "required": ["type"] + }, + "entity_id": { + "type": "string", + "description": "需要操作的设备id,homeassistant里的entity_id" + } + }, + "required": ["state", "entity_id"] + } + } + } + + + +@register_function('hass_set_state', hass_set_state_function_desc, ToolType.SYSTEM_CTL) +def hass_set_state(conn, entity_id='', state={}): + try: + + future = asyncio.run_coroutine_threadsafe( + handle_hass_set_state(conn, entity_id, state), + conn.loop + ) + ha_response = future.result() + return ActionResponse(action=Action.REQLLM, result="执行成功", response=ha_response) + except Exception as e: + logger.bind(tag=TAG).error(f"处理设置属性意图错误: {e}") +def initialize_hass_handler(conn): + config = conn.config + global HASS_CACHE + if HASS_CACHE == {}: + logger.bind(tag=TAG).info(f"实例化HASS:") + if "HomeAssistant" in config["LLM"]: + HASS_CACHE['base_url'] = config["LLM"]['HomeAssistant']['base_url'] + HASS_CACHE['api_key'] = config["LLM"]['HomeAssistant']['api_key'] + else: + logger.bind(tag=TAG).error(f"使用前请在config文件中配置: LLM.HomeAssistant.base_url LLM.HomeAssistant.api_key") + +async def handle_hass_set_state(conn, entity_id, state): + initialize_hass_handler(conn) + global HASS_CACHE + api_key = HASS_CACHE['api_key'] + base_url = HASS_CACHE['base_url'] + ''' + state = { "type":"brightness_up","input":"80","is_muted":"true"} + ''' + domains = entity_id.split(".") + if len(domains) > 1: + domain = domains[0] + else: + return "执行失败,错误的设备id" + action = '' + arg = '' + value = '' + if state['type'] == 'turn_on': + description = "设备已打开" + if domain == "cover": + action = "open_cover" + elif domain == "vacuum": + action = "start" + else: + action = "turn_on" + action = 'turn_on' + elif state['type'] == 'turn_off': + description = "设备已关闭" + if domain == 'cover': + action = "close_cover" + elif domain == 'vacuum': + action = "stop" + else: + action = "turn_off" + elif state['type'] == 'brightness_up': + description = "灯光已调亮" + action = 'turn_on' + arg = 'brightness_step_pct' + value = 10 + elif state['type'] == 'brightness_down': + description = "灯光已调暗" + action = 'turn_on' + arg = 'brightness_step_pct' + value = -10 + elif state['type'] == 'brightness_value': + description = f"亮度已调整到{state['input']}" + action = 'turn_on' + arg = 'brightness_pct' + value = state['input'] + elif state['type'] == 'volume_up': + description = "音量已调大" + action = state['type'] + elif state['type'] == 'volume_down': + description = "音量已调小" + action = state['type'] + elif state['type'] == 'volume_set': + description = f"音量已调整到{state['input']}" + action = state['type'] + arg = 'volume_level' + value = state['input'] + elif state['type'] == 'volume_mute': + description = f"设备已静音" + action = state['type'] + arg = 'is_volume_muted' + value = state['is_muted'] + elif state['type'] == 'pause': + description = f"设备已暂停" + action = state['type'] + if domain == 'media_player': + action = 'media_pause' + if domain == 'cover': + action = 'stop_cover' + if domain == 'vacuum': + action = 'pause' + elif state['type'] == 'continue': + description = f"设备已继续" + if domain == 'media_player': + action = 'media_play' + if domain == 'vacuum': + action = 'start' + else: + return f"{domain} {state.type}功能尚未支持" + + if arg == '': + data = { + "entity_id": entity_id, + } + else: + data = { + "entity_id": entity_id, + arg: value + } + url = f"{base_url}/api/services/{domain}/{action}" + headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json" + } + response = requests.post(url, headers=headers, json=data) + logger.bind(tag=TAG).info(f"设置状态:url:{url},return_code:{response.status_code}") + if response.status_code == 200: + return description + else: + return f"设置失败,错误码: {response.status_code}" + From 3ea1a2bf2f11c45a5f4624ae882eed12abd90a0b Mon Sep 17 00:00:00 2001 From: CGD <3030332422@qq.com> Date: Thu, 20 Mar 2025 14:08:38 +0800 Subject: [PATCH 02/28] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/manager-web/src/components/HeaderBar.vue | 37 ++---- main/manager-web/src/router/index.js | 10 +- .../src/views/DeviceManagement.vue | 12 +- main/manager-web/src/views/UserManagement.vue | 120 ++++++++++++++++++ 4 files changed, 147 insertions(+), 32 deletions(-) create mode 100644 main/manager-web/src/views/UserManagement.vue diff --git a/main/manager-web/src/components/HeaderBar.vue b/main/manager-web/src/components/HeaderBar.vue index acc0e981..7f8618dd 100644 --- a/main/manager-web/src/components/HeaderBar.vue +++ b/main/manager-web/src/components/HeaderBar.vue @@ -8,13 +8,11 @@ 智能体管理 -
- - 控制台 +
+ 用户管理
- 设备管理 - + 模型配置
@@ -55,6 +53,9 @@ export default { // 跳转到首页 this.$router.push('/') }, + goUserManagement() { + this.$router.push('/user-management') + }, // 获取用户信息 fetchUserInfo() { userApi.getUserInfo(({data}) => { @@ -108,17 +109,17 @@ export default { } .equipment-management2 { - width: 87px; - height: 22px; - border-radius: 11px; + width: 82px; + height: 24px; + border-radius: 12px; background: #fff; display: flex; justify-content: center; - font-size: 9px; - font-weight: 400; + font-size: 10px; + font-weight: 500; gap: 7px; color: #3d4566; - margin-left: 2px; + margin-left: 1px; align-items: center; } @@ -158,18 +159,4 @@ export default { text-align: left; color: #3d4566; } -.console { - width: 90px; - height: 22px; - border-radius: 11px; - background: radial-gradient(50% 50% at 50% 50%, #fff 0%, #e8f0ff 100%); - display: flex; - align-items: center; - justify-content: center; - font-size: 9px; - color: #979db1; - font-weight: 400; - gap: 7px; - margin-left: 15px; -} \ No newline at end of file diff --git a/main/manager-web/src/router/index.js b/main/manager-web/src/router/index.js index d3add00a..05c74054 100644 --- a/main/manager-web/src/router/index.js +++ b/main/manager-web/src/router/index.js @@ -39,13 +39,21 @@ const routes = [ return import('../views/register.vue') } }, - // 新增设备管理页面路由 + // 设备管理页面路由 { path: '/device-management', name: 'DeviceManagement', component: function () { return import('../views/DeviceManagement.vue') } + }, + // 添加用户管理路由 + { + path: '/user-management', + name: 'UserManagement', + component: function () { + return import('../views/UserManagement.vue') + } } ] diff --git a/main/manager-web/src/views/DeviceManagement.vue b/main/manager-web/src/views/DeviceManagement.vue index 06c4317c..03939a28 100644 --- a/main/manager-web/src/views/DeviceManagement.vue +++ b/main/manager-web/src/views/DeviceManagement.vue @@ -9,11 +9,11 @@ - - - - - + + + + + From 8bb0cf02ad2340d3de9631f88ef6b627ab1957c6 Mon Sep 17 00:00:00 2001 From: Huang <32005838+openrz@users.noreply.github.com> Date: Fri, 21 Mar 2025 21:08:50 +0800 Subject: [PATCH 11/28] =?UTF-8?q?update:=E9=85=8D=E7=BD=AE=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=BB=9F=E4=B8=80=E5=B0=8F=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py b/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py index 074d8f8d..ec0fb939 100644 --- a/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py +++ b/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py @@ -12,7 +12,7 @@ class LLMProvider(LLMProviderBase): self.app_id = config["app_id"] self.base_url = config.get("base_url") self.is_No_prompt = config.get("is_No_prompt") - self.memory_id = config.get("Ali_memory_id") + self.memory_id = config.get("ali_memory_id") def response(self, session_id, dialogue): try: @@ -49,4 +49,4 @@ class LLMProvider(LLMProviderBase): except Exception as e: logger.bind(tag=TAG).error(f"【阿里百练API服务】响应异常: {e}") - yield "【LLM服务响应异常】" \ No newline at end of file + yield "【LLM服务响应异常】" From 8e605dd1d4cfb8e74ee8f82ab2d0f9d6b93fd5f0 Mon Sep 17 00:00:00 2001 From: Huang <32005838+openrz@users.noreply.github.com> Date: Fri, 21 Mar 2025 21:09:32 +0800 Subject: [PATCH 12/28] =?UTF-8?q?update:=E9=85=8D=E7=BD=AE=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=BB=9F=E4=B8=80=E5=B0=8F=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/xiaozhi-server/config.yaml b/main/xiaozhi-server/config.yaml index 75426572..ac62f988 100644 --- a/main/xiaozhi-server/config.yaml +++ b/main/xiaozhi-server/config.yaml @@ -173,10 +173,10 @@ LLM: # 可在这里找到你的 api_key https://bailian.console.aliyun.com/?apiKey=1#/api-key api_key: 你的api_key # 是否不使用本地prompt:true|false (默不用请在百练应用中设置prompt) - is_No_prompt: true + is_no_prompt: true # Ali_memory_id:false(不使用)|你的memory_id(请在百练应用中设置中获取) # Tips!:Ali_memory未实现多用户存储记忆(记忆按id调用) - Ali_memory_id: false + ali_memory_id: false DoubaoLLM: # 定义LLM API类型 type: openai From 69630c2be044500c2af35d6ee7bf93ad671f5706 Mon Sep 17 00:00:00 2001 From: Huang <32005838+openrz@users.noreply.github.com> Date: Fri, 21 Mar 2025 21:09:54 +0800 Subject: [PATCH 13/28] =?UTF-8?q?update:=E9=85=8D=E7=BD=AE=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=BB=9F=E4=B8=80=E5=B0=8F=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py b/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py index ec0fb939..51efdc06 100644 --- a/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py +++ b/main/xiaozhi-server/core/providers/llm/AliBL/AliBL.py @@ -11,7 +11,7 @@ class LLMProvider(LLMProviderBase): self.api_key = config["api_key"] self.app_id = config["app_id"] self.base_url = config.get("base_url") - self.is_No_prompt = config.get("is_No_prompt") + self.is_No_prompt = config.get("is_no_prompt") self.memory_id = config.get("ali_memory_id") def response(self, session_id, dialogue): From ec6ab983f7d9b8e64b8add2d1e5e99eac49a60b3 Mon Sep 17 00:00:00 2001 From: hrz <1710360675@qq.com> Date: Fri, 21 Mar 2025 21:44:40 +0800 Subject: [PATCH 14/28] =?UTF-8?q?udate:=E8=A7=84=E8=8C=83=E5=8C=85?= =?UTF-8?q?=E5=90=8D=EF=BC=8C=E5=B0=8F=E5=86=99=E5=8C=85=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/security/oauth2/Oauth2Realm.java | 3 +- .../security/service/ShiroService.java | 8 ---- .../service/impl/ShiroServiceImpl.java | 16 ------- .../controller/TimbreController.java | 45 ++++++++++++++----- .../{Timbre => timbre}/dao/TimbreDao.java | 4 +- .../{Timbre => timbre}/dto/TimbreDataDTO.java | 2 +- .../{Timbre => timbre}/dto/TimbrePageDTO.java | 2 +- .../entity/TimbreEntity.java | 2 +- .../service/TimbreService.java | 10 ++--- .../service/impl/TimbreServiceImpl.java | 14 +++--- .../vo/TimbreDetailsVO.java | 2 +- 11 files changed, 53 insertions(+), 55 deletions(-) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/controller/TimbreController.java (51%) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/dao/TimbreDao.java (73%) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/dto/TimbreDataDTO.java (97%) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/dto/TimbrePageDTO.java (94%) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/entity/TimbreEntity.java (96%) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/service/TimbreService.java (80%) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/service/impl/TimbreServiceImpl.java (88%) rename main/manager-api/src/main/java/xiaozhi/modules/{Timbre => timbre}/vo/TimbreDetailsVO.java (95%) 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 b7d6c278..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 @@ -19,6 +19,7 @@ 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; /** @@ -47,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"); 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/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/Timbre/controller/TimbreController.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java similarity index 51% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/controller/TimbreController.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java index bba48abf..dc6ccca7 100644 --- 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 @@ -1,20 +1,26 @@ -package xiaozhi.modules.Timbre.controller; +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 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 */ @@ -27,38 +33,53 @@ public class TimbreController { @GetMapping @Operation(summary = "分页查找") - @RequiresPermissions("sys:ttsVoice:select") - public Result> page(@ModelAttribute TimbrePageDTO dto) { + @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:ttsVoice:save") + @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:ttsVoice:update") + @RequiresPermissions("sys:role:superAdmin") public Result update( @PathVariable Long id, @RequestBody TimbreDataDTO dto) { ValidatorUtils.validateEntity(dto); - timbreService.update(id,dto); + timbreService.update(id, dto); return new Result<>(); } + @DeleteMapping("/{id}") @Operation(summary = "音色删除") - @RequiresPermissions("sys:ttsVoice:delete") + @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 similarity index 73% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/dao/TimbreDao.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/dao/TimbreDao.java index d3273eed..62afa358 100644 --- 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 @@ -1,8 +1,8 @@ -package xiaozhi.modules.Timbre.dao; +package xiaozhi.modules.timbre.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; -import xiaozhi.modules.Timbre.entity.TimbreEntity; +import xiaozhi.modules.timbre.entity.TimbreEntity; /** * 音色持久层定义 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 similarity index 97% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/dto/TimbreDataDTO.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java index 70d44df1..08ed9b18 100644 --- 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 @@ -1,4 +1,4 @@ -package xiaozhi.modules.Timbre.dto; +package xiaozhi.modules.timbre.dto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Min; 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 similarity index 94% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/dto/TimbrePageDTO.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbrePageDTO.java index 55789c88..72ed68b1 100644 --- 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 @@ -1,4 +1,4 @@ -package xiaozhi.modules.Timbre.dto; +package xiaozhi.modules.timbre.dto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; 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 similarity index 96% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/entity/TimbreEntity.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java index 23f71c59..71bd58a9 100644 --- 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 @@ -1,4 +1,4 @@ -package xiaozhi.modules.Timbre.entity; +package xiaozhi.modules.timbre.entity; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; 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 similarity index 80% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/service/TimbreService.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/service/TimbreService.java index 7166c9c3..9b6c73eb 100644 --- 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 @@ -1,11 +1,11 @@ -package xiaozhi.modules.Timbre.service; +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; +import xiaozhi.modules.timbre.dto.TimbreDataDTO; +import xiaozhi.modules.timbre.dto.TimbrePageDTO; +import xiaozhi.modules.timbre.entity.TimbreEntity; +import xiaozhi.modules.timbre.vo.TimbreDetailsVO; /** 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 similarity index 88% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/service/impl/TimbreServiceImpl.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java index dddd0103..ce3c2b7b 100644 --- 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 @@ -1,4 +1,4 @@ -package xiaozhi.modules.Timbre.service.impl; +package xiaozhi.modules.timbre.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -9,12 +9,12 @@ 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 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; 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 similarity index 95% rename from main/manager-api/src/main/java/xiaozhi/modules/Timbre/vo/TimbreDetailsVO.java rename to main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java index 2918af41..fc82a5d0 100644 --- 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 @@ -1,4 +1,4 @@ -package xiaozhi.modules.Timbre.vo; +package xiaozhi.modules.timbre.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; From a5444b11b3f4663eca02e1ed1726104e425dcf0f Mon Sep 17 00:00:00 2001 From: CGD <3030332422@qq.com> Date: Sat, 22 Mar 2025 00:22:12 +0800 Subject: [PATCH 15/28] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E5=90=84?= =?UTF-8?q?=E4=B8=AA=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/EditVoiceDialog.vue | 22 +++--- main/manager-web/src/components/HeaderBar.vue | 10 ++- .../src/components/ModelEditDialog.vue | 71 +++++++++++++------ main/manager-web/src/views/ModelConfig.vue | 2 +- 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/main/manager-web/src/components/EditVoiceDialog.vue b/main/manager-web/src/components/EditVoiceDialog.vue index 65fc84d4..b7feb78d 100644 --- a/main/manager-web/src/components/EditVoiceDialog.vue +++ b/main/manager-web/src/components/EditVoiceDialog.vue @@ -1,5 +1,5 @@