From 1e6046cf5240842f227e7761cb8a4e0844b17e03 Mon Sep 17 00:00:00 2001 From: ageerle Date: Fri, 27 Feb 2026 14:00:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4=E6=95=B0=E5=AD=97?= =?UTF-8?q?=E4=BA=BA=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/script/sql/ruoyi-ai-v3_mysql8.sql | 143 ++--- pom.xml | 7 - ruoyi-admin/pom.xml | 6 - ruoyi-modules/pom.xml | 1 - ruoyi-modules/ruoyi-aihuman/pom.xml | 101 ---- .../org/ruoyi/aihuman/config/WebConfig.java | 16 - .../controller/AihumanConfigController.java | 126 ----- .../controller/AihumanInfoController.java | 80 --- .../AihumanRealConfigController.java | 157 ----- .../AihumanVolcengineController.java | 502 ---------------- .../ruoyi/aihuman/domain/AihumanConfig.java | 74 --- .../org/ruoyi/aihuman/domain/AihumanInfo.java | 52 -- .../aihuman/domain/AihumanRealConfig.java | 104 ---- .../ruoyi/aihuman/domain/VoiceRequest.java | 22 - .../aihuman/domain/bo/AihumanConfigBo.java | 65 --- .../aihuman/domain/bo/AihumanInfoBo.java | 44 -- .../domain/bo/AihumanRealConfigBo.java | 87 --- .../aihuman/domain/vo/AihumanConfigVo.java | 75 --- .../aihuman/domain/vo/AihumanInfoVo.java | 44 -- .../domain/vo/AihumanRealConfigVo.java | 109 ---- .../aihuman/mapper/AihumanConfigMapper.java | 17 - .../aihuman/mapper/AihumanInfoMapper.java | 16 - .../mapper/AihumanRealConfigMapper.java | 17 - .../aihuman/protocol/CompressionBits.java | 26 - .../org/ruoyi/aihuman/protocol/EventType.java | 90 --- .../aihuman/protocol/HeaderSizeBits.java | 27 - .../org/ruoyi/aihuman/protocol/Message.java | 220 -------- .../org/ruoyi/aihuman/protocol/MsgType.java | 29 - .../aihuman/protocol/MsgTypeFlagBits.java | 27 - .../aihuman/protocol/SerializationBits.java | 27 - .../protocol/SpeechWebSocketClient.java | 115 ---- .../ruoyi/aihuman/protocol/VersionBits.java | 27 - .../aihuman/service/AihumanConfigService.java | 48 -- .../service/AihumanRealConfigService.java | 56 -- .../service/AihumanVolcengineService.java | 4 - .../aihuman/service/IAihumanInfoService.java | 47 -- .../impl/AihumanConfigServiceImpl.java | 115 ---- .../service/impl/AihumanInfoServiceImpl.java | 96 ---- .../impl/AihumanRealConfigServiceImpl.java | 534 ------------------ .../impl/AihumanVolcengineServiceImpl.java | 4 - .../ruoyi/aihuman/volcengine/Bidirection.java | 160 ------ .../resources/mapper/AihumanInfoMapper.xml | 9 - .../mapper/aihuman/AihumanConfigMapper.xml | 7 - .../aihuman/AihumanRealConfigMapper.xml | 7 - 44 files changed, 53 insertions(+), 3487 deletions(-) delete mode 100644 ruoyi-modules/ruoyi-aihuman/pom.xml delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanConfigController.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanInfoController.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanRealConfigController.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanVolcengineController.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanConfig.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanInfo.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanRealConfig.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanConfigBo.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanInfoBo.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanRealConfigBo.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanConfigVo.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanInfoVo.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanRealConfigVo.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanConfigMapper.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanInfoMapper.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanRealConfigMapper.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/EventType.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/HeaderSizeBits.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/Message.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgType.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgTypeFlagBits.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SerializationBits.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SpeechWebSocketClient.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/VersionBits.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanConfigService.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanRealConfigService.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanVolcengineService.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/IAihumanInfoService.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanConfigServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanInfoServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanRealConfigServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanVolcengineServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/volcengine/Bidirection.java delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/AihumanInfoMapper.xml delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanConfigMapper.xml delete mode 100644 ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanRealConfigMapper.xml diff --git a/docs/script/sql/ruoyi-ai-v3_mysql8.sql b/docs/script/sql/ruoyi-ai-v3_mysql8.sql index 505bb0b9..26217b07 100644 --- a/docs/script/sql/ruoyi-ai-v3_mysql8.sql +++ b/docs/script/sql/ruoyi-ai-v3_mysql8.sql @@ -11,63 +11,12 @@ Target Server Version : 80045 (8.0.45) File Encoding : 65001 - Date: 24/02/2026 22:44:53 + Date: 27/02/2026 13:59:20 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; --- ---------------------------- --- Table structure for aihuman_config --- ---------------------------- -DROP TABLE IF EXISTS `aihuman_config`; -CREATE TABLE `aihuman_config` ( - `id` int NOT NULL AUTO_INCREMENT, - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `model_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `model_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `model_params` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL, - `agent_params` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL, - `create_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `update_time` datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, - `status` int NULL DEFAULT NULL, - `publish` int NULL DEFAULT NULL, - `create_dept` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '数字人配置信息' ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of aihuman_config --- ---------------------------- -INSERT INTO `aihuman_config` VALUES (9, '关爱老婆数字人(梅朵)', '梅朵吉祥物', '/Live2D/models/梅朵吉祥物/梅朵吉祥物.model3.json', '{\n \"Version\": 3,\n \"FileReferences\": {\n \"Moc\": \"梅朵吉祥物.moc3\",\n \"Textures\": [\n \"梅朵吉祥物.4096/texture_00.png\",\n \"梅朵吉祥物.4096/texture_01.png\"\n ],\n \"Physics\": \"梅朵吉祥物.physics3.json\",\n \"DisplayInfo\": \"梅朵吉祥物.cdi3.json\",\n \"MotionSync\": \"梅朵吉祥物.motionsync3.json\",\n \"Expressions\": [\n {\n \"Name\": \"kaixin\",\n \"File\": \"kaixin.exp3.json\"\n },\n {\n \"Name\": \"maozi\",\n \"File\": \"maozi.exp3.json\"\n },\n {\n \"Name\": \"mouth open\",\n \"File\": \"mouth open.exp3.json\"\n },\n {\n \"Name\": \"shibai\",\n \"File\": \"shibai.exp3.json\"\n },\n {\n \"Name\": \"yinchen\",\n \"File\": \"yinchen.exp3.json\"\n }\n ],\n \"Motions\": {\n \"\": [\n {\n \"File\": \"mouth.motion3.json\"\n }\n ]\n }\n },\n \"Groups\": [\n {\n \"Target\": \"Parameter\",\n \"Name\": \"LipSync\",\n \"Ids\": [\n \"ParamMouthForm\",\n \"ParamMouthOpenY\"\n ]\n },\n {\n \"Target\": \"Parameter\",\n \"Name\": \"EyeBlink\",\n \"Ids\": [\n \"ParamEyeLOpen\",\n \"ParamEyeROpen\"\n ]\n }\n ],\n \"HitAreas\": []\n}', '{\n \"bot_id\": \"7504596188201746470\",\n \"user_id\": \"7376476310010937396\",\n \"stream\": true,\n \"auto_save_history\": true\n}', '2025-09-29 16:36:46', '2025-09-29 16:36:46', 0, 1, NULL, NULL, '1', 0); -INSERT INTO `aihuman_config` VALUES (10, '关爱老婆数字人(K)', 'kei_vowels_pro', '/Live2D/models/kei_vowels_pro/kei_vowels_pro.model3.json', '{\n \"Version\": 3,\n \"FileReferences\": {\n \"Moc\": \"kei_vowels_pro.moc3\",\n \"Textures\": [\n \"kei_vowels_pro.2048/texture_00.png\"\n ],\n \"Physics\": \"kei_vowels_pro.physics3.json\",\n \"DisplayInfo\": \"kei_vowels_pro.cdi3.json\",\n \"MotionSync\": \"kei_vowels_pro.motionsync3.json\",\n \"Motions\": {\n \"\": [\n {\n \"File\": \"motions/01_kei_en.motion3.json\",\n \"Sound\": \"sounds/01_kei_en.wav\",\n \"MotionSync\": \"Vowels_CRI\"\n },\n {\n \"File\": \"motions/01_kei_jp.motion3.json\",\n \"Sound\": \"sounds/01_kei_jp.wav\",\n \"MotionSync\": \"Vowels_CRI\"\n },\n {\n \"File\": \"motions/01_kei_ko.motion3.json\",\n \"Sound\": \"sounds/01_kei_ko.wav\",\n \"MotionSync\": \"Vowels_CRI\"\n },\n {\n \"File\": \"motions/01_kei_zh.motion3.json\",\n \"Sound\": \"sounds/01_kei_zh.wav\",\n \"MotionSync\": \"Vowels_CRI\"\n }\n ]\n }\n },\n \"Groups\": [\n {\n \"Target\": \"Parameter\",\n \"Name\": \"LipSync\",\n \"Ids\": []\n },\n {\n \"Target\": \"Parameter\",\n \"Name\": \"EyeBlink\",\n \"Ids\": [\n \"ParamEyeLOpen\",\n \"ParamEyeROpen\"\n ]\n }\n ],\n \"HitAreas\": [\n {\n \"Id\": \"HitAreaHead\",\n \"Name\": \"Head\"\n }\n ]\n}', '3', '2025-09-29 16:35:27', '2025-09-29 16:35:27', 0, 1, NULL, NULL, '1', 0); -INSERT INTO `aihuman_config` VALUES (11, '关爱老婆数字人(March 7th)', 'March 7th', '/Live2D/models/March 7th/March 7th.model3.json', '{\n \"Version\": 3,\n \"FileReferences\": {\n \"Moc\": \"March 7th.moc3\",\n \"Textures\": [\n \"March 7th.4096/texture_00.png\",\n \"March 7th.4096/texture_01.png\"\n ],\n \"Physics\": \"March 7th.physics3.json\",\n \"DisplayInfo\": \"March 7th.cdi3.json\",\n \"Expressions\": [\n {\n \"Name\": \"捂脸\",\n \"File\": \"1.exp3.json\"\n },\n {\n \"Name\": \"比耶\",\n \"File\": \"2.exp3.json\"\n },\n {\n \"Name\": \"照相\",\n \"File\": \"3.exp3.json\"\n },\n {\n \"Name\": \"脸红\",\n \"File\": \"4.exp3.json\"\n },\n {\n \"Name\": \"黑脸\",\n \"File\": \"5.exp3.json\"\n },\n {\n \"Name\": \"哭\",\n \"File\": \"6.exp3.json\"\n },\n {\n \"Name\": \"流汗\",\n \"File\": \"7.exp3.json\"\n },\n {\n \"Name\": \"星星\",\n \"File\": \"8.exp3.json\"\n }\n ]\n },\n \"Groups\": [\n {\n \"Target\": \"Parameter\",\n \"Name\": \"EyeBlink\",\n \"Ids\": [\n \"ParamEyeLOpen\",\n \"ParamEyeROpen\"\n ]\n },\n {\n \"Target\": \"Parameter\",\n \"Name\": \"LipSync\",\n \"Ids\": [\n \"ParamMouthOpenY\"\n ]\n }\n ],\n \"HitAreas\": []\n}', '3', '2025-09-29 21:09:26', '2025-09-29 21:09:28', 0, 1, NULL, NULL, NULL, 0); -INSERT INTO `aihuman_config` VALUES (12, '关爱老婆数字人(pachan)', 'pachan', '/Live2D/models/pachan/pachan.model3.json', '{\n \"Version\": 3,\n \"FileReferences\": {\n \"Moc\": \"pachirisu anime girl - top half.moc3\",\n \"Textures\": [\n \"pachirisu anime girl - top half.4096/texture_00.png\"\n ],\n \"Physics\": \"pachirisu anime girl - top half.physics3.json\",\n \"DisplayInfo\": \"pachirisu anime girl - top half.cdi3.json\"\n },\n \"Groups\": [\n {\n \"Target\": \"Parameter\",\n \"Name\": \"EyeBlink\",\n \"Ids\": []\n },\n {\n \"Target\": \"Parameter\",\n \"Name\": \"LipSync\",\n \"Ids\": []\n }\n ]\n}', NULL, '2025-10-05 19:49:56', '2025-10-05 19:49:56', 0, 1, NULL, NULL, NULL, 0); -INSERT INTO `aihuman_config` VALUES (13, '关爱老婆数字人(230108)', '230108', '/Live2D/models/230108/230108.model3.json', '{\n \"Version\": 3,\n \"FileReferences\": {\n \"Moc\": \"230108.moc3\",\n \"Textures\": [\n \"230108.4096/texture_00.png\"\n ],\n \"Physics\": \"230108.physics3.json\",\n \"DisplayInfo\": \"230108.cdi3.json\"\n },\n \"Groups\": [\n {\n \"Target\": \"Parameter\",\n \"Name\": \"LipSync\",\n \"Ids\": [\n \"ParamMouthOpenY\"\n ]\n },\n {\n \"Target\": \"Parameter\",\n \"Name\": \"EyeBlink\",\n \"Ids\": [\n \"ParamEyeLOpen\",\n \"ParamEyeROpen\"\n ]\n }\n ]\n}', NULL, '2025-10-06 19:28:20', '2025-10-06 19:28:23', 0, 1, NULL, NULL, NULL, 0); - --- ---------------------------- --- Table structure for aihuman_info --- ---------------------------- -DROP TABLE IF EXISTS `aihuman_info`; -CREATE TABLE `aihuman_info` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '交互名称', - `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '交互内容', - `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', - `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', - `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户Id', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'AI人类交互信息表' ROW_FORMAT = DYNAMIC; - --- ---------------------------- --- Records of aihuman_info --- ---------------------------- -INSERT INTO `aihuman_info` VALUES (1, '1', '1', '2025-09-26 18:02:00', '2025-09-26 18:02:02', '0', 0); - -- ---------------------------- -- Table structure for chat_config -- ---------------------------- @@ -154,8 +103,8 @@ CREATE TABLE `chat_model` ( -- ---------------------------- -- Records of chat_model -- ---------------------------- -INSERT INTO `chat_model` VALUES (2000585866022060033, 'chat', 'deepseek/deepseek-v3.2', 'openai', 'deepseek', 1, '1', 'Y', 'Y', 1, 'https://api.ppinfra.com/openai', 'sk_xx', 103, 1, '2025-12-15 23:16:54', 1, '2026-02-06 01:02:31', 'DeepSeek-V3.2 是一款在高效推理、复杂推理能力与智能体场景中表现突出的领先模型。其基于 DeepSeek Sparse Attention(DSA)稀疏注意力机制,在显著降低计算开销的同时优化长上下文性能;通过可扩展强化学习框架,整体能力达到 GPT-5 同级,高算力版本 V3.2-Speciale 更在推理表现上接近 Gemini-3.0-Pro;同时,模型依托大型智能体任务合成管线,具备更强的工具调用与多步骤决策能力,并在 2025 年 IMO 与 IOI 中取得金牌级表现。作为 MaaS 平台,我们已对 DeepSeek-V3.2 完成深度适配,通过动态调度、批处理加速、低延迟推理与企业级 SLA 保障,进一步增强其在企业生产环境中的稳定性、性价比与可控性,适用于搜索、问答、智能体、代码、数据处理等多类高价值场景。', 0); -INSERT INTO `chat_model` VALUES (2007528268536287233, 'vector', 'baai/bge-m3', 'openai', 'bge-m3', 0, '1', 'N', 'Y', 1, 'https://api.ppinfra.com/openai', 'sk_xx', 103, 1, '2026-01-04 03:03:32', 1, '2026-02-06 01:02:35', 'bge-large-zh-v1.5', 0); +INSERT INTO `chat_model` VALUES (2000585866022060033, 'chat', 'deepseek/deepseek-v3.2', 'ppio', 'deepseek', 1, '1', 'Y', 'Y', 1, 'https://api.ppinfra.com/openai', 'sk_xx', 103, 1, '2025-12-15 23:16:54', 1, '2026-02-25 21:46:08', 'DeepSeek-V3.2 是一款在高效推理、复杂推理能力与智能体场景中表现突出的领先模型。其基于 DeepSeek Sparse Attention(DSA)稀疏注意力机制,在显著降低计算开销的同时优化长上下文性能;通过可扩展强化学习框架,整体能力达到 GPT-5 同级,高算力版本 V3.2-Speciale 更在推理表现上接近 Gemini-3.0-Pro;同时,模型依托大型智能体任务合成管线,具备更强的工具调用与多步骤决策能力,并在 2025 年 IMO 与 IOI 中取得金牌级表现。作为 MaaS 平台,我们已对 DeepSeek-V3.2 完成深度适配,通过动态调度、批处理加速、低延迟推理与企业级 SLA 保障,进一步增强其在企业生产环境中的稳定性、性价比与可控性,适用于搜索、问答、智能体、代码、数据处理等多类高价值场景。', 0); +INSERT INTO `chat_model` VALUES (2007528268536287233, 'vector', 'baai/bge-m3', 'ppio', 'bge-m3', 0, '1', 'N', 'Y', 1, 'https://api.ppinfra.com/openai', 'sk_xx', 103, 1, '2026-01-04 03:03:32', 1, '2026-02-25 21:15:14', 'bge-large-zh-v1.5', 0); -- ---------------------------- -- Table structure for chat_provider @@ -188,11 +137,11 @@ CREATE TABLE `chat_provider` ( -- ---------------------------- -- Records of chat_provider -- ---------------------------- -INSERT INTO `chat_provider` VALUES (1, 'OpenAI', 'openai', 'https://ruoyi-ai-1254149996.cos.ap-guangzhou.myqcloud.com/2025/12/15/9d944a6abfcd46e2bd6e364f07202589.png', 'OpenAI官方API服务商', 'https://api.openai.com', '0', 1, NULL, '2025-12-14 21:48:11', '1', '1', '2026-01-22 15:05:55', 'OpenAI厂商', NULL, '0', NULL, 0); -INSERT INTO `chat_provider` VALUES (2, '阿里云百炼', 'qianwen', 'https://ruoyi-ai-1254149996.cos.ap-guangzhou.myqcloud.com/2025/12/15/039ad13f690649f0ade139f8c803727b.png', '阿里云百炼大模型服务', 'https://dashscope.aliyuncs.com', '0', 2, NULL, '2025-12-14 21:48:11', '1', '1', '2026-02-06 00:58:22', '阿里云厂商', NULL, '0', NULL, 0); +INSERT INTO `chat_provider` VALUES (1, 'OpenAI', 'openai', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/01091be272334383a1efd9bc22b73ee6.png', 'OpenAI官方API服务商', 'https://api.openai.com', '0', 1, NULL, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:46:59', 'OpenAI厂商', NULL, '0', NULL, 0); +INSERT INTO `chat_provider` VALUES (2, '阿里云百炼', 'qianwen', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', '阿里云百炼大模型服务', 'https://dashscope.aliyuncs.com', '0', 2, NULL, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:49:13', '阿里云厂商', NULL, '0', NULL, 0); INSERT INTO `chat_provider` VALUES (3, '智谱AI', 'zhipu', 'https://ruoyi-ai-1254149996.cos.ap-guangzhou.myqcloud.com/2025/12/15/a43e98fb7b3b4861b8caa6184e6fa40a.png', '智谱AI大模型服务', 'https://open.bigmodel.cn', '0', 3, NULL, '2025-12-14 21:48:11', '1', '1', '2026-02-06 00:49:14', '智谱AI厂商', NULL, '1', NULL, 0); -INSERT INTO `chat_provider` VALUES (5, 'ollama', 'ollama', 'https://ruoyi-ai-1254149996.cos.ap-guangzhou.myqcloud.com/2025/12/15/2ff984bc9e4249df992733b31959056b.png', 'ollama大模型', 'http://127.0.0.1:11434', '0', 5, NULL, '2025-12-14 21:48:11', '1', '1', '2025-12-15 00:49:05', 'ollama厂商', NULL, '0', NULL, 0); -INSERT INTO `chat_provider` VALUES (2000585060904435714, 'PPIO', 'ppio', 'https://ruoyi-ai-1254149996.cos.ap-guangzhou.myqcloud.com/2025/12/15/c4f8e304ce7740029b0024934d4625bc.png', 'api聚合厂商', 'https://api.ppinfra.com/openai', '0', 5, 103, '2025-12-15 23:13:42', '1', '1', '2026-01-02 00:54:45', 'api聚合厂商', NULL, '0', NULL, 0); +INSERT INTO `chat_provider` VALUES (5, 'ollama', 'ollama', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', 'ollama大模型', 'http://127.0.0.1:11434', '0', 5, NULL, '2025-12-14 21:48:11', '1', '1', '2026-02-25 20:48:48', 'ollama厂商', NULL, '0', NULL, 0); +INSERT INTO `chat_provider` VALUES (2000585060904435714, 'PPIO', 'ppio', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', 'api聚合厂商', 'https://api.ppinfra.com/openai', '0', 5, 103, '2025-12-15 23:13:42', '1', '1', '2026-02-25 20:49:01', 'api聚合厂商', NULL, '0', NULL, 0); -- ---------------------------- -- Table structure for chat_session @@ -1485,7 +1434,7 @@ CREATE TABLE `mcp_market_info` ( INDEX `idx_name`(`name` ASC) USING BTREE, INDEX `idx_status`(`status` ASC) USING BTREE, INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP市场表' ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP市场表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of mcp_market_info @@ -1509,7 +1458,7 @@ CREATE TABLE `mcp_market_tool` ( INDEX `idx_market_id`(`market_id` ASC) USING BTREE, INDEX `idx_tool_name`(`tool_name` ASC) USING BTREE, INDEX `idx_is_loaded`(`is_loaded` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP市场工具关联表' ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'MCP市场工具关联表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of mcp_market_tool @@ -1652,7 +1601,7 @@ CREATE TABLE `sj_job_executor` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务执行器信息' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务执行器信息' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_job_executor @@ -1678,7 +1627,7 @@ CREATE TABLE `sj_job_log_message` ( INDEX `idx_task_batch_id_task_id`(`task_batch_id` ASC, `task_id` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '调度日志' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '调度日志' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_job_log_message @@ -1741,7 +1690,7 @@ CREATE TABLE `sj_job_task` ( INDEX `idx_task_batch_id_task_status`(`task_batch_id` ASC, `task_status` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务实例' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务实例' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_job_task @@ -1773,7 +1722,7 @@ CREATE TABLE `sj_job_task_batch` ( INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE, INDEX `idx_workflow_task_batch_id_workflow_node_id`(`workflow_task_batch_id` ASC, `workflow_node_id` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务批次' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务批次' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_job_task_batch @@ -1823,7 +1772,7 @@ CREATE TABLE `sj_notify_config` ( `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_namespace_id_group_name_scene_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '通知配置' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '通知配置' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_notify_config @@ -1844,7 +1793,7 @@ CREATE TABLE `sj_notify_recipient` ( `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_namespace_id`(`namespace_id` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '告警通知接收人' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '告警通知接收人' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_notify_recipient @@ -1883,7 +1832,7 @@ CREATE TABLE `sj_retry` ( INDEX `idx_retry_status_bucket_index`(`retry_status` ASC, `bucket_index` ASC) USING BTREE, INDEX `idx_parent_id`(`parent_id` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '重试信息表' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '重试信息表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_retry @@ -1912,7 +1861,7 @@ CREATE TABLE `sj_retry_dead_letter` ( INDEX `idx_idempotent_id`(`idempotent_id` ASC) USING BTREE, INDEX `idx_biz_no`(`biz_no` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '死信队列表' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '死信队列表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_retry_dead_letter @@ -1947,7 +1896,7 @@ CREATE TABLE `sj_retry_scene_config` ( `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_namespace_id_group_name_scene_name`(`namespace_id` ASC, `group_name` ASC, `scene_name` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '场景配置' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '场景配置' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_retry_scene_config @@ -2000,7 +1949,7 @@ CREATE TABLE `sj_retry_task` ( INDEX `task_status`(`task_status` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE, INDEX `idx_retry_id`(`retry_id` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '重试任务表' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '重试任务表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_retry_task @@ -2023,7 +1972,7 @@ CREATE TABLE `sj_retry_task_log_message` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_namespace_id_group_name_retry_task_id`(`namespace_id` ASC, `group_name` ASC, `retry_task_id` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务调度日志信息记录表' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '任务调度日志信息记录表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_retry_task_log_message @@ -2050,7 +1999,7 @@ CREATE TABLE `sj_server_node` ( UNIQUE INDEX `uk_host_id_host_ip`(`host_id` ASC, `host_ip` ASC) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE, INDEX `idx_expire_at_node_type`(`expire_at` ASC, `node_type` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '服务器节点' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '服务器节点' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_server_node @@ -2089,7 +2038,7 @@ CREATE TABLE `sj_system_user_permission` ( `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_namespace_id_group_name_system_user_id`(`namespace_id` ASC, `group_name` ASC, `system_user_id` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统用户权限表' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '系统用户权限表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_system_user_permission @@ -2124,7 +2073,7 @@ CREATE TABLE `sj_workflow` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '工作流' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '工作流' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_workflow @@ -2155,7 +2104,7 @@ CREATE TABLE `sj_workflow_node` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '工作流节点' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '工作流节点' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_workflow_node @@ -2184,7 +2133,7 @@ CREATE TABLE `sj_workflow_task_batch` ( INDEX `idx_job_id_task_batch_status`(`workflow_id` ASC, `task_batch_status` ASC) USING BTREE, INDEX `idx_create_dt`(`create_dt` ASC) USING BTREE, INDEX `idx_namespace_id_group_name`(`namespace_id` ASC, `group_name` ASC) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '工作流批次' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '工作流批次' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sj_workflow_task_batch @@ -2387,6 +2336,11 @@ INSERT INTO `sys_dict_data` VALUES (2018858143757504522, '154726', 0, 'PC', 'pc' INSERT INTO `sys_dict_data` VALUES (2018858143761698817, '154726', 0, '安卓', 'android', 'sys_device_type', '', 'default', 'N', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', '安卓'); INSERT INTO `sys_dict_data` VALUES (2018858143761698818, '154726', 0, 'iOS', 'ios', 'sys_device_type', '', 'default', 'N', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', 'iOS'); INSERT INTO `sys_dict_data` VALUES (2018858143761698819, '154726', 0, '小程序', 'xcx', 'sys_device_type', '', 'default', 'N', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', '小程序'); +INSERT INTO `sys_dict_data` VALUES (2026642472673288194, '000000', 0, '对话', 'chat', 'chat_model_category', NULL, 'cyan', 'N', 103, 1, '2026-02-25 20:56:33', 1, '2026-02-25 21:01:42', NULL); +INSERT INTO `sys_dict_data` VALUES (2026642525081116674, '000000', 1, '图像', 'image', 'chat_model_category', NULL, 'success', 'N', 103, 1, '2026-02-25 20:56:46', 1, '2026-02-25 21:01:37', NULL); +INSERT INTO `sys_dict_data` VALUES (2026643983713247233, '000000', 1, '次数计费', '1', 'sys_model_billing', NULL, 'green', 'N', 103, 1, '2026-02-25 21:02:34', 1, '2026-02-25 21:02:56', NULL); +INSERT INTO `sys_dict_data` VALUES (2026644058522853378, '000000', 2, 'token计费', '2', 'sys_model_billing', NULL, 'primary', 'N', 103, 1, '2026-02-25 21:02:51', 1, '2026-02-25 21:02:51', NULL); +INSERT INTO `sys_dict_data` VALUES (2027261114955931650, '000000', 2, '向量', 'vector', 'chat_model_category', NULL, 'default', 'N', 103, 1, '2026-02-27 13:54:49', 1, '2026-02-27 13:54:54', NULL); -- ---------------------------- -- Table structure for sys_dict_type @@ -2430,6 +2384,8 @@ INSERT INTO `sys_dict_type` VALUES (2018858143723950085, '154726', '操作类型 INSERT INTO `sys_dict_type` VALUES (2018858143723950086, '154726', '系统状态', 'sys_common_status', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', '登录状态列表'); INSERT INTO `sys_dict_type` VALUES (2018858143723950087, '154726', '授权类型', 'sys_grant_type', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', '认证授权类型'); INSERT INTO `sys_dict_type` VALUES (2018858143723950088, '154726', '设备类型', 'sys_device_type', 103, 1, '2026-02-04 09:24:25', 1, '2026-02-04 09:24:25', '客户端设备类型'); +INSERT INTO `sys_dict_type` VALUES (2026642112982360066, '000000', '模型分类', 'chat_model_category', 103, 1, '2026-02-25 20:55:08', 1, '2026-02-25 20:55:08', '模型分类'); +INSERT INTO `sys_dict_type` VALUES (2026642183606050817, '000000', '计费方式', 'sys_model_billing', 103, 1, '2026-02-25 20:55:24', 1, '2026-02-25 20:55:24', '计费方式'); -- ---------------------------- -- Table structure for sys_logininfor @@ -2668,6 +2624,15 @@ INSERT INTO `sys_logininfor` VALUES (2019224998575153153, '000000', 'admin', 'pc INSERT INTO `sys_logininfor` VALUES (2019225059417726977, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-05 09:42:24'); INSERT INTO `sys_logininfor` VALUES (2019240817392693249, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-05 10:45:01'); INSERT INTO `sys_logininfor` VALUES (2019447979716972545, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-06 00:28:13'); +INSERT INTO `sys_logininfor` VALUES (2026536636865163265, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-25 13:56:00'); +INSERT INTO `sys_logininfor` VALUES (2026556949535502337, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-25 15:16:43'); +INSERT INTO `sys_logininfor` VALUES (2026578433112911874, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-25 16:42:05'); +INSERT INTO `sys_logininfor` VALUES (2026638437400518657, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-25 20:40:31'); +INSERT INTO `sys_logininfor` VALUES (2026647463072952321, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-25 21:16:23'); +INSERT INTO `sys_logininfor` VALUES (2026653919016968194, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '退出成功', '2026-02-25 21:42:02'); +INSERT INTO `sys_logininfor` VALUES (2026654082020204546, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-25 21:42:41'); +INSERT INTO `sys_logininfor` VALUES (2026654455514587138, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-25 21:44:10'); +INSERT INTO `sys_logininfor` VALUES (2027260957187186689, '000000', 'admin', 'pc', 'pc', '127.0.0.1', '内网IP', 'MSEdge', 'Windows 10 or Windows Server 2016', '0', '登录成功', '2026-02-27 13:54:12'); -- ---------------------------- -- Table structure for sys_menu @@ -2703,7 +2668,7 @@ CREATE TABLE `sys_menu` ( INSERT INTO `sys_menu` VALUES (1, '系统管理', 0, 3, 'system', '', '', 1, 0, 'M', '0', '0', '', 'eos-icons:system-group', 103, 1, '2025-12-14 16:11:49', 1, '2026-01-01 19:06:19', '系统管理目录'); INSERT INTO `sys_menu` VALUES (2, '系统监控', 0, 3, 'monitor', '', '', 1, 0, 'M', '0', '0', '', 'solar:monitor-camera-outline', 103, 1, '2025-12-14 16:11:49', 1, '2025-12-14 17:56:44', '系统监控目录'); INSERT INTO `sys_menu` VALUES (3, '系统工具', 0, 4, 'tool', NULL, '', 1, 0, 'M', '0', '0', '', 'ant-design:tool-outlined', 103, 1, '2025-12-14 16:11:49', NULL, NULL, '系统工具目录'); -INSERT INTO `sys_menu` VALUES (6, '租户管理', 0, 2, 'tenant', NULL, '', 1, 0, 'M', '0', '0', '', 'ph:users-light', 103, 1, '2025-12-14 16:11:49', NULL, NULL, '租户管理目录'); +INSERT INTO `sys_menu` VALUES (6, '租户管理', 0, 8, 'tenant', '', '', 1, 0, 'M', '0', '0', '', 'ph:users-light', 103, 1, '2025-12-14 16:11:49', 1, '2026-02-25 20:42:14', '租户管理目录'); INSERT INTO `sys_menu` VALUES (100, '用户管理', 1, 1, 'user', 'system/user/index', '', 1, 0, 'C', '0', '0', 'system:user:list', 'ant-design:user-outlined', 103, 1, '2025-12-14 16:11:49', NULL, NULL, '用户管理菜单'); INSERT INTO `sys_menu` VALUES (101, '角色管理', 1, 2, 'role', 'system/role/index', '', 1, 0, 'C', '0', '0', 'system:role:list', 'eos-icons:role-binding-outlined', 103, 1, '2025-12-14 16:11:49', NULL, NULL, '角色管理菜单'); INSERT INTO `sys_menu` VALUES (102, '菜单管理', 1, 3, 'menu', 'system/menu/index', '', 1, 0, 'C', '0', '0', 'system:menu:list', 'ic:sharp-menu', 103, 1, '2025-12-14 16:11:49', NULL, NULL, '菜单管理菜单'); @@ -2807,8 +2772,8 @@ INSERT INTO `sys_menu` VALUES (1620, '配置列表', 118, 5, '#', '', '', 1, 0, INSERT INTO `sys_menu` VALUES (1621, '配置添加', 118, 6, '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:add', '#', 103, 1, '2025-12-14 16:11:49', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (1622, '配置编辑', 118, 6, '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:edit', '#', 103, 1, '2025-12-14 16:11:49', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (1623, '配置删除', 118, 6, '#', '', '', 1, 0, 'F', '0', '0', 'system:ossConfig:remove', '#', 103, 1, '2025-12-14 16:11:49', NULL, NULL, ''); -INSERT INTO `sys_menu` VALUES (2000, 'MCP管理', 0, 5, 'mcp', '', '', 1, 0, 'M', '0', '0', '', 'mdi:robot-industrial', 103, 1, '2026-02-24 20:02:47', NULL, NULL, 'MCP模块管理菜单'); -INSERT INTO `sys_menu` VALUES (2001, 'MCP工具管理', 2000, 1, 'tool', 'mcp/tool/index', '', 1, 0, 'C', '0', '0', 'mcp:tool:list', 'material-symbols:tools-hammer-outline', 103, 1, '2026-02-24 20:02:47', NULL, NULL, 'MCP工具管理菜单'); +INSERT INTO `sys_menu` VALUES (2000, 'MCP管理', 0, 2, 'mcp', '', '', 1, 0, 'M', '0', '0', '', 'mdi:robot-industrial', 103, 1, '2026-02-24 20:02:47', 1, '2026-02-25 20:41:54', 'MCP模块管理菜单'); +INSERT INTO `sys_menu` VALUES (2001, 'MCP工具管理', 2000, 1, 'tool', 'mcp/tool/index', '', 1, 0, 'C', '0', '0', 'mcp:tool:list', 'octicon:tools-24', 103, 1, '2026-02-24 20:02:47', 1, '2026-02-25 20:41:27', 'MCP工具管理菜单'); INSERT INTO `sys_menu` VALUES (2002, 'MCP工具查询', 2001, 1, '#', '', '', 1, 0, 'F', '0', '0', 'mcp:tool:query', '#', 103, 1, '2026-02-24 20:02:47', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (2003, 'MCP工具新增', 2001, 2, '#', '', '', 1, 0, 'F', '0', '0', 'mcp:tool:add', '#', 103, 1, '2026-02-24 20:02:47', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (2004, 'MCP工具修改', 2001, 3, '#', '', '', 1, 0, 'F', '0', '0', 'mcp:tool:edit', '#', 103, 1, '2026-02-24 20:02:47', NULL, NULL, ''); @@ -2847,13 +2812,6 @@ INSERT INTO `sys_menu` VALUES (11803, '流程达式定义新增', 11801, 2, '#', INSERT INTO `sys_menu` VALUES (11804, '流程达式定义修改', 11801, 3, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:edit', '#', 103, 1, '2026-01-05 14:39:33', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (11805, '流程达式定义删除', 11801, 4, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:remove', '#', 103, 1, '2026-01-05 14:39:33', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (11806, '流程达式定义导出', 11801, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'workflow:spel:export', '#', 103, 1, '2026-01-05 14:39:33', NULL, NULL, ''); -INSERT INTO `sys_menu` VALUES (1971546066781597696, '数字人体验', 2019459914910994434, 10, 'aihumanPublish', 'aihuman/aihumanPublish/index', NULL, 1, 0, 'C', '0', '0', '', 'mdi:human-child', 103, 1, '2026-02-06 01:13:22', 1, '2026-02-06 01:29:34', '数字人信息管理菜单'); -INSERT INTO `sys_menu` VALUES (1971546066781597697, '数字人信息管理查询', 1971546066781597696, 1, '#', '', NULL, 1, 0, 'F', '0', '0', 'aihuman:aihumanInfo:query', '#', 103, 1, '2026-02-06 01:13:22', NULL, NULL, ''); -INSERT INTO `sys_menu` VALUES (1971546066781597698, '数字人信息管理新增', 1971546066781597696, 2, '#', '', NULL, 1, 0, 'F', '0', '0', 'aihuman:aihumanInfo:add', '#', 103, 1, '2026-02-06 01:13:22', NULL, NULL, ''); -INSERT INTO `sys_menu` VALUES (1971546066781597699, '数字人信息管理修改', 1971546066781597696, 3, '#', '', NULL, 1, 0, 'F', '0', '0', 'aihuman:aihumanInfo:edit', '#', 103, 1, '2026-02-06 01:13:22', NULL, NULL, ''); -INSERT INTO `sys_menu` VALUES (1971546066781597700, '数字人信息管理删除', 1971546066781597696, 4, '#', '', NULL, 1, 0, 'F', '0', '0', 'aihuman:aihumanInfo:remove', '#', 103, 1, '2026-02-06 01:13:22', NULL, NULL, ''); -INSERT INTO `sys_menu` VALUES (1971546066781597701, '数字人信息管理导出', 1971546066781597696, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'aihuman:aihumanInfo:export', '#', 103, 1, '2026-02-06 01:13:22', NULL, NULL, ''); -INSERT INTO `sys_menu` VALUES (1980480880138051584, '数字人配置', 2019459914910994434, 1, 'aihumanConfig', 'aihuman/aihumanConfig/index', NULL, 1, 0, 'C', '0', '0', 'aihuman:aihumanConfig:list', 'mdi:human-child', 103, 1, '2026-02-06 01:13:35', 1, '2026-02-06 01:28:12', ''); INSERT INTO `sys_menu` VALUES (2000209300188356609, '对话管理', 0, 0, 'chat', '', NULL, 1, 0, 'M', '0', '0', NULL, 'material-symbols:chat-outline', 103, 1, '2025-12-14 22:20:34', 1, '2025-12-14 22:21:24', ''); INSERT INTO `sys_menu` VALUES (2000210913451892738, '厂商管理', 2000209300188356609, 1, 'provider', 'chat/provider/index', NULL, 1, 0, 'C', '0', '0', 'system:provider:list', 'tabler:cube-spark', 103, 1, '2025-12-14 22:28:05', 1, '2025-12-14 23:42:55', '厂商管理菜单'); INSERT INTO `sys_menu` VALUES (2000210913451892739, '厂商管理查询', 2000210913451892738, 1, '#', '', NULL, 1, 0, 'F', '0', '0', 'system:provider:query', '#', 103, 1, '2025-12-14 22:28:05', NULL, NULL, ''); @@ -2886,7 +2844,6 @@ INSERT INTO `sys_menu` VALUES (2006681261898813444, '知识库修改', 200668126 INSERT INTO `sys_menu` VALUES (2006681261898813445, '知识库删除', 2006681261898813441, 4, '#', '', NULL, 1, 0, 'F', '0', '0', 'system:info:remove', '#', 103, 1, '2026-01-01 18:59:06', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (2006681261898813446, '知识库导出', 2006681261898813441, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'system:info:export', '#', 103, 1, '2026-01-01 18:59:06', NULL, NULL, ''); INSERT INTO `sys_menu` VALUES (2006683336984580098, '知识管理', 0, 2, 'knowledge', '', NULL, 1, 0, 'M', '0', '0', NULL, 'bx:book', 103, 1, '2026-01-01 19:06:05', 1, '2026-01-01 19:06:05', ''); -INSERT INTO `sys_menu` VALUES (2019459914910994434, '数字人管理', 0, 2, 'human', '', NULL, 1, 0, 'M', '0', '0', NULL, 'tdesign:user', 103, 1, '2026-02-06 01:15:38', 1, '2026-02-06 01:16:58', ''); INSERT INTO `sys_menu` VALUES (2019464280262905857, '图谱实例', 2019464531388469250, 1, 'graphInstance', 'graph/graphInstance/index', NULL, 1, 0, 'C', '0', '0', 'operator:graph:list', 'ant-design:node-index-outlined', 103, 1, '2026-02-06 01:32:59', 1, '2026-02-06 01:40:06', ''); INSERT INTO `sys_menu` VALUES (2019464531388469250, '知识图谱', 2006683336984580098, 15, 'graph', '', NULL, 1, 0, 'M', '0', '0', NULL, 'carbon:chart-relationship', 103, 1, '2026-02-06 01:33:59', 1, '2026-02-06 01:33:59', ''); INSERT INTO `sys_menu` VALUES (2019464779217309697, '图谱可视化', 2019464531388469250, 2, 'graphVisualization', 'graph/graphVisualization/index', NULL, 1, 0, 'C', '0', '0', 'operator:graph:view', 'carbon:chart-network', 103, 1, '2026-02-06 01:34:58', 1, '2026-02-06 01:40:14', ''); @@ -2975,6 +2932,12 @@ CREATE TABLE `sys_oss` ( -- ---------------------------- -- Records of sys_oss -- ---------------------------- +INSERT INTO `sys_oss` VALUES (2026580908423340033, '000000', '2026/02/25/9219d6d71a6d45e19192014609d92dc9.png', 'logo.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/9219d6d71a6d45e19192014609d92dc9.png', '{\"fileSize\":\"183613\",\"contentType\":\"image/png\"}', 103, '2026-02-25 16:51:55', 1, '2026-02-25 16:51:55', 1, 'qcloud'); +INSERT INTO `sys_oss` VALUES (2026640059920883713, '000000', '2026/02/25/01091be272334383a1efd9bc22b73ee6.png', 'openai.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/01091be272334383a1efd9bc22b73ee6.png', '{\"fileSize\":\"11297\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:46:58', 1, '2026-02-25 20:46:58', 1, 'qcloud'); +INSERT INTO `sys_oss` VALUES (2026640515967557633, '000000', '2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', 'ollama.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/afecabebc8014d80b0f06b4796a74c5d.png', '{\"fileSize\":\"8746\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:48:47', 1, '2026-02-25 20:48:47', 1, 'qcloud'); +INSERT INTO `sys_oss` VALUES (2026640548213366785, '000000', '2026/02/25/e16429a462e54e14a1d36673146b9e3c.png', 'ppio-color.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/e16429a462e54e14a1d36673146b9e3c.png', '{\"fileSize\":\"7382\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:48:55', 1, '2026-02-25 20:48:55', 1, 'qcloud'); +INSERT INTO `sys_oss` VALUES (2026640572443860993, '000000', '2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', 'ppio-color.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/049bb6a507174f73bba4b8d8b9e55b8a.png', '{\"fileSize\":\"7382\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:49:00', 1, '2026-02-25 20:49:00', 1, 'qcloud'); +INSERT INTO `sys_oss` VALUES (2026640621945036802, '000000', '2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', 'bailian-color.png', '.png', 'https://ruoyiai-1254149996.cos.ap-guangzhou.myqcloud.com/2026/02/25/de2aa7e649de44f3ba5c6380ac6acd04.png', '{\"fileSize\":\"5901\",\"contentType\":\"image/png\"}', 103, '2026-02-25 20:49:12', 1, '2026-02-25 20:49:12', 1, 'qcloud'); -- ---------------------------- -- Table structure for sys_oss_config @@ -3007,10 +2970,10 @@ CREATE TABLE `sys_oss_config` ( -- ---------------------------- -- Records of sys_oss_config -- ---------------------------- -INSERT INTO `sys_oss_config` VALUES (1, '000000', 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', '127.0.0.1:9000', '', 'N', '', '1', '0', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-03 05:14:52', NULL); +INSERT INTO `sys_oss_config` VALUES (1, '000000', 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', '127.0.0.1:9000', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-25 15:44:13', NULL); INSERT INTO `sys_oss_config` VALUES (2, '000000', 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 's3-cn-north-1.qiniucs.com', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-03 05:14:52', NULL); INSERT INTO `sys_oss_config` VALUES (3, '000000', 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'oss-cn-beijing.aliyuncs.com', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-03 05:14:52', NULL); -INSERT INTO `sys_oss_config` VALUES (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1240000000', '', 'cos.ap-beijing.myqcloud.com', '', 'N', 'ap-beijing', '1', '1', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-03 05:14:52', NULL); +INSERT INTO `sys_oss_config` VALUES (4, '000000', 'qcloud', 'xx', 'xx', 'ruoyiai-1254149996', '', 'cos.ap-guangzhou.myqcloud.com', '', 'Y', 'ap-guangzhou', '1', '0', '', 103, 1, '2026-02-03 05:14:52', 1, '2026-02-25 16:51:41', ''); INSERT INTO `sys_oss_config` VALUES (5, '000000', 'image', 'ruoyi', 'ruoyi123', 'ruoyi', 'image', '127.0.0.1:9000', '', 'N', '', '1', '1', '', 103, 1, '2026-02-03 05:14:53', 1, '2026-02-03 05:14:53', NULL); -- ---------------------------- @@ -3457,7 +3420,7 @@ CREATE TABLE `sys_user` ( -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO `sys_user` VALUES (1, '000000', 103, 'admin', 'admin', 'sys_user', 'ageerle@163.com', '15888888888', '1', NULL, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', '2026-02-06 00:28:13', 103, 1, '2026-02-05 09:22:12', -1, '2026-02-06 00:28:13', '管理员', NULL, 0.00); +INSERT INTO `sys_user` VALUES (1, '000000', 103, 'admin', 'admin', 'sys_user', 'ageerle@163.com', '15888888888', '1', NULL, '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', '2026-02-27 13:54:12', 103, 1, '2026-02-05 09:22:12', -1, '2026-02-27 13:54:12', '管理员', NULL, 0.00); INSERT INTO `sys_user` VALUES (3, '000000', 108, 'test', '本部门及以下 密码666666', 'sys_user', '', '', '0', NULL, '$2a$10$b8yUzN0C71sbz.PhNOCgJe.Tu1yWC3RNrTyjSQ8p1W0.aaUXUJ.Ne', '0', '0', '127.0.0.1', '2026-02-05 09:22:12', 103, 1, '2026-02-05 09:22:12', 3, '2026-02-05 09:22:12', NULL, NULL, 0.00); INSERT INTO `sys_user` VALUES (4, '000000', 102, 'test1', '仅本人 密码666666', 'sys_user', '', '', '0', NULL, '$2a$10$b8yUzN0C71sbz.PhNOCgJe.Tu1yWC3RNrTyjSQ8p1W0.aaUXUJ.Ne', '0', '0', '127.0.0.1', '2026-02-05 09:22:12', 103, 1, '2026-02-05 09:22:12', 4, '2026-02-05 09:22:12', NULL, NULL, 0.00); diff --git a/pom.xml b/pom.xml index e10bf329..dbd40c94 100644 --- a/pom.xml +++ b/pom.xml @@ -390,13 +390,6 @@ ${revision} - - - org.ruoyi - ruoyi-aihuman - ${revision} - - org.ruoyi diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 1ee16ddb..153e82da 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -104,12 +104,6 @@ ruoyi-wechat - - - org.ruoyi - ruoyi-aihuman - - org.ruoyi diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml index 67d9ecfd..73fe7257 100644 --- a/ruoyi-modules/pom.xml +++ b/ruoyi-modules/pom.xml @@ -10,7 +10,6 @@ 4.0.0 - ruoyi-aihuman ruoyi-aiflow ruoyi-chat ruoyi-demo diff --git a/ruoyi-modules/ruoyi-aihuman/pom.xml b/ruoyi-modules/ruoyi-aihuman/pom.xml deleted file mode 100644 index baaf8619..00000000 --- a/ruoyi-modules/ruoyi-aihuman/pom.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - 4.0.0 - - org.ruoyi - ruoyi-modules - ${revision} - ../pom.xml - - - ruoyi-aihuman - - - aihuman模块 - - - - 3.2.1 - 5.13.0 - 1.5.5 - - - - - - - org.ruoyi - ruoyi-common-core - - - - org.ruoyi - ruoyi-common-doc - - - - org.ruoyi - ruoyi-common-mybatis - - - - org.ruoyi - ruoyi-common-web - - - - org.ruoyi - ruoyi-common-log - - - - org.ruoyi - ruoyi-common-idempotent - - - - - org.apache.velocity - velocity-engine-core - - - - - - - - - - - - - - - - org.ruoyi - ruoyi-common-excel - - - - net.java.dev.jna - jna - ${jna.version} - - - - net.java.dev.jna - jna-platform - ${jna.version} - - - - org.java-websocket - Java-WebSocket - ${java-websocket.version} - - - - - diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java deleted file mode 100644 index 5ccaf134..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.ruoyi.aihuman.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@Configuration -public class WebConfig implements WebMvcConfigurer { - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - // 映射/voice/**路径到classpath:/voice/目录 - registry.addResourceHandler("/voice/**") - .addResourceLocations("classpath:/voice/") - .setCachePeriod(3600); - } -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanConfigController.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanConfigController.java deleted file mode 100644 index c4397df8..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanConfigController.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.ruoyi.aihuman.controller; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.dev33.satoken.annotation.SaIgnore; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.ruoyi.aihuman.domain.bo.AihumanConfigBo; -import org.ruoyi.aihuman.domain.vo.AihumanConfigVo; -import org.ruoyi.aihuman.service.AihumanConfigService; -import org.ruoyi.common.core.domain.R; -import org.ruoyi.common.core.validate.AddGroup; -import org.ruoyi.common.core.validate.EditGroup; -import org.ruoyi.common.excel.utils.ExcelUtil; -import org.ruoyi.common.idempotent.annotation.RepeatSubmit; -import org.ruoyi.common.log.annotation.Log; -import org.ruoyi.common.log.enums.BusinessType; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; -import org.ruoyi.common.web.core.BaseController; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 交互数字人配置 - * - * @author ageerle - * @date Fri Sep 26 22:27:00 GMT+08:00 2025 - */ - -//临时免登录 -@SaIgnore - -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/aihuman/aihumanConfig") -public class AihumanConfigController extends BaseController { - - private final AihumanConfigService aihumanConfigService; - - /** - * 查询交互数字人配置列表 - */ - @SaCheckPermission("aihuman:aihumanConfig:list") - @GetMapping("/list") - public TableDataInfo list(AihumanConfigBo bo, PageQuery pageQuery) { - return aihumanConfigService.queryPageList(bo, pageQuery); - } - - /** - * 导出交互数字人配置列表 - */ - @SaCheckPermission("aihuman:aihumanConfig:export") - @Log(title = "交互数字人配置", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(AihumanConfigBo bo, HttpServletResponse response) { - List list = aihumanConfigService.queryList(bo); - ExcelUtil.exportExcel(list, "交互数字人配置", AihumanConfigVo.class, response); - } - - /** - * 获取交互数字人配置详细信息 - * - * @param id 主键 - */ - @SaCheckPermission("aihuman:aihumanConfig:query") - @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Integer id) { - return R.ok(aihumanConfigService.queryById(id)); - } - - /** - * 新增交互数字人配置 - */ - @SaCheckPermission("aihuman:aihumanConfig:add") - @Log(title = "交互数字人配置", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping() - public R add(@Validated(AddGroup.class) @RequestBody AihumanConfigBo bo) { - return toAjax(aihumanConfigService.insertByBo(bo)); - } - - /** - * 修改交互数字人配置 - */ - @SaCheckPermission("aihuman:aihumanConfig:edit") - @Log(title = "交互数字人配置", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping() - public R edit(@Validated(EditGroup.class) @RequestBody AihumanConfigBo bo) { - return toAjax(aihumanConfigService.updateByBo(bo)); - } - - /** - * 删除交互数字人配置 - * - * @param ids 主键串 - */ - @SaCheckPermission("aihuman:aihumanConfig:remove") - @Log(title = "交互数字人配置", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Integer[] ids) { - return toAjax(aihumanConfigService.deleteWithValidByIds(List.of(ids), true)); - } - - /** - * 查询已发布的交互数字人配置列表 - * 只返回 publish = 1 的数据 - */ - @GetMapping("/publishedList") - public TableDataInfo publishedList(PageQuery pageQuery) { - // 创建查询条件对象并设置publish=1 - AihumanConfigBo bo = new AihumanConfigBo(); - bo.setPublish(1); - // 调用现有的查询方法,传入预设了publish=1条件的bo对象 - return aihumanConfigService.queryPageList(bo, pageQuery); - } - - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanInfoController.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanInfoController.java deleted file mode 100644 index 2f0e9628..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanInfoController.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.ruoyi.aihuman.controller; - -import cn.dev33.satoken.annotation.SaIgnore; -import lombok.RequiredArgsConstructor; -import org.ruoyi.aihuman.domain.AihumanInfo; -import org.ruoyi.aihuman.domain.vo.AihumanInfoVo; -import org.ruoyi.aihuman.service.IAihumanInfoService; -import org.ruoyi.common.core.domain.R; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Arrays; - -/** - * AI人类交互信息Controller - * 免登录接口,方便验证 - * - * @author QingYunAI - */ -@SaIgnore -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/aihuman/info") -public class AihumanInfoController { - - private final IAihumanInfoService aihumanInfoService; - - /** - * 获取AI人类交互信息详情 - */ - @GetMapping("/{id}") - public R getInfo(@PathVariable Long id) { - return R.ok(aihumanInfoService.queryById(id)); - } - - /** - * 查询AI人类交互信息列表 - */ - @GetMapping("/list") - public R> list(AihumanInfo aihumanInfo, PageQuery pageQuery) { - TableDataInfo tableDataInfo = aihumanInfoService.queryPageList(aihumanInfo, pageQuery); - return R.ok(tableDataInfo); - } - - /** - * 新增AI人类交互信息 - */ - @PostMapping - public R add(@Validated @RequestBody AihumanInfo aihumanInfo) { - return R.ok(aihumanInfoService.insert(aihumanInfo)); - } - - /** - * 修改AI人类交互信息 - */ - @PutMapping - public R edit(@Validated @RequestBody AihumanInfo aihumanInfo) { - return R.ok(aihumanInfoService.update(aihumanInfo)); - } - - /** - * 删除AI人类交互信息 - */ - @DeleteMapping("/{ids}") - public R remove(@PathVariable Long[] ids) { - return R.ok(aihumanInfoService.deleteWithValidByIds(Arrays.asList(ids), true)); - } - - /** - * 测试接口 - * 提供一个简单的GET接口用于快速验证控制器是否正常工作 - */ - @GetMapping("/test") - public R test() { - return R.ok("AI Human Controller is working!"); - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanRealConfigController.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanRealConfigController.java deleted file mode 100644 index 46e47198..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanRealConfigController.java +++ /dev/null @@ -1,157 +0,0 @@ -package org.ruoyi.aihuman.controller; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.dev33.satoken.annotation.SaIgnore; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.ruoyi.aihuman.domain.bo.AihumanRealConfigBo; -import org.ruoyi.aihuman.domain.vo.AihumanRealConfigVo; -import org.ruoyi.aihuman.service.AihumanRealConfigService; -import org.ruoyi.common.core.domain.R; -import org.ruoyi.common.core.validate.AddGroup; -import org.ruoyi.common.core.validate.EditGroup; -import org.ruoyi.common.excel.utils.ExcelUtil; -import org.ruoyi.common.idempotent.annotation.RepeatSubmit; -import org.ruoyi.common.log.annotation.Log; -import org.ruoyi.common.log.enums.BusinessType; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; -import org.ruoyi.common.web.core.BaseController; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 真人交互数字人配置 - * - * @author ageerle - * @date Tue Oct 21 11:46:52 GMT+08:00 2025 - */ -//临时免登录 -@SaIgnore - -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/aihuman/aihumanRealConfig") -public class AihumanRealConfigController extends BaseController { - - private final AihumanRealConfigService aihumanRealConfigService; - - /** - * 查询真人交互数字人配置列表 - */ - @SaCheckPermission("aihuman:aihumanRealConfig:list") - @GetMapping("/list") - public TableDataInfo list(AihumanRealConfigBo bo, PageQuery pageQuery) { - return aihumanRealConfigService.queryPageList(bo, pageQuery); - } - - /** - * 导出真人交互数字人配置列表 - */ - @SaCheckPermission("aihuman:aihumanRealConfig:export") - @Log(title = "真人交互数字人配置", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(AihumanRealConfigBo bo, HttpServletResponse response) { - List list = aihumanRealConfigService.queryList(bo); - ExcelUtil.exportExcel(list, "真人交互数字人配置", AihumanRealConfigVo.class, response); - } - - /** - * 获取真人交互数字人配置详细信息 - * - * @param id 主键 - */ - @SaCheckPermission("aihuman:aihumanRealConfig:query") - @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Integer id) { - return R.ok(aihumanRealConfigService.queryById(id)); - } - - /** - * 新增真人交互数字人配置 - */ - @SaCheckPermission("aihuman:aihumanRealConfig:add") - @Log(title = "真人交互数字人配置", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping() - public R add(@Validated(AddGroup.class) @RequestBody AihumanRealConfigBo bo) { - return toAjax(aihumanRealConfigService.insertByBo(bo)); - } - - /** - * 修改真人交互数字人配置 - */ - @SaCheckPermission("aihuman:aihumanRealConfig:edit") - @Log(title = "真人交互数字人配置", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping() - public R edit(@Validated(EditGroup.class) @RequestBody AihumanRealConfigBo bo) { - return toAjax(aihumanRealConfigService.updateByBo(bo)); - } - - /** - * 删除真人交互数字人配置 - * - * @param ids 主键串 - */ - @SaCheckPermission("aihuman:aihumanRealConfig:remove") - @Log(title = "真人交互数字人配置", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Integer[] ids) { - return toAjax(aihumanRealConfigService.deleteWithValidByIds(List.of(ids), true)); - } - - /** - * 1.执行以下命令: - * cd F:\Projects\AI-Human\LiveTalking - * conda activate D:\zg117\C\Users\zg117\.conda\envs\livetalking_new - * python app.py --transport webrtc --model wav2lip --avatar_id wav2lip256_avatar1 - *

- * 2.监听 python app.py --transport webrtc --model wav2lip --avatar_id wav2lip256_avatar1 执行情况 - *

- * 3.返回执行结果并打开页面 - * http://127.0.0.1:8010/webrtcapi-diy.html - */ - @SaCheckPermission("aihuman:aihumanRealConfig:run") - //@Log(title = "真人交互数字人配置", businessType = BusinessType.UPDATE, operatorType = OperatorType.OTHER) - @RepeatSubmit() - @PutMapping("/run") - public R run(@Validated(EditGroup.class) @RequestBody AihumanRealConfigBo bo) { - boolean result = aihumanRealConfigService.runByBo(bo); - if (result) { - // 返回前端页面URL,前端可以根据这个URL跳转或打开新页面 - // http://127.0.0.1:8010/webrtcapi-diy.html 其中的 http://127.0.0.1 获取当前java服务的IP地址 - // return R.ok("http://127.0.0.1:8010/webrtcapi-diy.html"); - // 运行状态 - bo.setRunStatus("1"); - return R.ok("http://127.0.0.1:8010/webrtcapi-diy.html"); - } else { - return R.fail("启动真人交互数字人失败"); - } - } - - /** - * 停止真人交互数字人配置任务 - */ - @SaCheckPermission("aihuman:aihumanRealConfig:stop") - //@Log(title = "真人交互数字人配置", businessType = BusinessType.UPDATE, operatorType = OperatorType.OTHER) - @RepeatSubmit() - @PutMapping("/stop") - public R stop(@Validated(EditGroup.class) @RequestBody AihumanRealConfigBo bo) { - boolean result = aihumanRealConfigService.stopByBo(bo); - if (result) { - // 运行状态 - bo.setRunStatus("0"); - return R.ok("真人交互数字人任务已停止"); - } else { - return R.fail("停止真人交互数字人任务失败或没有正在运行的任务"); - } - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanVolcengineController.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanVolcengineController.java deleted file mode 100644 index e9b3e99a..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanVolcengineController.java +++ /dev/null @@ -1,502 +0,0 @@ -package org.ruoyi.aihuman.controller; - -import cn.dev33.satoken.annotation.SaIgnore; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.ruoyi.aihuman.domain.VoiceRequest; -import org.ruoyi.aihuman.protocol.EventType; -import org.ruoyi.aihuman.protocol.Message; -import org.ruoyi.aihuman.protocol.MsgType; -import org.ruoyi.aihuman.protocol.SpeechWebSocketClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.ResourceLoader; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/** - * 火山引擎相关接口 - * - * @author ruoyi - */ -// 临时免登录 -@SaIgnore - -@Validated -@RequiredArgsConstructor -@Slf4j -@RestController -@RequestMapping("/aihuman/volcengine") -public class AihumanVolcengineController { - - private static final ObjectMapper objectMapper = new ObjectMapper(); - private static final Logger logger = LoggerFactory.getLogger(AihumanVolcengineController.class); - @Autowired - private ResourceLoader resourceLoader; - - @PostMapping("/generate-voice-direct") - public ResponseEntity generateVoiceDirect(@RequestBody VoiceRequest request) { - try { - // 生成唯一的语音ID - String voiceId = UUID.randomUUID().toString().replace("-", ""); - - log.info("开始生成语音,voiceId: {}", voiceId); - - // 调用火山引擎TTS API获取音频数据 - byte[] audioData = generateVoiceData(request, voiceId); - - // 设置响应头,返回音频数据 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.parseMediaType("audio/wav")); - headers.setContentDispositionFormData("attachment", "voice_" + System.currentTimeMillis() + ".wav"); - headers.setContentLength(audioData.length); - - log.info("语音生成成功并返回,长度: {} bytes", audioData.length); - return new ResponseEntity<>(audioData, headers, HttpStatus.OK); - } catch (Exception e) { - log.error("生成语音失败", e); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - private byte[] generateVoiceData(VoiceRequest request, String voiceId) { - try { - // 这里是调用火山引擎TTS API的核心逻辑 - // 您需要根据火山引擎的API文档实现具体的调用逻辑 - // 注意:这只是一个示例框架,您需要根据实际情况进行实现 - - // 调用火山引擎API并获取音频数据 - // 假设您已经有现有的调用逻辑,这里保留原有的实现 - String endpoint = request.getEndpoint(); - String appId = request.getAppId(); - String accessToken = request.getAccessToken(); - String resourceId = request.getResourceId(); - String voice = request.getVoice(); - String text = request.getText(); - String encoding = request.getEncoding(); - - // 调用原有的火山引擎API调用方法(如果有) - // 或者直接在这里实现API调用逻辑 - byte[] audioData = callVolcengineTtsApiByte(endpoint, appId, accessToken, - resourceId, voice, text, encoding); - - log.info("成功生成语音数据,大小: {} bytes", audioData.length); - return audioData; - } catch (Exception e) { - log.error("生成语音数据失败", e); - throw new RuntimeException("生成语音数据失败", e); - } - - } - - private byte[] callVolcengineTtsApiByte(String endpoint, String appId, String accessToken, - String resourceId, String voice, String text, String encoding) { - try { - // 确保resourceId不为空,如果为空则根据voice类型获取默认值 - if (resourceId == null || resourceId.isEmpty()) { - resourceId = voiceToResourceId(voice); - } - - // 设置请求头 - Map headers = new HashMap<>(); - headers.put("X-Api-App-Key", appId); - headers.put("X-Api-Access-Key", accessToken); - headers.put("X-Api-Resource-Id", resourceId); - headers.put("X-Api-Connect-Id", UUID.randomUUID().toString()); - - // 创建WebSocket客户端 - SpeechWebSocketClient client = new SpeechWebSocketClient(new URI(endpoint), headers); - ByteArrayOutputStream totalAudioStream = new ByteArrayOutputStream(); - boolean audioReceived = false; - - try { - // 连接WebSocket - client.connectBlocking(); - - // 构建请求参数 - Map request = new HashMap<>(); - request.put("user", Map.of("uid", UUID.randomUUID().toString())); - request.put("namespace", "BidirectionalTTS"); - - Map reqParams = new HashMap<>(); - reqParams.put("speaker", voice); - - Map audioParams = new HashMap<>(); - audioParams.put("format", encoding); - audioParams.put("sample_rate", 24000); - audioParams.put("enable_timestamp", true); - - reqParams.put("audio_params", audioParams); - reqParams.put("additions", objectMapper.writeValueAsString(Map.of("disable_markdown_filter", false))); - - request.put("req_params", reqParams); - - // 开始连接 - client.sendStartConnection(); - // 等待连接成功 - client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.CONNECTION_STARTED); - - // 处理每个句子 - String[] sentences = text.split("。"); - for (int i = 0; i < sentences.length; i++) { - if (sentences[i].trim().isEmpty()) { - continue; - } - - String sessionId = UUID.randomUUID().toString(); - ByteArrayOutputStream sentenceAudioStream = new ByteArrayOutputStream(); - - // 开始会话 - Map startReq = new HashMap<>(); - startReq.put("user", request.get("user")); - startReq.put("namespace", request.get("namespace")); - startReq.put("req_params", request.get("req_params")); - startReq.put("event", EventType.START_SESSION.getValue()); - client.sendStartSession(objectMapper.writeValueAsBytes(startReq), sessionId); - // 等待会话开始 - client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.SESSION_STARTED); - - // 发送文本内容 - for (char c : sentences[i].toCharArray()) { - @SuppressWarnings("unchecked") - Map currentReqParams = new HashMap<>((Map) request.get("req_params")); - currentReqParams.put("text", String.valueOf(c)); - - Map currentRequest = new HashMap<>(); - currentRequest.put("user", request.get("user")); - currentRequest.put("namespace", request.get("namespace")); - currentRequest.put("req_params", currentReqParams); - currentRequest.put("event", EventType.TASK_REQUEST.getValue()); - - client.sendTaskRequest(objectMapper.writeValueAsBytes(currentRequest), sessionId); - } - - // 结束会话 - client.sendFinishSession(sessionId); - - // 接收响应 - while (true) { - Message msg = client.receiveMessage(); - switch (msg.getType()) { - case FULL_SERVER_RESPONSE: - break; - case AUDIO_ONLY_SERVER: - if (!audioReceived && sentenceAudioStream.size() > 0) { - audioReceived = true; - } - if (msg.getPayload() != null) { - sentenceAudioStream.write(msg.getPayload()); - } - break; - default: - // 不抛出异常,记录日志并继续处理 - log.warn("Unexpected message type: {}", msg.getType()); - } - if (msg.getEvent() == EventType.SESSION_FINISHED) { - break; - } - } - - // 将当前句子的音频追加到总音频流 - if (sentenceAudioStream.size() > 0) { - totalAudioStream.write(sentenceAudioStream.toByteArray()); - } - } - - // 验证是否收到音频数据 - if (totalAudioStream.size() > 0) { - log.info("Audio data generated successfully, size: {} bytes", totalAudioStream.size()); - return totalAudioStream.toByteArray(); - } else { - throw new RuntimeException("No audio data received"); - } - } finally { - // 结束连接 - client.sendFinishConnection(); - client.closeBlocking(); - } - } catch (Exception e) { - log.error("Error calling Volcengine TTS API: {}", e.getMessage(), e); - throw new RuntimeException("Failed to generate voice", e); - } - } - - - /** - * 生成语音文件接口 - * 用户传入JSON参数,返回音频文件的播放地址 - */ - @PostMapping("/generate-voice") - public ResponseEntity generateVoice(@RequestBody VoiceRequest request) { - try { - // 1. 解析请求参数 - String endpoint = request.getEndpoint(); - String appId = request.getAppId(); - String accessToken = request.getAccessToken(); - String resourceId = request.getResourceId(); - String voice = request.getVoice(); - String text = request.getText(); - String encoding = request.getEncoding(); - - // 1.1 验证必要参数 - if (endpoint == null || endpoint.isEmpty()) { - return ResponseEntity.badRequest().body(Map.of("error", "endpoint cannot be null or empty")); - } - if (appId == null || appId.isEmpty()) { - return ResponseEntity.badRequest().body(Map.of("error", "appId cannot be null or empty")); - } - if (accessToken == null || accessToken.isEmpty()) { - return ResponseEntity.badRequest().body(Map.of("error", "accessToken cannot be null or empty")); - } - if (text == null || text.isEmpty()) { - return ResponseEntity.badRequest().body(Map.of("error", "text cannot be null or empty")); - } - - // 1.2 设置默认值 - if (encoding == null || encoding.isEmpty()) { - encoding = "mp3"; - } - - // 2. 调用火山引擎API生成音频文件 - String audioUrl = callVolcengineTtsApi(endpoint, appId, accessToken, resourceId, voice, text, encoding); - - // 3. 构造并返回响应 - Map response = new HashMap<>(); - response.put("audioUrl", audioUrl); - - return ResponseEntity.ok(response); - } catch (Exception e) { - // 处理异常情况 - Map errorResponse = new HashMap<>(); - errorResponse.put("error", "生成音频文件失败: " + e.getMessage()); - return ResponseEntity.status(500).body(errorResponse); - } - } - - /** - * 调用火山引擎TTS API生成音频文件 - */ - private String callVolcengineTtsApi(String endpoint, String appId, String accessToken, - String resourceId, String voice, String text, String encoding) { - try { - // 确保resourceId不为空,如果为空则根据voice类型获取默认值 - if (resourceId == null || resourceId.isEmpty()) { - resourceId = voiceToResourceId(voice); - } - - // 生成唯一的文件名 - String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); - String randomId = UUID.randomUUID().toString().substring(0, 8); - String fileName = "voice_" + timestamp + "_" + randomId + "." + encoding; - - // 获取resources/voice目录路径 - String voiceDirPath = getVoiceDirectoryPath(); - File voiceDir = new File(voiceDirPath); - if (!voiceDir.exists()) { - voiceDir.mkdirs(); - } - - String filePath = voiceDirPath + File.separator + fileName; - - // 设置请求头 - Map headers = new HashMap<>(); - headers.put("X-Api-App-Key", appId); - headers.put("X-Api-Access-Key", accessToken); - headers.put("X-Api-Resource-Id", resourceId); - headers.put("X-Api-Connect-Id", UUID.randomUUID().toString()); - - // 创建WebSocket客户端 - SpeechWebSocketClient client = new SpeechWebSocketClient(new URI(endpoint), headers); - ByteArrayOutputStream totalAudioStream = new ByteArrayOutputStream(); - boolean audioReceived = false; - - try { - // 连接WebSocket - client.connectBlocking(); - - // 构建请求参数 - Map request = new HashMap<>(); - request.put("user", Map.of("uid", UUID.randomUUID().toString())); - request.put("namespace", "BidirectionalTTS"); - - Map reqParams = new HashMap<>(); - reqParams.put("speaker", voice); - - Map audioParams = new HashMap<>(); - audioParams.put("format", encoding); - audioParams.put("sample_rate", 24000); - audioParams.put("enable_timestamp", true); - - reqParams.put("audio_params", audioParams); - reqParams.put("additions", objectMapper.writeValueAsString(Map.of("disable_markdown_filter", false))); - - request.put("req_params", reqParams); - - // 开始连接 - client.sendStartConnection(); - // 等待连接成功 - client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.CONNECTION_STARTED); - - // 处理每个句子 - String[] sentences = text.split("。"); - for (int i = 0; i < sentences.length; i++) { - if (sentences[i].trim().isEmpty()) { - continue; - } - - String sessionId = UUID.randomUUID().toString(); - ByteArrayOutputStream sentenceAudioStream = new ByteArrayOutputStream(); - - // 开始会话 - Map startReq = new HashMap<>(); - startReq.put("user", request.get("user")); - startReq.put("namespace", request.get("namespace")); - startReq.put("req_params", request.get("req_params")); - startReq.put("event", EventType.START_SESSION.getValue()); - client.sendStartSession(objectMapper.writeValueAsBytes(startReq), sessionId); - // 等待会话开始 - client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.SESSION_STARTED); - - // 发送文本内容 - for (char c : sentences[i].toCharArray()) { - @SuppressWarnings("unchecked") - Map currentReqParams = new HashMap<>((Map) request.get("req_params")); - currentReqParams.put("text", String.valueOf(c)); - - Map currentRequest = new HashMap<>(); - currentRequest.put("user", request.get("user")); - currentRequest.put("namespace", request.get("namespace")); - currentRequest.put("req_params", currentReqParams); - currentRequest.put("event", EventType.TASK_REQUEST.getValue()); - - client.sendTaskRequest(objectMapper.writeValueAsBytes(currentRequest), sessionId); - } - - // 结束会话 - client.sendFinishSession(sessionId); - - // 接收响应 - while (true) { - Message msg = client.receiveMessage(); - switch (msg.getType()) { - case FULL_SERVER_RESPONSE: - break; - case AUDIO_ONLY_SERVER: - if (!audioReceived && sentenceAudioStream.size() > 0) { - audioReceived = true; - } - if (msg.getPayload() != null) { - sentenceAudioStream.write(msg.getPayload()); - } - break; - default: - // 不抛出异常,记录日志并继续处理 - log.warn("Unexpected message type: {}", msg.getType()); - } - if (msg.getEvent() == EventType.SESSION_FINISHED) { - break; - } - } - - // 将当前句子的音频追加到总音频流 - if (sentenceAudioStream.size() > 0) { - totalAudioStream.write(sentenceAudioStream.toByteArray()); - } - } - - // 保存音频文件 - if (totalAudioStream.size() > 0) { - Files.write(Paths.get(filePath), totalAudioStream.toByteArray(), StandardOpenOption.CREATE); - log.info("Audio saved to file: {}", filePath); - } else { - throw new RuntimeException("No audio data received"); - } - - // 结束连接 - client.sendFinishConnection(); - } finally { - client.closeBlocking(); - } - - // 返回音频文件的访问路径 - return "/voice/" + fileName; - } catch (Exception e) { - log.error("Error calling Volcengine TTS API: {}", e.getMessage(), e); - throw new RuntimeException("Failed to generate voice", e); - } - } - - /** - * 根据voice类型获取resourceId - */ - private String voiceToResourceId(String voice) { - if (voice != null && voice.startsWith("S_")) { - return "volc.megatts.default"; - } - return "volc.service_type.10029"; - } - - /** - * 获取voice目录路径 - */ - private String getVoiceDirectoryPath() { - try { - // 获取当前项目根目录 - String projectRoot = System.getProperty("user.dir"); - - // 构建目标目录路径:ruoyi-ai/ruoyi-modules/ruoyi-aihuman/src/main/resources/voice - File targetDir = new File(projectRoot, "ruoyi-modules/ruoyi-aihuman/src/main/resources/voice"); - - // 确保目录存在 - if (!targetDir.exists()) { - boolean created = targetDir.mkdirs(); - if (created) { - logger.info("成功创建目录: {}", targetDir.getAbsolutePath()); - } else { - logger.warn("无法创建目录: {}", targetDir.getAbsolutePath()); - - // 降级方案:直接使用项目根目录下的voice文件夹 - File fallbackDir = new File(projectRoot, "voice"); - if (!fallbackDir.exists()) { - fallbackDir.mkdirs(); - } - return fallbackDir.getAbsolutePath(); - } - } - - return targetDir.getAbsolutePath(); - } catch (Exception e) { - logger.error("获取音频目录路径失败", e); - - // 异常情况下的安全降级 - File safeDir = new File("voice"); - if (!safeDir.exists()) { - safeDir.mkdirs(); - } - return safeDir.getAbsolutePath(); - } - } -} - - diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanConfig.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanConfig.java deleted file mode 100644 index 5e9fadbb..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanConfig.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.ruoyi.aihuman.domain; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 交互数字人配置对象 aihuman_config - * - * @author ageerle - * @date Fri Sep 26 22:27:00 GMT+08:00 2025 - */ -@Data -@TableName("aihuman_config") -public class AihumanConfig implements Serializable { - - - /** - * id - */ - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - /** - * name - */ - private String name; - - /** - * modelName - */ - private String modelName; - - /** - * modelPath - */ - private String modelPath; - - /** - * modelParams - */ - private String modelParams; - - /** - * agentParams - */ - private String agentParams; - - /** - * createTime - */ - private LocalDateTime createTime; - - /** - * updateTime - */ - private LocalDateTime updateTime; - - /** - * status - */ - private Integer status; - - /** - * publish - */ - private Integer publish; - - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanInfo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanInfo.java deleted file mode 100644 index 9be681f2..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanInfo.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.ruoyi.aihuman.domain; - -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; - -import java.io.Serializable; -import java.util.Date; - -/** - * AI人类交互信息实体类 - * - * @author QingYunAI - */ -@Data -@TableName("aihuman_info") -public class AihumanInfo implements Serializable { - private static final long serialVersionUID = 1L; - - /** - * 主键ID - */ - @TableId(value = "id", type = IdType.AUTO) - private Long id; - - /** - * 交互名称 - */ - private String name; - - /** - * 交互内容 - */ - private String content; - - /** - * 创建时间 - */ - @TableField(fill = FieldFill.INSERT) - private Date createTime; - - /** - * 更新时间 - */ - @TableField(fill = FieldFill.INSERT_UPDATE) - private Date updateTime; - - /** - * 删除标志(0代表存在 2代表删除) - */ - @TableLogic - private String delFlag; -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanRealConfig.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanRealConfig.java deleted file mode 100644 index c87f9bcd..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanRealConfig.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.ruoyi.aihuman.domain; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 真人交互数字人配置对象 aihuman_real_config - * - * @author ageerle - * @date Tue Oct 21 11:46:52 GMT+08:00 2025 - */ -@Data -@TableName("aihuman_real_config") -public class AihumanRealConfig implements Serializable { - - - /** - * 主键id - */ - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - /** - * 场景名称 - */ - private String name; - - /** - * 真人形象名称 - */ - private String avatars; - - /** - * 模型名称 - */ - private String models; - - /** - * 形象参数(预留) - */ - private String avatarsParams; - - /** - * 模型参数(预留) - */ - private String modelsParams; - - /** - * 智能体参数(扣子) - */ - private String agentParams; - - /** - * 创建时间 - */ - private LocalDateTime createTime; - - /** - * 更新时间 - */ - private LocalDateTime updateTime; - - /** - * 状态 - */ - private Integer status; - - /** - * 发布状态 - */ - private Integer publish; - - /** - * 运行参数 - */ - private String runParams; - - /** - * 运行状态 - */ - private String runStatus; - - /** - * 创建部门 - */ - private String createDept; - - /** - * 创建用户 - */ - private String createBy; - - /** - * 更新用户 - */ - private String updateBy; - - -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java deleted file mode 100644 index 4ed0d017..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.ruoyi.aihuman.domain; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - - -/** - * 语音请求参数实体类 - */ -@Data -public class VoiceRequest { - - @JsonProperty("ENDPOINT") - private String endpoint; - private String appId; - private String accessToken; - private String resourceId; - private String voice; - private String text; - private String encoding; - -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanConfigBo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanConfigBo.java deleted file mode 100644 index ac9ffad0..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanConfigBo.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.ruoyi.aihuman.domain.bo; - -import io.github.linpeilie.annotations.AutoMapper; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import org.ruoyi.aihuman.domain.AihumanConfig; -import org.ruoyi.common.core.validate.AddGroup; -import org.ruoyi.common.core.validate.EditGroup; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 交互数字人配置业务对象 aihuman_config - * - * @author ageerle - * @date Fri Sep 26 22:27:00 GMT+08:00 2025 - */ -@Data - -@AutoMapper(target = AihumanConfig.class, reverseConvertGenerate = false) -public class AihumanConfigBo implements Serializable { - - private Integer id; - - /** - * name - */ - private String name; - /** - * modelName - */ - private String modelName; - /** - * modelPath - */ - private String modelPath; - /** - * modelParams - */ - private String modelParams; - /** - * agentParams - */ - private String agentParams; - /** - * createTime - */ - private LocalDateTime createTime; - /** - * updateTime - */ - private LocalDateTime updateTime; - /** - * status - */ - @NotNull(message = "status不能为空", groups = {AddGroup.class, EditGroup.class}) - private Integer status; - /** - * publish - */ - @NotNull(message = "publish不能为空", groups = {AddGroup.class, EditGroup.class}) - private Integer publish; - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanInfoBo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanInfoBo.java deleted file mode 100644 index c6e49989..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanInfoBo.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.ruoyi.aihuman.domain.bo; - -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import org.ruoyi.aihuman.domain.AihumanInfo; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 数字人信息管理业务对象 aihuman_info - * - * @author ageerle - * @date Fri Sep 26 20:03:06 GMT+08:00 2025 - */ -@Data - -@AutoMapper(target = AihumanInfo.class, reverseConvertGenerate = false) -public class AihumanInfoBo implements Serializable { - - private Long id; - - /** - * 交互名称 - */ - private String name; - /** - * 交互内容 - */ - private String content; - /** - * 创建时间 - */ - private LocalDateTime createTime; - /** - * 更新时间 - */ - private LocalDateTime updateTime; - /** - * 删除标志(0代表存在 2代表删除) - */ - private String delFlag; - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanRealConfigBo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanRealConfigBo.java deleted file mode 100644 index 2008c97c..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanRealConfigBo.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.ruoyi.aihuman.domain.bo; - -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import org.ruoyi.aihuman.domain.AihumanRealConfig; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 真人交互数字人配置业务对象 aihuman_real_config - * - * @author ageerle - * @date Tue Oct 21 11:46:52 GMT+08:00 2025 - */ -@Data - -@AutoMapper(target = AihumanRealConfig.class, reverseConvertGenerate = false) -public class AihumanRealConfigBo implements Serializable { - - private Integer id; - - /** - * 场景名称 - */ - private String name; - /** - * 真人形象名称 - */ - private String avatars; - /** - * 模型名称 - */ - private String models; - /** - * 形象参数(预留) - */ - private String avatarsParams; - /** - * 模型参数(预留) - */ - private String modelsParams; - /** - * 智能体参数(扣子) - */ - private String agentParams; - /** - * 创建时间 - */ - private LocalDateTime createTime; - /** - * 更新时间 - */ - private LocalDateTime updateTime; - /** - * 状态 - */ - private Integer status; - /** - * 发布状态 - */ - private Integer publish; - - /** - * 运行参数 - */ - private String runParams; - - /** - * 运行状态 - */ - private String runStatus; - - /** - * 创建部门 - */ - private String createDept; - /** - * 创建用户 - */ - private String createBy; - /** - * 更新用户 - */ - private String updateBy; - -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanConfigVo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanConfigVo.java deleted file mode 100644 index 93fffa76..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanConfigVo.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.ruoyi.aihuman.domain.vo; - -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import org.ruoyi.aihuman.domain.AihumanConfig; -import org.ruoyi.common.excel.annotation.ExcelDictFormat; -import org.ruoyi.common.excel.convert.ExcelDictConvert; - -import java.io.Serializable; -import java.time.LocalDateTime; - - -/** - * 交互数字人配置视图对象 aihuman_config - * - * @author ageerle - * @date Fri Sep 26 22:27:00 GMT+08:00 2025 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = AihumanConfig.class) -public class AihumanConfigVo implements Serializable { - - private Integer id; - /** - * name - */ - @ExcelProperty(value = "name") - private String name; - /** - * modelName - */ - @ExcelProperty(value = "modelName") - private String modelName; - /** - * modelPath - */ - @ExcelProperty(value = "modelPath") - private String modelPath; - /** - * modelParams - */ - @ExcelProperty(value = "modelParams") - private String modelParams; - /** - * agentParams - */ - @ExcelProperty(value = "agentParams") - private String agentParams; - /** - * createTime - */ - @ExcelProperty(value = "createTime") - private LocalDateTime createTime; - /** - * updateTime - */ - @ExcelProperty(value = "updateTime") - private LocalDateTime updateTime; - /** - * status - */ - @ExcelProperty(value = "status", converter = ExcelDictConvert.class) - @ExcelDictFormat(dictType = "sys_common_status") - private Integer status; - /** - * publish - */ - @ExcelProperty(value = "publish", converter = ExcelDictConvert.class) - @ExcelDictFormat(dictType = "sys_common_status") - private Integer publish; - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanInfoVo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanInfoVo.java deleted file mode 100644 index a36d7fbd..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanInfoVo.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.ruoyi.aihuman.domain.vo; - -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import org.ruoyi.aihuman.domain.AihumanInfo; - -import java.io.Serializable; -import java.util.Date; - -/** - * AI人类交互信息视图对象 - * - * @author QingYunAI - */ -@Data -@AutoMapper(target = AihumanInfo.class) -public class AihumanInfoVo implements Serializable { - private static final long serialVersionUID = 1L; - - /** - * 主键ID - */ - private Long id; - - /** - * 交互名称 - */ - private String name; - - /** - * 交互内容 - */ - private String content; - - /** - * 创建时间 - */ - private Date createTime; - - /** - * 更新时间 - */ - private Date updateTime; -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanRealConfigVo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanRealConfigVo.java deleted file mode 100644 index f6fe020e..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanRealConfigVo.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.ruoyi.aihuman.domain.vo; - -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import org.ruoyi.aihuman.domain.AihumanRealConfig; -import org.ruoyi.common.excel.annotation.ExcelDictFormat; -import org.ruoyi.common.excel.convert.ExcelDictConvert; - -import java.io.Serializable; -import java.time.LocalDateTime; - - -/** - * 真人交互数字人配置视图对象 aihuman_real_config - * - * @author ageerle - * @date Tue Oct 21 11:46:52 GMT+08:00 2025 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = AihumanRealConfig.class) -public class AihumanRealConfigVo implements Serializable { - - private Integer id; - /** - * 场景名称 - */ - @ExcelProperty(value = "场景名称") - private String name; - /** - * 真人形象名称 - */ - @ExcelProperty(value = "真人形象名称") - private String avatars; - /** - * 模型名称 - */ - @ExcelProperty(value = "模型名称") - private String models; - /** - * 形象参数(预留) - */ - @ExcelProperty(value = "形象参数", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "$column.readConverterExp()") - private String avatarsParams; - /** - * 模型参数(预留) - */ - @ExcelProperty(value = "模型参数", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "$column.readConverterExp()") - private String modelsParams; - /** - * 智能体参数(扣子) - */ - @ExcelProperty(value = "智能体参数", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "$column.readConverterExp()") - private String agentParams; - /** - * 创建时间 - */ - @ExcelProperty(value = "创建时间") - private LocalDateTime createTime; - /** - * 更新时间 - */ - @ExcelProperty(value = "更新时间") - private LocalDateTime updateTime; - /** - * 状态 - */ - @ExcelProperty(value = "状态") - private Integer status; - /** - * 发布状态 - */ - @ExcelProperty(value = "发布状态") - private Integer publish; - - /** - * 运行参数 - */ - @ExcelProperty(value = "运行参数") - private String runParams; - - /** - * 运行状态 - */ - @ExcelProperty(value = "运行状态") - private String runStatus; - - /** - * 创建部门 - */ - @ExcelProperty(value = "创建部门") - private String createDept; - /** - * 创建用户 - */ - @ExcelProperty(value = "创建用户") - private String createBy; - /** - * 更新用户 - */ - @ExcelProperty(value = "更新用户") - private String updateBy; - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanConfigMapper.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanConfigMapper.java deleted file mode 100644 index 3a26ef0b..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanConfigMapper.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.ruoyi.aihuman.mapper; - -import org.apache.ibatis.annotations.Mapper; -import org.ruoyi.aihuman.domain.AihumanConfig; -import org.ruoyi.aihuman.domain.vo.AihumanConfigVo; -import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 交互数字人配置Mapper接口 - * - * @author ageerle - * @date Fri Sep 26 22:27:00 GMT+08:00 2025 - */ -@Mapper -public interface AihumanConfigMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanInfoMapper.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanInfoMapper.java deleted file mode 100644 index a64d0b13..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanInfoMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.ruoyi.aihuman.mapper; - -import org.apache.ibatis.annotations.Mapper; -import org.ruoyi.aihuman.domain.AihumanInfo; -import org.ruoyi.aihuman.domain.vo.AihumanInfoVo; -import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * AI人类交互信息Mapper接口 - * - * @author QingYunAI - */ -@Mapper -public interface AihumanInfoMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanRealConfigMapper.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanRealConfigMapper.java deleted file mode 100644 index 9ae4768e..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanRealConfigMapper.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.ruoyi.aihuman.mapper; - -import org.apache.ibatis.annotations.Mapper; -import org.ruoyi.aihuman.domain.AihumanRealConfig; -import org.ruoyi.aihuman.domain.vo.AihumanRealConfigVo; -import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 真人交互数字人配置Mapper接口 - * - * @author ageerle - * @date Tue Oct 21 11:46:52 GMT+08:00 2025 - */ -@Mapper -public interface AihumanRealConfigMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java deleted file mode 100644 index 78794aa4..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Getter; - -@Getter -public enum CompressionBits { - None_((byte) 0), - Gzip((byte) 0b1), - Custom((byte) 0b11), - ; - - private final byte value; - - CompressionBits(byte b) { - this.value = b; - } - - public static CompressionBits fromValue(int value) { - for (CompressionBits type : CompressionBits.values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown CompressionBits value: " + value); - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/EventType.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/EventType.java deleted file mode 100644 index ece69af3..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/EventType.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Getter; - -@Getter -public enum EventType { - // Default event - NONE(0), - - // Upstream Connection events (1-49) - START_CONNECTION(1), - START_TASK(1), - FINISH_CONNECTION(2), - FINISH_TASK(2), - - // Downstream Connection events (50-99) - CONNECTION_STARTED(50), - TASK_STARTED(50), - CONNECTION_FAILED(51), - TASK_FAILED(51), - CONNECTION_FINISHED(52), - TASK_FINISHED(52), - - // Upstream Session events (100-149) - START_SESSION(100), - CANCEL_SESSION(101), - FINISH_SESSION(102), - - // Downstream Session events (150-199) - SESSION_STARTED(150), - SESSION_CANCELED(151), - SESSION_FINISHED(152), - SESSION_FAILED(153), - USAGE_RESPONSE(154), - CHARGE_DATA(154), - - // Upstream General events (200-249) - TASK_REQUEST(200), - UPDATE_CONFIG(201), - - // Downstream General events (250-299) - AUDIO_MUTED(250), - - // Upstream TTS events (300-349) - SAY_HELLO(300), - - // Downstream TTS events (350-399) - TTS_SENTENCE_START(350), - TTS_SENTENCE_END(351), - TTS_RESPONSE(352), - TTS_ENDED(359), - PODCAST_ROUND_START(360), - PODCAST_ROUND_RESPONSE(361), - PODCAST_ROUND_END(362), - - // Downstream ASR events (450-499) - ASR_INFO(450), - ASR_RESPONSE(451), - ASR_ENDED(459), - - // Upstream Chat events (500-549) - CHAT_TTS_TEXT(500), - - // Downstream Chat events (550-599) - CHAT_RESPONSE(550), - CHAT_ENDED(559), - - // Subtitle events (650-699) - SOURCE_SUBTITLE_START(650), - SOURCE_SUBTITLE_RESPONSE(651), - SOURCE_SUBTITLE_END(652), - TRANSLATION_SUBTITLE_START(653), - TRANSLATION_SUBTITLE_RESPONSE(654), - TRANSLATION_SUBTITLE_END(655); - - private final int value; - - EventType(int value) { - this.value = value; - } - - public static EventType fromValue(int value) { - for (EventType type : EventType.values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown EventType value: " + value); - } -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/HeaderSizeBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/HeaderSizeBits.java deleted file mode 100644 index 6c09a20d..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/HeaderSizeBits.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Getter; - -@Getter -public enum HeaderSizeBits { - HeaderSize4((byte) 1), - HeaderSize8((byte) 2), - HeaderSize12((byte) 3), - HeaderSize16((byte) 4), - ; - - private final byte value; - - HeaderSizeBits(byte b) { - this.value = b; - } - - public static HeaderSizeBits fromValue(int value) { - for (HeaderSizeBits type : HeaderSizeBits.values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown HeaderSizeBits value: " + value); - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/Message.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/Message.java deleted file mode 100644 index d3605edc..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/Message.java +++ /dev/null @@ -1,220 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Data; -import lombok.extern.slf4j.Slf4j; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; - -@Slf4j -@Data -public class Message { - private byte version = VersionBits.Version1.getValue(); - private byte headerSize = HeaderSizeBits.HeaderSize4.getValue(); - private MsgType type; - private MsgTypeFlagBits flag; - private byte serialization = SerializationBits.JSON.getValue(); - private byte compression = 0; - - private EventType event; - private String sessionId; - private String connectId; - private int sequence; - private int errorCode; - - private byte[] payload; - - public Message(MsgType type, MsgTypeFlagBits flag) { - this.type = type; - this.flag = flag; - } - - public static Message unmarshal(byte[] data) throws Exception { - ByteBuffer buffer = ByteBuffer.wrap(data); - - byte type_and_flag = data[1]; - MsgType type = MsgType.fromValue((type_and_flag >> 4) & 0x0F); - MsgTypeFlagBits flag = MsgTypeFlagBits.fromValue(type_and_flag & 0x0F); - - // Read version and header size - int versionAndHeaderSize = buffer.get(); - VersionBits version = VersionBits.fromValue((versionAndHeaderSize >> 4) & 0x0F); - HeaderSizeBits headerSize = HeaderSizeBits.fromValue(versionAndHeaderSize & 0x0F); - - // Skip second byte - buffer.get(); - - // Read serialization and compression method - int serializationCompression = buffer.get(); - SerializationBits serialization = SerializationBits.fromValue((serializationCompression >> 4) & 0x0F); - CompressionBits compression = CompressionBits.fromValue(serializationCompression & 0x0F); - - // Skip padding bytes - int headerSizeInt = 4 * (int) headerSize.getValue(); - int paddingSize = headerSizeInt - 3; - while (paddingSize > 0) { - buffer.get(); - paddingSize -= 1; - } - - Message message = new Message(type, flag); - message.setVersion(version.getValue()); - message.setHeaderSize(headerSize.getValue()); - message.setSerialization(serialization.getValue()); - message.setCompression(compression.getValue()); - - // Read sequence if present - if (flag == MsgTypeFlagBits.POSITIVE_SEQ || flag == MsgTypeFlagBits.NEGATIVE_SEQ) { - // Read 4 bytes from ByteBuffer and parse as int (big-endian) - byte[] sequeueBytes = new byte[4]; - if (buffer.remaining() >= 4) { - buffer.get(sequeueBytes); // Read 4 bytes into array - ByteBuffer wrapper = ByteBuffer.wrap(sequeueBytes); - wrapper.order(ByteOrder.BIG_ENDIAN); // Set big-endian order - message.setSequence(wrapper.getInt()); - } - } - - // Read event if present - if (flag == MsgTypeFlagBits.WITH_EVENT) { - // Read 4 bytes from ByteBuffer and parse as int (big-endian) - byte[] eventBytes = new byte[4]; - if (buffer.remaining() >= 4) { - buffer.get(eventBytes); // Read 4 bytes into array - ByteBuffer wrapper = ByteBuffer.wrap(eventBytes); - wrapper.order(ByteOrder.BIG_ENDIAN); // Set big-endian order - message.setEvent(EventType.fromValue(wrapper.getInt())); - } - - if (type != MsgType.ERROR && !(message.event == EventType.START_CONNECTION - || message.event == EventType.FINISH_CONNECTION || - message.event == EventType.CONNECTION_STARTED - || message.event == EventType.CONNECTION_FAILED || - message.event == EventType.CONNECTION_FINISHED)) { - // Read sessionId if present - int sessionIdLength = buffer.getInt(); - if (sessionIdLength > 0) { - byte[] sessionIdBytes = new byte[sessionIdLength]; - buffer.get(sessionIdBytes); - message.setSessionId(new String(sessionIdBytes, StandardCharsets.UTF_8)); - } - } - - if (message.event == EventType.CONNECTION_STARTED || message.event == EventType.CONNECTION_FAILED - || message.event == EventType.CONNECTION_FINISHED) { - // Read connectId if present - int connectIdLength = buffer.getInt(); - if (connectIdLength > 0) { - byte[] connectIdBytes = new byte[connectIdLength]; - buffer.get(connectIdBytes); - message.setConnectId(new String(connectIdBytes, StandardCharsets.UTF_8)); - } - } - } - - // Read errorCode if present - if (type == MsgType.ERROR) { - // Read 4 bytes from ByteBuffer and parse as int (big-endian) - byte[] errorCodeBytes = new byte[4]; - if (buffer.remaining() >= 4) { - buffer.get(errorCodeBytes); // Read 4 bytes into array - ByteBuffer wrapper = ByteBuffer.wrap(errorCodeBytes); - wrapper.order(ByteOrder.BIG_ENDIAN); // Set big-endian order - message.setErrorCode(wrapper.getInt()); - } - } - - // Read remaining bytes as payload - if (buffer.remaining() > 0) { - // 4 bytes length - int payloadLength = buffer.getInt(); - if (payloadLength > 0) { - byte[] payloadBytes = new byte[payloadLength]; - buffer.get(payloadBytes); - message.setPayload(payloadBytes); - } - } - - return message; - } - - public byte[] marshal() throws Exception { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - // Write header - buffer.write((version & 0x0F) << 4 | (headerSize & 0x0F)); - buffer.write((type.getValue() & 0x0F) << 4 | (flag.getValue() & 0x0F)); - buffer.write((serialization & 0x0F) << 4 | (compression & 0x0F)); - - int headerSizeInt = 4 * (int) headerSize; - int padding = headerSizeInt - buffer.size(); - while (padding > 0) { - buffer.write(0); - padding -= 1; - } - - // Write event if present - if (event != null) { - byte[] eventBytes = ByteBuffer.allocate(4).putInt(event.getValue()).array(); - buffer.write(eventBytes); - } - - // Write sessionId if present - if (sessionId != null) { - byte[] sessionIdBytes = sessionId.getBytes(StandardCharsets.UTF_8); - buffer.write(ByteBuffer.allocate(4).putInt(sessionIdBytes.length).array()); - buffer.write(sessionIdBytes); - } - - // Write connectId if present - if (connectId != null) { - byte[] connectIdBytes = connectId.getBytes(StandardCharsets.UTF_8); - buffer.write(ByteBuffer.allocate(4).putInt(connectIdBytes.length).array()); - buffer.write(connectIdBytes); - } - - // Write sequence if present - if (sequence != 0) { - buffer.write(ByteBuffer.allocate(4).putInt(sequence).array()); - } - - // Write errorCode if present - if (errorCode != 0) { - buffer.write(ByteBuffer.allocate(4).putInt(errorCode).array()); - } - - // Write payload if present - if (payload != null && payload.length > 0) { - buffer.write(ByteBuffer.allocate(4).putInt(payload.length).array()); - buffer.write(payload); - } - return buffer.toByteArray(); - } - - @Override - public String toString() { - switch (this.type) { - case AUDIO_ONLY_SERVER: - case AUDIO_ONLY_CLIENT: - if (this.flag == MsgTypeFlagBits.POSITIVE_SEQ || this.flag == MsgTypeFlagBits.NEGATIVE_SEQ) { - return String.format("MsgType: %s, EventType: %s, Sequence: %d, PayloadSize: %d", this.type, this.event, this.sequence, - this.payload != null ? this.payload.length : 0); - } - return String.format("MsgType: %s, EventType: %s, PayloadSize: %d", this.type, this.event, - this.payload != null ? this.payload.length : 0); - case ERROR: - return String.format("MsgType: %s, EventType: %s, ErrorCode: %d, Payload: %s", this.type, this.event, this.errorCode, - this.payload != null ? new String(this.payload) : "null"); - default: - if (this.flag == MsgTypeFlagBits.POSITIVE_SEQ || this.flag == MsgTypeFlagBits.NEGATIVE_SEQ) { - return String.format("MsgType: %s, EventType: %s, Sequence: %d, Payload: %s", - this.type, this.event, this.sequence, - this.payload != null ? new String(this.payload) : "null"); - } - return String.format("MsgType: %s, EventType: %s, Payload: %s", this.type, this.event, - this.payload != null ? new String(this.payload) : "null"); - } - } -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgType.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgType.java deleted file mode 100644 index 965f40e8..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgType.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Getter; - -@Getter -public enum MsgType { - INVALID((byte) 0), - FULL_CLIENT_REQUEST((byte) 0b1), - AUDIO_ONLY_CLIENT((byte) 0b10), - FULL_SERVER_RESPONSE((byte) 0b1001), - AUDIO_ONLY_SERVER((byte) 0b1011), - FRONT_END_RESULT_SERVER((byte) 0b1100), - ERROR((byte) 0b1111); - - private final byte value; - - MsgType(byte value) { - this.value = value; - } - - public static MsgType fromValue(int value) { - for (MsgType type : MsgType.values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown MsgType value: " + value); - } -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgTypeFlagBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgTypeFlagBits.java deleted file mode 100644 index 393a24dc..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgTypeFlagBits.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Getter; - -@Getter -public enum MsgTypeFlagBits { - NO_SEQ((byte) 0), // Non-terminating packet without sequence number - POSITIVE_SEQ((byte) 0b1), // Non-terminating packet with positive sequence number - LAST_NO_SEQ((byte) 0b10), // Terminating packet without sequence number - NEGATIVE_SEQ((byte) 0b11), // Terminating packet with negative sequence number - WITH_EVENT((byte) 0b100); // Packet containing event number - - private final byte value; - - MsgTypeFlagBits(byte value) { - this.value = value; - } - - public static MsgTypeFlagBits fromValue(int value) { - for (MsgTypeFlagBits flag : MsgTypeFlagBits.values()) { - if (flag.value == value) { - return flag; - } - } - throw new IllegalArgumentException("Unknown MsgTypeFlagBits value: " + value); - } -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SerializationBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SerializationBits.java deleted file mode 100644 index 01e8f102..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SerializationBits.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Getter; - -@Getter -public enum SerializationBits { - Raw((byte) 0), - JSON((byte) 0b1), - Thrift((byte) 0b11), - Custom((byte) 0b1111), - ; - - private final byte value; - - SerializationBits(byte b) { - this.value = b; - } - - public static SerializationBits fromValue(int value) { - for (SerializationBits type : SerializationBits.values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown SerializationBits value: " + value); - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SpeechWebSocketClient.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SpeechWebSocketClient.java deleted file mode 100644 index c41e57b3..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SpeechWebSocketClient.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.extern.slf4j.Slf4j; -import org.java_websocket.client.WebSocketClient; -import org.java_websocket.handshake.ServerHandshake; - -import java.net.URI; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -@Slf4j -public class SpeechWebSocketClient extends WebSocketClient { - private final BlockingQueue messageQueue = new LinkedBlockingQueue<>(); - - public SpeechWebSocketClient(URI serverUri, Map headers) { - super(serverUri, headers); - } - - @Override - public void onOpen(ServerHandshake handshakedata) { - log.info("WebSocket connection established, Logid: {}", handshakedata.getFieldValue("x-tt-logid")); - } - - @Override - public void onMessage(String message) { - log.warn("Received unexpected text message: {}", message); - } - - @Override - public void onMessage(ByteBuffer bytes) { - try { - Message message = Message.unmarshal(bytes.array()); - messageQueue.put(message); - } catch (Exception e) { - log.error("Failed to parse message", e); - } - } - - @Override - public void onClose(int code, String reason, boolean remote) { - log.info("WebSocket connection closed: code={}, reason={}, remote={}", code, reason, remote); - } - - @Override - public void onError(Exception ex) { - log.error("WebSocket error", ex); - } - - public void sendStartConnection() throws Exception { - Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT); - message.setEvent(EventType.START_CONNECTION); - message.setPayload("{}".getBytes()); - sendMessage(message); - } - - public void sendFinishConnection() throws Exception { - Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT); - message.setEvent(EventType.FINISH_CONNECTION); - sendMessage(message); - } - - public void sendStartSession(byte[] payload, String sessionId) throws Exception { - Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT); - message.setEvent(EventType.START_SESSION); - message.setSessionId(sessionId); - message.setPayload(payload); - sendMessage(message); - } - - public void sendFinishSession(String sessionId) throws Exception { - Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT); - message.setEvent(EventType.FINISH_SESSION); - message.setSessionId(sessionId); - message.setPayload("{}".getBytes()); - sendMessage(message); - } - - public void sendTaskRequest(byte[] payload, String sessionId) throws Exception { - Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT); - message.setEvent(EventType.TASK_REQUEST); - message.setSessionId(sessionId); - message.setPayload(payload); - sendMessage(message); - } - - public void sendFullClientMessage(byte[] payload) throws Exception { - Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.NO_SEQ); - message.setPayload(payload); - sendMessage(message); - } - - public void sendMessage(Message message) throws Exception { - log.info("Send: {}", message); - send(message.marshal()); - } - - public Message receiveMessage() throws InterruptedException { - Message message = messageQueue.take(); - log.info("Receive: {}", message); - return message; - } - - public Message waitForMessage(MsgType type, EventType event) throws InterruptedException { - while (true) { - Message message = receiveMessage(); - if (message.getType() == type && message.getEvent() == event) { - return message; - } else { - throw new RuntimeException("Unexpected message: " + message); - } - } - } -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/VersionBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/VersionBits.java deleted file mode 100644 index 6f4a8174..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/VersionBits.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.ruoyi.aihuman.protocol; - -import lombok.Getter; - -@Getter -public enum VersionBits { - Version1((byte) 1), - Version2((byte) 2), - Version3((byte) 3), - Version4((byte) 4), - ; - - private final byte value; - - VersionBits(byte b) { - this.value = b; - } - - public static VersionBits fromValue(int value) { - for (VersionBits type : VersionBits.values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown VersionBits value: " + value); - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanConfigService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanConfigService.java deleted file mode 100644 index b70367cb..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanConfigService.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.ruoyi.aihuman.service; - -import org.ruoyi.aihuman.domain.bo.AihumanConfigBo; -import org.ruoyi.aihuman.domain.vo.AihumanConfigVo; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; - -import java.util.Collection; -import java.util.List; - -/** - * 交互数字人配置Service接口 - * - * @author ageerle - * @date Fri Sep 26 22:27:00 GMT+08:00 2025 - */ -public interface AihumanConfigService { - - /** - * 查询交互数字人配置 - */ - AihumanConfigVo queryById(Integer id); - - /** - * 查询交互数字人配置列表 - */ - TableDataInfo queryPageList(AihumanConfigBo bo, PageQuery pageQuery); - - /** - * 查询交互数字人配置列表 - */ - List queryList(AihumanConfigBo bo); - - /** - * 新增交互数字人配置 - */ - Boolean insertByBo(AihumanConfigBo bo); - - /** - * 修改交互数字人配置 - */ - Boolean updateByBo(AihumanConfigBo bo); - - /** - * 校验并批量删除交互数字人配置信息 - */ - Boolean deleteWithValidByIds(Collection ids, Boolean isValid); -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanRealConfigService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanRealConfigService.java deleted file mode 100644 index 56398190..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanRealConfigService.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.ruoyi.aihuman.service; - -import org.ruoyi.aihuman.domain.bo.AihumanRealConfigBo; -import org.ruoyi.aihuman.domain.vo.AihumanRealConfigVo; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; - -import java.util.Collection; -import java.util.List; - -/** - * 真人交互数字人配置Service接口 - * - * @author ageerle - * @date Tue Oct 21 11:46:52 GMT+08:00 2025 - */ -public interface AihumanRealConfigService { - - /** - * 查询真人交互数字人配置 - */ - AihumanRealConfigVo queryById(Integer id); - - /** - * 查询真人交互数字人配置列表 - */ - TableDataInfo queryPageList(AihumanRealConfigBo bo, PageQuery pageQuery); - - /** - * 查询真人交互数字人配置列表 - */ - List queryList(AihumanRealConfigBo bo); - - /** - * 新增真人交互数字人配置 - */ - Boolean insertByBo(AihumanRealConfigBo bo); - - /** - * 修改真人交互数字人配置 - */ - Boolean updateByBo(AihumanRealConfigBo bo); - - /** - * 执行真人交互数字人配置 - */ - Boolean runByBo(AihumanRealConfigBo bo); - - /** - * 校验并批量删除真人交互数字人配置信息 - */ - Boolean deleteWithValidByIds(Collection ids, Boolean isValid); - - // 在AihumanRealConfigService接口中添加 - Boolean stopByBo(AihumanRealConfigBo bo); -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanVolcengineService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanVolcengineService.java deleted file mode 100644 index 6c99f013..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanVolcengineService.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.ruoyi.aihuman.service; - -public interface AihumanVolcengineService { -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/IAihumanInfoService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/IAihumanInfoService.java deleted file mode 100644 index a07001d6..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/IAihumanInfoService.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.ruoyi.aihuman.service; - -import org.ruoyi.aihuman.domain.AihumanInfo; -import org.ruoyi.aihuman.domain.vo.AihumanInfoVo; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; - -import java.util.Collection; -import java.util.List; - -/** - * AI人类交互信息Service接口 - * - * @author QingYunAI - */ -public interface IAihumanInfoService { - - /** - * 查询AI人类交互信息 - */ - AihumanInfoVo queryById(Long id); - - /** - * 查询AI人类交互信息列表 - */ - TableDataInfo queryPageList(AihumanInfo record, PageQuery pageQuery); - - /** - * 查询AI人类交互信息列表 - */ - List queryList(AihumanInfo record); - - /** - * 新增AI人类交互信息 - */ - int insert(AihumanInfo record); - - /** - * 修改AI人类交互信息 - */ - int update(AihumanInfo record); - - /** - * 批量删除AI人类交互信息 - */ - int deleteWithValidByIds(Collection ids, Boolean isValid); -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanConfigServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanConfigServiceImpl.java deleted file mode 100644 index 6031d692..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanConfigServiceImpl.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.ruoyi.aihuman.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.RequiredArgsConstructor; -import org.ruoyi.aihuman.domain.AihumanConfig; -import org.ruoyi.aihuman.domain.bo.AihumanConfigBo; -import org.ruoyi.aihuman.domain.vo.AihumanConfigVo; -import org.ruoyi.aihuman.mapper.AihumanConfigMapper; -import org.ruoyi.aihuman.service.AihumanConfigService; -import org.ruoyi.common.core.utils.MapstructUtils; -import org.ruoyi.common.core.utils.StringUtils; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; -import org.springframework.stereotype.Service; - -import java.util.Collection; -import java.util.List; - -/** - * 交互数字人配置Service业务层处理 - * - * @author ageerle - * @date Fri Sep 26 22:27:00 GMT+08:00 2025 - */ -@RequiredArgsConstructor -@Service -public class AihumanConfigServiceImpl implements AihumanConfigService { - - private final AihumanConfigMapper baseMapper; - - /** - * 查询交互数字人配置 - */ - @Override - public AihumanConfigVo queryById(Integer id) { - return baseMapper.selectVoById(id); - } - - /** - * 查询交互数字人配置列表 - */ - @Override - public TableDataInfo queryPageList(AihumanConfigBo bo, PageQuery pageQuery) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); - return TableDataInfo.build(result); - } - - /** - * 查询交互数字人配置列表 - */ - @Override - public List queryList(AihumanConfigBo bo) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); - } - - private LambdaQueryWrapper buildQueryWrapper(AihumanConfigBo bo) { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.eq(StringUtils.isNotBlank(bo.getName()), AihumanConfig::getName, bo.getName()); - lqw.eq(StringUtils.isNotBlank(bo.getModelName()), AihumanConfig::getModelName, bo.getModelName()); - lqw.eq(StringUtils.isNotBlank(bo.getModelPath()), AihumanConfig::getModelPath, bo.getModelPath()); - lqw.eq(StringUtils.isNotBlank(bo.getModelParams()), AihumanConfig::getModelParams, bo.getModelParams()); - lqw.eq(StringUtils.isNotBlank(bo.getAgentParams()), AihumanConfig::getAgentParams, bo.getAgentParams()); - lqw.eq(bo.getCreateTime() != null, AihumanConfig::getCreateTime, bo.getCreateTime()); - lqw.eq(bo.getUpdateTime() != null, AihumanConfig::getUpdateTime, bo.getUpdateTime()); - lqw.eq(bo.getStatus() != null, AihumanConfig::getStatus, bo.getStatus()); - lqw.eq(bo.getPublish() != null, AihumanConfig::getPublish, bo.getPublish()); - return lqw; - } - - /** - * 新增交互数字人配置 - */ - @Override - public Boolean insertByBo(AihumanConfigBo bo) { - AihumanConfig add = MapstructUtils.convert(bo, AihumanConfig.class); - validEntityBeforeSave(add); - boolean flag = baseMapper.insert(add) > 0; - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 修改交互数字人配置 - */ - @Override - public Boolean updateByBo(AihumanConfigBo bo) { - AihumanConfig update = MapstructUtils.convert(bo, AihumanConfig.class); - validEntityBeforeSave(update); - return baseMapper.updateById(update) > 0; - } - - /** - * 保存前的数据校验 - */ - private void validEntityBeforeSave(AihumanConfig entity) { - //TODO 做一些数据校验,如唯一约束 - } - - /** - * 批量删除交互数字人配置 - */ - @Override - public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { - if (isValid) { - //TODO 做一些业务上的校验,判断是否需要校验 - } - return baseMapper.deleteBatchIds(ids) > 0; - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanInfoServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanInfoServiceImpl.java deleted file mode 100644 index dd5e8a9c..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanInfoServiceImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.ruoyi.aihuman.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.RequiredArgsConstructor; -import org.ruoyi.aihuman.domain.AihumanInfo; -import org.ruoyi.aihuman.domain.vo.AihumanInfoVo; -import org.ruoyi.aihuman.mapper.AihumanInfoMapper; -import org.ruoyi.aihuman.service.IAihumanInfoService; -import org.ruoyi.common.core.utils.StringUtils; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; -import org.springframework.stereotype.Service; - -import java.util.Collection; -import java.util.List; - -/** - * AI人类交互信息Service业务层处理 - * - * @author QingYunAI - */ -@RequiredArgsConstructor -@Service -public class AihumanInfoServiceImpl implements IAihumanInfoService { - - private final AihumanInfoMapper baseMapper; - - /** - * 查询AI人类交互信息 - */ - @Override - public AihumanInfoVo queryById(Long id) { - return baseMapper.selectVoById(id); - } - - /** - * 查询AI人类交互信息列表 - */ - @Override - public TableDataInfo queryPageList(AihumanInfo record, PageQuery pageQuery) { - LambdaQueryWrapper lqw = buildQueryWrapper(record); - Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); - return TableDataInfo.build(result); - } - - /** - * 查询AI人类交互信息列表 - */ - @Override - public List queryList(AihumanInfo record) { - LambdaQueryWrapper lqw = buildQueryWrapper(record); - return baseMapper.selectVoList(lqw); - } - - /** - * 构建查询条件 - */ - private LambdaQueryWrapper buildQueryWrapper(AihumanInfo record) { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.eq(record.getId() != null, AihumanInfo::getId, record.getId()); - lqw.like(StringUtils.isNotBlank(record.getName()), AihumanInfo::getName, record.getName()); - lqw.like(StringUtils.isNotBlank(record.getContent()), AihumanInfo::getContent, record.getContent()); - lqw.orderByDesc(AihumanInfo::getCreateTime); - return lqw; - } - - /** - * 新增AI人类交互信息 - */ - @Override - public int insert(AihumanInfo record) { - return baseMapper.insert(record); - } - - /** - * 修改AI人类交互信息 - */ - @Override - public int update(AihumanInfo record) { - return baseMapper.updateById(record); - } - - /** - * 批量删除AI人类交互信息 - */ - @Override - public int deleteWithValidByIds(Collection ids, Boolean isValid) { - if (isValid) { - // 如果需要逻辑删除,MyBatis-Plus会自动处理 - // 这里的@TableLogic注解已经在实体类中配置 - } - return baseMapper.deleteBatchIds(ids); - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanRealConfigServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanRealConfigServiceImpl.java deleted file mode 100644 index 2b162e1c..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanRealConfigServiceImpl.java +++ /dev/null @@ -1,534 +0,0 @@ -package org.ruoyi.aihuman.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.sun.jna.Library; -import com.sun.jna.Native; -import com.sun.jna.Pointer; -import com.sun.jna.platform.win32.WinNT; -import jakarta.annotation.PreDestroy; -import lombok.RequiredArgsConstructor; -import org.ruoyi.aihuman.domain.AihumanRealConfig; -import org.ruoyi.aihuman.domain.bo.AihumanRealConfigBo; -import org.ruoyi.aihuman.domain.vo.AihumanRealConfigVo; -import org.ruoyi.aihuman.mapper.AihumanRealConfigMapper; -import org.ruoyi.aihuman.service.AihumanRealConfigService; -import org.ruoyi.common.core.utils.MapstructUtils; -import org.ruoyi.common.core.utils.StringUtils; -import org.ruoyi.common.mybatis.core.page.PageQuery; -import org.ruoyi.common.mybatis.core.page.TableDataInfo; -import org.ruoyi.common.redis.utils.RedisUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -/** - * 真人交互数字人配置Service业务层处理 - * - * @author ageerle - * @date Tue Oct 21 11:46:52 GMT+08:00 2025 - */ -@RequiredArgsConstructor -@Service -public class AihumanRealConfigServiceImpl implements AihumanRealConfigService { - - private static final Logger log = LoggerFactory.getLogger(AihumanRealConfigServiceImpl.class); - private final AihumanRealConfigMapper baseMapper; - // 存储当前运行的进程,用于停止操作 - private volatile Process runningProcess = null; - - /** - * 查询真人交互数字人配置 - */ - @Override - public AihumanRealConfigVo queryById(Integer id) { - return baseMapper.selectVoById(id); - } - - /** - * 查询真人交互数字人配置列表 - */ - @Override - public TableDataInfo queryPageList(AihumanRealConfigBo bo, PageQuery pageQuery) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); - return TableDataInfo.build(result); - } - - /** - * 查询真人交互数字人配置列表 - */ - @Override - public List queryList(AihumanRealConfigBo bo) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); - } - - private LambdaQueryWrapper buildQueryWrapper(AihumanRealConfigBo bo) { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.like(StringUtils.isNotBlank(bo.getName()), AihumanRealConfig::getName, bo.getName()); - lqw.like(StringUtils.isNotBlank(bo.getAvatars()), AihumanRealConfig::getAvatars, bo.getAvatars()); - lqw.like(StringUtils.isNotBlank(bo.getModels()), AihumanRealConfig::getModels, bo.getModels()); - lqw.eq(StringUtils.isNotBlank(bo.getAvatarsParams()), AihumanRealConfig::getAvatarsParams, bo.getAvatarsParams()); - lqw.eq(StringUtils.isNotBlank(bo.getModelsParams()), AihumanRealConfig::getModelsParams, bo.getModelsParams()); - lqw.eq(StringUtils.isNotBlank(bo.getAgentParams()), AihumanRealConfig::getAgentParams, bo.getAgentParams()); - lqw.eq(bo.getCreateTime() != null, AihumanRealConfig::getCreateTime, bo.getCreateTime()); - lqw.eq(bo.getUpdateTime() != null, AihumanRealConfig::getUpdateTime, bo.getUpdateTime()); - lqw.eq(bo.getStatus() != null, AihumanRealConfig::getStatus, bo.getStatus()); - lqw.eq(bo.getPublish() != null, AihumanRealConfig::getPublish, bo.getPublish()); - lqw.eq(StringUtils.isNotBlank(bo.getRunParams()), AihumanRealConfig::getRunParams, bo.getRunParams()); - // 添加runStatus字段的查询条件 - lqw.eq(StringUtils.isNotBlank(bo.getRunStatus()), AihumanRealConfig::getRunStatus, bo.getRunStatus()); - lqw.eq(StringUtils.isNotBlank(bo.getCreateDept()), AihumanRealConfig::getCreateDept, bo.getCreateDept()); - lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), AihumanRealConfig::getCreateBy, bo.getCreateBy()); - lqw.eq(StringUtils.isNotBlank(bo.getUpdateBy()), AihumanRealConfig::getUpdateBy, bo.getUpdateBy()); - return lqw; - } - - /** - * 新增真人交互数字人配置 - */ - @Override - public Boolean insertByBo(AihumanRealConfigBo bo) { - AihumanRealConfig add = MapstructUtils.convert(bo, AihumanRealConfig.class); - validEntityBeforeSave(add); - boolean flag = baseMapper.insert(add) > 0; - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 修改真人交互数字人配置 - */ - @Override - public Boolean updateByBo(AihumanRealConfigBo bo) { - AihumanRealConfig update = MapstructUtils.convert(bo, AihumanRealConfig.class); - validEntityBeforeSave(update); - return baseMapper.updateById(update) > 0; - } - - /** - * 保存前的数据校验 - */ - private void validEntityBeforeSave(AihumanRealConfig entity) { - //TODO 做一些数据校验,如唯一约束 - } - - /** - * 批量删除真人交互数字人配置 - */ - @Override - public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { - if (isValid) { - //TODO 做一些业务上的校验,判断是否需要校验 - } - return baseMapper.deleteBatchIds(ids) > 0; - } - - /** - * 执行真人交互数字人配置 - * 通过主键获取数据库记录,然后从run_params字段读取命令并执行 - */ - @Override - public Boolean runByBo(AihumanRealConfigBo bo) { - try { - // 1. 通过主键获取数据库记录 - Integer id = bo.getId(); - if (id == null) { - log.error("执行命令失败:主键ID为空"); - throw new RuntimeException("执行命令失败:主键ID为空"); - } - - // 检查是否已经有对应的进程在运行 - String redisKey = "aihuman:process:" + id; - String existingPid = RedisUtils.getCacheObject(redisKey); - if (StringUtils.isNotEmpty(existingPid) && isProcessRunning(existingPid)) { - log.warn("ID为{}的配置已有进程在运行,进程ID: {}", id, existingPid); - // 刷新run_status状态为运行中 - AihumanRealConfig updateStatus = new AihumanRealConfig(); - updateStatus.setId(id); - updateStatus.setRunStatus("1"); // 1表示运行中 - baseMapper.updateById(updateStatus); - return true; - } - - // 查询数据库记录 - AihumanRealConfig config = baseMapper.selectById(id); - if (config == null) { - log.error("执行命令失败:未找到ID为{}的配置记录", id); - throw new RuntimeException("执行命令失败:未找到对应的配置记录"); - } - - // 2. 从记录中获取run_params字段 - String runParams = config.getRunParams(); - if (StringUtils.isBlank(runParams)) { - log.error("执行命令失败:ID为{}的记录中run_params字段为空", id); - throw new RuntimeException("执行命令失败:run_params字段为空"); - } - - // 3. 解析并执行命令 - // 将多行命令合并为一个命令字符串 - String[] commands = runParams.split("\\r?\\n"); - if (commands.length == 0) { - log.error("执行命令失败:runParams中没有有效的命令"); - throw new RuntimeException("执行命令失败:runParams中没有有效的命令"); - } - - // 将所有命令合并到一个命令字符串中,使用&&连接,确保在同一个进程中执行 - StringBuilder mergedCmd = new StringBuilder(); - for (int i = 0; i < commands.length; i++) { - String command = commands[i].trim(); - if (command.isEmpty()) { - continue; - } - - if (mergedCmd.length() > 0) { - mergedCmd.append(" && "); - } - - mergedCmd.append(command); - } - - String cmd = "cmd.exe /c " + mergedCmd.toString(); - log.info("准备执行合并命令:{}", cmd); - - // 更新数据库中的运行状态为运行中 - AihumanRealConfig updateStatus = new AihumanRealConfig(); - updateStatus.setId(id); - updateStatus.setRunStatus("1"); // 1表示运行中 - baseMapper.updateById(updateStatus); - - // 使用线程池执行命令并监听输出 - ExecutorService executor = Executors.newSingleThreadExecutor(); - executor.submit(() -> { - try { - Process process = Runtime.getRuntime().exec(cmd); - // 保存进程引用,用于后续停止操作 - runningProcess = process; - - // 获取进程ID并保存到Redis - String pid = getProcessId(process); - if (!"unknown".equals(pid)) { - RedisUtils.setCacheObject(redisKey, pid); - log.info("保存进程ID到Redis:key={}, pid={}", redisKey, pid); - } - - // 读取标准输出 - new Thread(() -> { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String line; - while ((line = reader.readLine()) != null) { - log.info("[LiveTalking] {}", line); - } - } catch (IOException e) { - log.error("读取命令输出失败", e); - } - }).start(); - - // 读取debug输出 - new Thread(() -> { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { - String line; - while ((line = reader.readLine()) != null) { - log.debug("[LiveTalking DEBUG] {}", line); - } - } catch (IOException e) { - log.error("读取命令debug输出失败", e); - } - }).start(); - - // 等待进程结束 - int exitCode = process.waitFor(); - log.info("LiveTalking进程结束,退出码: {}", exitCode); - - // 进程结束后更新数据库状态为已停止 - AihumanRealConfig endStatus = new AihumanRealConfig(); - endStatus.setId(id); - endStatus.setRunStatus("0"); // 0表示已停止 - baseMapper.updateById(endStatus); - - // 进程结束后从Redis中删除进程ID - RedisUtils.deleteObject(redisKey); - log.info("从Redis中删除进程ID:key={}", redisKey); - - // 进程结束后清空引用 - runningProcess = null; - } catch (Exception e) { - log.error("执行命令失败", e); - // 发生异常时更新数据库状态为失败 - try { - AihumanRealConfig errorStatus = new AihumanRealConfig(); - errorStatus.setId(id); - errorStatus.setRunStatus("2"); // 2表示启动失败 - baseMapper.updateById(errorStatus); - } catch (Exception ex) { - log.error("更新状态失败", ex); - } - // 发生异常时从Redis中删除进程ID - RedisUtils.deleteObject(redisKey); - // 发生异常时清空引用 - runningProcess = null; - } - }); - - executor.shutdown(); - return true; - } catch (Exception e) { - log.error("执行命令过程中发生异常", e); - return false; - } - } - - /** - * 检查进程是否正在运行 - * - * @param pid 进程ID - * @return 是否正在运行 - */ - private boolean isProcessRunning(String pid) { - if (StringUtils.isEmpty(pid) || "unknown".equals(pid)) { - return false; - } - - try { - boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win"); - ProcessBuilder processBuilder; - - if (isWindows) { - processBuilder = new ProcessBuilder("tasklist", "/FI", "PID eq " + pid); - } else { - processBuilder = new ProcessBuilder("ps", "-p", pid); - } - - Process process = processBuilder.start(); - int exitCode = process.waitFor(); - - // 在Windows上,tasklist命令如果找不到进程,退出码也是0,但输出中不会包含PID - if (isWindows) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String line; - while ((line = reader.readLine()) != null) { - if (line.contains(pid)) { - return true; - } - } - } - return false; - } else { - // 在Linux/Mac上,ps命令如果找不到进程,退出码不为0 - return exitCode == 0; - } - } catch (Exception e) { - log.error("检查进程是否运行失败, pid={}", pid, e); - return false; - } - } - - /** - * 停止正在运行的真人交互数字人配置任务 - */ - @Override - public Boolean stopByBo(AihumanRealConfigBo bo) { - try { - Integer id = bo.getId(); - String redisKey = "aihuman:process:" + id; - - // 首先检查Redis中是否有对应的进程ID - String pid = RedisUtils.getCacheObject(redisKey); - if (StringUtils.isNotEmpty(pid)) { - // 如果Redis中有进程ID,先尝试通过进程ID停止进程 - try { - // 根据操作系统类型,使用不同的命令终止进程树 - if (System.getProperty("os.name").toLowerCase().contains("win")) { - // Windows系统使用taskkill命令终止进程树 - log.info("通过Redis中的PID停止进程: taskkill /F /T /PID {}", pid); - Process killProcess = Runtime.getRuntime().exec("taskkill /F /T /PID " + pid); - // 等待kill命令执行完成 - killProcess.waitFor(5, TimeUnit.SECONDS); - } else { - // Linux/Mac系统使用pkill命令终止进程树 - Runtime.getRuntime().exec("pkill -P " + pid); - } - } catch (Exception e) { - log.error("通过Redis中的PID停止进程失败", e); - } - } - - // 然后检查本地runningProcess引用 - if (runningProcess != null && runningProcess.isAlive()) { - log.info("正在停止LiveTalking进程..."); - // 强制销毁进程树,确保完全停止 - destroyProcessTree(runningProcess); - - // 更新数据库中的运行状态为已停止 - AihumanRealConfig updateStatus = new AihumanRealConfig(); - updateStatus.setId(id); - updateStatus.setRunStatus("0"); // 0表示已停止 - baseMapper.updateById(updateStatus); - - runningProcess = null; - log.info("LiveTalking进程已停止"); - } else { - log.warn("没有正在运行的LiveTalking进程"); - // 确保数据库中的状态也是已停止 - AihumanRealConfig updateStatus = new AihumanRealConfig(); - updateStatus.setId(id); - updateStatus.setRunStatus("0"); // 0表示已停止 - baseMapper.updateById(updateStatus); - } - - // 无论如何都从Redis中删除进程ID - RedisUtils.deleteObject(redisKey); - log.info("从Redis中删除进程ID:key={}", redisKey); - - return true; - } catch (Exception e) { - log.error("停止进程时发生异常", e); - // 发生异常时也尝试从Redis中删除进程ID - try { - RedisUtils.deleteObject("aihuman:process:" + bo.getId()); - } catch (Exception ex) { - log.error("从Redis中删除进程ID失败", ex); - } - return false; - } - } - - /** - * 销毁进程及其子进程(进程树) - * - * @param process 要销毁的进程 - */ - private void destroyProcessTree(Process process) { - try { - if (process.isAlive()) { - // 获取进程ID - String pid = getProcessId(process); - log.info("获取到进程ID: {}", pid); - - // 根据操作系统类型,使用不同的命令终止进程树 - if (System.getProperty("os.name").toLowerCase().contains("win")) { - // Windows系统使用taskkill命令终止进程树 - log.info("执行taskkill命令终止进程树: taskkill /F /T /PID {}", pid); - Process killProcess = Runtime.getRuntime().exec("taskkill /F /T /PID " + pid); - // 等待kill命令执行完成 - killProcess.waitFor(5, TimeUnit.SECONDS); - } else { - // Linux/Mac系统使用pkill命令终止进程树 - Runtime.getRuntime().exec("pkill -P " + pid); - process.destroy(); - } - } - } catch (Exception e) { - log.error("销毁进程树时发生异常", e); - // 如果出现异常,尝试使用普通销毁方法 - process.destroy(); - try { - // 强制销毁 - if (process.isAlive()) { - process.destroyForcibly(); - } - } catch (Exception ex) { - log.error("强制销毁进程失败", ex); - } - } - } - - /** - * 获取进程ID - * - * @param process 进程对象 - * @return 进程ID - */ - private String getProcessId(Process process) { - try { - // 不同JVM实现可能有所不同,这里尝试通过反射获取 - if (process.getClass().getName().equals("java.lang.Win32Process") || - process.getClass().getName().equals("java.lang.ProcessImpl")) { - Field f = process.getClass().getDeclaredField("handle"); - f.setAccessible(true); - long handl = f.getLong(process); - Kernel32 kernel = Kernel32.INSTANCE; - WinNT.HANDLE handle = new WinNT.HANDLE(); - handle.setPointer(Pointer.createConstant(handl)); - return String.valueOf(kernel.GetProcessId(handle)); - } else if (process.getClass().getName().equals("java.lang.UNIXProcess")) { - Field f = process.getClass().getDeclaredField("pid"); - f.setAccessible(true); - return String.valueOf(f.getInt(process)); - } - } catch (Exception e) { - log.error("获取进程ID失败", e); - } - - // 如果反射获取失败,尝试通过wmic命令获取 - try { - // 对于Windows系统,可以尝试使用wmic命令获取进程ID - if (System.getProperty("os.name").toLowerCase().contains("win")) { - ProcessHandle.Info info = process.toHandle().info(); - return String.valueOf(process.toHandle().pid()); - } - } catch (Exception e) { - log.error("通过ProcessHandle获取进程ID失败", e); - } - - return "unknown"; - } - - @PreDestroy - public void onDestroy() { - if (runningProcess != null && runningProcess.isAlive()) { - try { - log.info("应用关闭,正在停止数字人进程"); - destroyProcessTree(runningProcess); - - // 查找所有运行状态为运行中的配置,并更新为已停止 - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.eq(AihumanRealConfig::getRunStatus, "1"); - List runningConfigs = baseMapper.selectList(lqw); - for (AihumanRealConfig config : runningConfigs) { - config.setRunStatus("0"); - baseMapper.updateById(config); - - // 从Redis中删除对应的进程ID记录 - String redisKey = "aihuman:process:" + config.getId(); - RedisUtils.deleteObject(redisKey); - log.info("应用关闭,从Redis中删除进程ID:key={}", redisKey); - } - } catch (Exception e) { - log.error("停止数字人进程失败", e); - // 即使发生异常,也尝试清理Redis中的进程ID记录 - try { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.eq(AihumanRealConfig::getRunStatus, "1"); - List runningConfigs = baseMapper.selectList(lqw); - for (AihumanRealConfig config : runningConfigs) { - RedisUtils.deleteObject("aihuman:process:" + config.getId()); - } - } catch (Exception ex) { - log.error("清理Redis中的进程ID记录失败", ex); - } - } - } - } - - // JNA接口定义,用于Windows系统获取进程ID - interface Kernel32 extends Library { - Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class); - - int GetProcessId(WinNT.HANDLE hProcess); - } -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanVolcengineServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanVolcengineServiceImpl.java deleted file mode 100644 index aa11aabd..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanVolcengineServiceImpl.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.ruoyi.aihuman.service.impl; - -public class AihumanVolcengineServiceImpl { -} diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/volcengine/Bidirection.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/volcengine/Bidirection.java deleted file mode 100644 index dc8ef8c9..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/volcengine/Bidirection.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.ruoyi.aihuman.volcengine; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.ruoyi.aihuman.protocol.EventType; -import org.ruoyi.aihuman.protocol.Message; -import org.ruoyi.aihuman.protocol.MsgType; -import org.ruoyi.aihuman.protocol.SpeechWebSocketClient; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.net.URI; -import java.nio.file.Files; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -@Slf4j -public class Bidirection { - private static final String ENDPOINT = "wss://openspeech.bytedance.com/api/v3/tts/bidirection"; - private static final ObjectMapper objectMapper = new ObjectMapper(); - - /** - * Get resource ID based on voice type - * - * @param voice Voice type string - * @return Corresponding resource ID - */ - public static String voiceToResourceId(String voice) { - // Map different voice types to resource IDs based on actual needs - if (voice.startsWith("S_")) { - return "volc.megatts.default"; - } - return "volc.service_type.10029"; - } - - public static void main(String[] args) throws Exception { - // Configure parameters - String appId = System.getProperty("appId", "1055299334"); - String accessToken = System.getProperty("accessToken", "fOHuq4R4dirMYiOruCU3Ek9q75zV0KVW"); - String resourceId = System.getProperty("resourceId", "seed-tts-2.0"); - String voice = System.getProperty("voice", "zh_female_vv_uranus_bigtts"); - String text = System.getProperty("text", "你好呀!我是AI合成的语音,很高兴认识你。"); - String encoding = System.getProperty("encoding", "mp3"); - - if (appId.isEmpty() || accessToken.isEmpty()) { - throw new IllegalArgumentException("Please set appId and accessToken system properties"); - } - - // Set request headers - Map headers = Map.of( - "X-Api-App-Key", appId, - "X-Api-Access-Key", accessToken, - "X-Api-Resource-Id", resourceId.isEmpty() ? voiceToResourceId(voice) : resourceId, - "X-Api-Connect-Id", UUID.randomUUID().toString()); - - // Create WebSocket client - SpeechWebSocketClient client = new SpeechWebSocketClient(new URI(ENDPOINT), headers); - try { - client.connectBlocking(); - Map request = Map.of( - "user", Map.of("uid", UUID.randomUUID().toString()), - "namespace", "BidirectionalTTS", - "req_params", Map.of( - "speaker", voice, - "audio_params", Map.of( - "format", encoding, - "sample_rate", 24000, - "enable_timestamp", true), - // additions requires a JSON string - "additions", objectMapper.writeValueAsString(Map.of( - "disable_markdown_filter", false)))); - - // Start connection - client.sendStartConnection(); - // Wait for connection started - client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.CONNECTION_STARTED); - - // Process each sentence - String[] sentences = text.split("。"); - boolean audioReceived = false; - for (int i = 0; i < sentences.length; i++) { - if (sentences[i].trim().isEmpty()) { - continue; - } - - String sessionId = UUID.randomUUID().toString(); - ByteArrayOutputStream audioStream = new ByteArrayOutputStream(); - - // Start session - Map startReq = Map.of( - "user", request.get("user"), - "namespace", request.get("namespace"), - "req_params", request.get("req_params"), - "event", EventType.START_SESSION.getValue()); - client.sendStartSession(objectMapper.writeValueAsBytes(startReq), sessionId); - // Wait for session started - client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.SESSION_STARTED); - - // Send text - for (char c : sentences[i].toCharArray()) { - // Create new req_params with text - @SuppressWarnings("unchecked") - Map currentReqParams = new HashMap<>( - (Map) request.get("req_params")); - currentReqParams.put("text", String.valueOf(c)); - - // Create current request - Map currentRequest = Map.of( - "user", request.get("user"), - "namespace", request.get("namespace"), - "req_params", currentReqParams, - "event", EventType.TASK_REQUEST.getValue()); - - client.sendTaskRequest(objectMapper.writeValueAsBytes(currentRequest), sessionId); - } - - // End session - client.sendFinishSession(sessionId); - - // Receive response - while (true) { - Message msg = client.receiveMessage(); - switch (msg.getType()) { - case FULL_SERVER_RESPONSE: - break; - case AUDIO_ONLY_SERVER: - if (!audioReceived && audioStream.size() > 0) { - audioReceived = true; - } - if (msg.getPayload() != null) { - audioStream.write(msg.getPayload()); - } - break; - default: - throw new RuntimeException("Unexpected message: " + msg); - } - if (msg.getEvent() == EventType.SESSION_FINISHED) { - break; - } - } - - if (audioStream.size() > 0) { - String fileName = String.format("%s_session_%d.%s", voice, i, encoding); - Files.write(new File(fileName).toPath(), audioStream.toByteArray()); - log.info("Audio saved to file: {}", fileName); - } - } - - if (!audioReceived) { - throw new RuntimeException("No audio data received"); - } - - // End connection - client.sendFinishConnection(); - } finally { - client.closeBlocking(); - } - } -} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/AihumanInfoMapper.xml b/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/AihumanInfoMapper.xml deleted file mode 100644 index 22bd47aa..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/AihumanInfoMapper.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanConfigMapper.xml b/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanConfigMapper.xml deleted file mode 100644 index 0cbe9dcb..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanConfigMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanRealConfigMapper.xml b/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanRealConfigMapper.xml deleted file mode 100644 index 8c7011ca..00000000 --- a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanRealConfigMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - -