From 33542056c7f42cf410c71246a8f8dbb93ad08750 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Tue, 21 Oct 2025 17:15:52 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BC=9A=E8=AE=AE?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=A8=A1=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/data/services/db/database_helper.dart | 202 +----------------- lib/data/services/db/sqflite_api.dart | 35 +++ lib/data/services/network/api.dart | 9 + .../login/controllers/login_controller.dart | 9 + 4 files changed, 54 insertions(+), 201 deletions(-) diff --git a/lib/data/services/db/database_helper.dart b/lib/data/services/db/database_helper.dart index fcefe6bbf..b0d7562c0 100644 --- a/lib/data/services/db/database_helper.dart +++ b/lib/data/services/db/database_helper.dart @@ -104,6 +104,7 @@ class DatabaseHelper { icon TEXT, tag TEXT, desc TEXT, + outline TEXT, prompt TEXT ) '''); @@ -112,207 +113,6 @@ class DatabaseHelper { 'synctime': 0, 'privatecloud': 0, }); - // 商务会议助手插入默认模版 - batch.insert('meetingcategorytemplate', { - 'id': 1, - 'name': '通用', - }); - batch.insert('meetingcategorytemplate', { - 'id': 2, - 'name': '会议', - }); - batch.insert('meetingcategorytemplate', { - 'id': 3, - 'name': '演讲', - }); - batch.insert('meetingcategorytemplate', { - 'id': 4, - 'name': '自定义', - }); - batch.insert('meetingtemplate', { - 'categoryid': 1, - 'name': '会议纪要', - 'icon': 'auto_stories', - 'tag': '主题, 代办事项', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 1, - 'name': 'Autopilot', - 'icon': 'auto_graph', - 'tag': '自适应结构, 全场景适配', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 1, - 'name': '推理Autopilot', - 'icon': 'add_to_drive_outlined', - 'tag': '推理模型, 自动结构化', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 1, - 'name': '通话', - 'icon': 'perm_phone_msg', - 'tag': '主题, 代办事项', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 1, - 'name': '项目计划', - 'icon': 'assignment', - 'tag': '目标, 里程碑', - 'desc': '用于规划项目阶段和关键节点,跟踪项目执行进度', - 'prompt': '请按时间顺序整理项目阶段' - }); - batch.insert('meetingtemplate', { - 'categoryid': 1, - 'name': '头脑风暴', - 'icon': 'lightbulb', - 'tag': '创意, 发散思维', - 'desc': '记录创意发散过程,结构化整理核心创意点', - 'prompt': '请将讨论内容按创新性排序' - }); - batch.insert('meetingtemplate', { - 'categoryid': 1, - 'name': '日常记录', - 'icon': 'note', - 'tag': '日志, 每日总结', - 'desc': '自动化生成结构化日报,自动提取工作亮点与待办事项', - 'prompt': '请按优先级排列今日工作事项' - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '咨询', - 'icon': 'auto_stories', - 'tag': '主题, 代办事项', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '讨论', - 'icon': 'auto_graph', - 'tag': '自适应结构, 全场景适配', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '汇报', - 'icon': 'add_to_drive_outlined', - 'tag': '推理模型, 自动结构化', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '任务分配', - 'icon': 'perm_phone_msg', - 'tag': '主题, 代办事项', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '评审会议', - 'icon': 'rate_review', - 'tag': '质量评估, 改进建议', - 'desc': '用于评估项目阶段成果,生成改进建议和风险评估', - 'prompt': '请按优先级列出需要改进的环节' - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '周例会', - 'icon': 'event_repeat', - 'tag': '进度汇报, 计划制定', - 'desc': '自动生成每周工作进展摘要,识别延期风险', - 'prompt': '请按部门分类整理工作进度' - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '客户洽谈', - 'icon': 'handshake', - 'tag': '需求沟通, 合同条款', - 'desc': '记录客户核心诉求和合作关键条款', - 'prompt': '请按优先级排列客户需求' - }); - batch.insert('meetingtemplate', { - 'categoryid': 2, - 'name': '项目复盘', - 'icon': 'restart_alt', - 'tag': '经验总结, 问题分析', - 'desc': '自动生成项目得失分析报告', - 'prompt': '请按影响程度排序待改进项' - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': '课堂笔记', - 'icon': 'auto_stories', - 'tag': '主题, 代办事项', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': '讲座', - 'icon': 'auto_graph', - 'tag': '自适应结构, 全场景适配', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': '培训', - 'icon': 'add_to_drive_outlined', - 'tag': '推理模型, 自动结构化', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': 'Sermon', - 'icon': 'perm_phone_msg', - 'tag': '主题, 代办事项', - 'desc': '旨在概述和回顾项目内容,重点捕捉所提话题的精髓和关键点', - 'prompt': '提示词', - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': '产品发布会', - 'icon': 'rocket_launch', - 'tag': '功能展示, 市场定位', - 'desc': '结构化整理产品核心卖点和市场差异化特征', - 'prompt': '请按用户场景分类产品功能' - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': '技术分享', - 'icon': 'code', - 'tag': '知识传递, 最佳实践', - 'desc': '自动提取技术要点和可复用代码片段', - 'prompt': '请按技术难度分级整理内容' - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': '投资者路演', - 'icon': 'bar_chart', - 'tag': '财务数据, 商业模式', - 'desc': '自动提取核心财务指标和增长预期', - 'prompt': '请按投资关注度整理内容' - }); - batch.insert('meetingtemplate', { - 'categoryid': 3, - 'name': '学术报告', - 'icon': 'school', - 'tag': '研究成果, 数据分析', - 'desc': '结构化整理实验数据和学术论点', - 'prompt': '请按研究重要性排序结论' - }); await batch.commit(); } } diff --git a/lib/data/services/db/sqflite_api.dart b/lib/data/services/db/sqflite_api.dart index 51c43babe..5b5a8641a 100644 --- a/lib/data/services/db/sqflite_api.dart +++ b/lib/data/services/db/sqflite_api.dart @@ -210,6 +210,41 @@ class SqfliteApi { await db.insert('meetingai', meeting); } + // 初始化模版 + static Future initMeetingTemplate(List data) async { + final db = await DatabaseHelper().database; + await db.transaction((txn) async { + // 清空旧数据 + await txn.delete('meetingtemplate'); + await txn.delete('meetingcategorytemplate'); + + List categoryList = []; + + for (var i = 0; i < data.length; i++) { + Map item = data[i]; + int index = categoryList.indexOf(item['ttype']); + int categoryId = categoryList.length; + if (index == -1) { + categoryList.add(item['ttype']); + categoryId++; + await txn.insert('meetingcategorytemplate', { + 'id': categoryId, + 'name': item['ttype'], + }); + } + await txn.insert('meetingtemplate', { + 'categoryid': categoryId, + 'name': item['title'], + 'icon': item['icon'], + 'tag': item['tags'], + 'desc': item['description'], + 'outline': item['outline'], + 'prompt': item['template'], + }); + } + }); + } + // 获取商务会议助手所有分类模版列表 static Future getMeetingCategoryTemplateList() async { final db = await DatabaseHelper().database; diff --git a/lib/data/services/network/api.dart b/lib/data/services/network/api.dart index 8e36e726c..ef52ac4e5 100644 --- a/lib/data/services/network/api.dart +++ b/lib/data/services/network/api.dart @@ -180,4 +180,13 @@ class Api { params: params, ); } + + //获取模版数据 + static getEchomeetTemplates([params]) { + return DioManager().request( + NWMethod.post, + '/api/home/echomeet_gettemplates', + params: params, + ); + } } diff --git a/lib/modules/login/controllers/login_controller.dart b/lib/modules/login/controllers/login_controller.dart index a159b0269..395c197a2 100644 --- a/lib/modules/login/controllers/login_controller.dart +++ b/lib/modules/login/controllers/login_controller.dart @@ -8,6 +8,7 @@ import 'package:logger/web.dart'; import 'package:get_storage/get_storage.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'dart:convert'; +import '../../../data/services/db/sqflite_api.dart'; import 'facebookLogin.dart'; import 'googleLogin.dart'; import 'weixinLogin.dart'; @@ -869,6 +870,7 @@ class LoginController extends GetxController { // 获取app的配置信息 await getAppConfig(); + await _initMeetingTemplate(); Get.offAllNamed(Routes.pairing); } else { throw Exception('接口返回错误: ${response['msg']}'); @@ -991,4 +993,11 @@ class LoginController extends GetxController { return false; } } + + Future _initMeetingTemplate() async { + var response = await Api.getEchomeetTemplates(); + if (response != null) { + await SqfliteApi.initMeetingTemplate(response['templates']); + } + } } From aad80c89f2f8d8ebf4442dc04c03e58cf39d35f9 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Tue, 21 Oct 2025 18:57:31 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BC=9A=E8=AE=AE?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=A8=A1=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../meeting/meeting_task_service.dart | 37 ++++++++++++------- .../meeting/meeting_upload_service.dart | 10 ++++- .../meeting_details_controller.dart | 8 ++-- .../bottomSheet/generate_bottom_sheet.dart | 10 ++++- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/lib/data/services/meeting/meeting_task_service.dart b/lib/data/services/meeting/meeting_task_service.dart index ccae12596..debff4b35 100644 --- a/lib/data/services/meeting/meeting_task_service.dart +++ b/lib/data/services/meeting/meeting_task_service.dart @@ -6,7 +6,6 @@ import 'package:http/http.dart' as http; import '../../../core/utils/logger.dart'; import '../../../core/utils/synchrodata.dart'; -import '../../models/appconfig.dart'; import '../db/sqflite_api.dart'; import '../deapsound_ai_service.dart'; import 'meeting_upload_service.dart'; @@ -21,7 +20,6 @@ class MeetingTaskService extends GetxService { bool _isTask = false; - String _systemPrompt = ''; String _userId = ''; final String _appid = '2316081933'; @@ -50,7 +48,6 @@ class MeetingTaskService extends GetxService { void _getAgent() async { Map userInfo = _storage.read("user_info"); _userId = userInfo['user']['uid']; - _systemPrompt = AppConfig.agentsystemPrompt("meet_assistant") ?? ''; } void _getTaskList() { @@ -59,7 +56,8 @@ class MeetingTaskService extends GetxService { _executeTask(); } - Future addTask(int id, String audiourl, String taskid) async { + Future addTask(int id, String audiourl, String taskid, String prompt, + String outline) async { if (audiourl.isEmpty) { Map uploadData = _uploadService.uploadList.firstWhere( (element) => element['id'] == id, @@ -68,16 +66,20 @@ class MeetingTaskService extends GetxService { if (uploadData.isNotEmpty) { if (uploadData['audiourl'].isEmpty) { uploadData['isTask'] = true; + uploadData['prompt'] = prompt; + uploadData['outline'] = outline; } else { - await addTaskList(id, uploadData['audiourl'], taskid); + await addTaskList( + id, uploadData['audiourl'], taskid, prompt, outline); } } } else { - await addTaskList(id, audiourl, taskid); + await addTaskList(id, audiourl, taskid, prompt, outline); } } - Future addTaskList(int id, String audiourl, String taskId) async { + Future addTaskList(int id, String audiourl, String taskId, + String prompt, String outline) async { if (taskId.isEmpty) { taskId = await _submitTask(audiourl); } @@ -86,6 +88,8 @@ class MeetingTaskService extends GetxService { 'id': id, 'taskid': taskId, 'tasktype': 1, + 'prompt': prompt, + 'outline': outline, }); taskFinishList.add({ 'id': id, @@ -206,7 +210,12 @@ class MeetingTaskService extends GetxService { var code = respDic['resp']['code'] as int; if (code == 1000) { - await _addTextList(item['id'], respDic['resp']['utterances']); + await _addTextList( + item['id'], + respDic['resp']['utterances'], + item['prompt'], + item['outline'], + ); return; } else if (code < 2000) { Logger.debug("FileRecognize failed"); @@ -217,7 +226,8 @@ class MeetingTaskService extends GetxService { } } - Future _addTextList(int id, List utterances) async { + Future _addTextList( + int id, List utterances, String prompt, String outline) async { String text = ''; String personnel = ''; List> list = []; @@ -267,10 +277,10 @@ class MeetingTaskService extends GetxService { _storage.write("meeting_task_list", _taskList); _storage.write("meeting_task_finish_list", taskFinishList); } - aiServiceMessage(id, text); + aiServiceMessage(id, text, prompt, outline); } - void aiServiceMessage(int id, String text) { + void aiServiceMessage(int id, String text, String prompt, String outline) { int awaitQuantity = 0; String summaryText = ''; String overviewText = ''; @@ -278,8 +288,7 @@ class MeetingTaskService extends GetxService { messages: [ { 'role': 'system', - 'content': - '您将扮演一名会议总结专家,拥有超强的信息归纳与细分能力。不仅能高效处理各类通用场景会议,精准提炼会议核心内容,为后续思维导图生成奠定坚实基础。若涉及人员,人员名称保留[]。并根据内容只输出对应语言。', + 'content': prompt, }, {'role': 'user', 'content': text}, ], @@ -294,7 +303,7 @@ class MeetingTaskService extends GetxService { messages: [ { 'role': 'system', - 'content': '您将扮演一名会议事件归纳专家,能准确抓住会议中事件的关键点,并每个事件只需一句话精简总结。', + 'content': outline, }, {'role': 'user', 'content': text}, ], diff --git a/lib/data/services/meeting/meeting_upload_service.dart b/lib/data/services/meeting/meeting_upload_service.dart index 65ebdd805..27e25ee47 100644 --- a/lib/data/services/meeting/meeting_upload_service.dart +++ b/lib/data/services/meeting/meeting_upload_service.dart @@ -41,6 +41,8 @@ class MeetingUploadService extends GetxService { 'rootdir': rootDir, 'audiourl': '', 'isTask': false, + 'prompt': '', + 'outline': '', }); _storage.write("meeting_upload_list", uploadList); if (isUpload) { @@ -70,7 +72,13 @@ class MeetingUploadService extends GetxService { {'audiourl': audiourl}, ); if (element['isTask']) { - await _taskService.addTaskList(element['id'], audiourl, ''); + await _taskService.addTaskList( + element['id'], + audiourl, + '', + element['prompt'], + element['outline'], + ); } element['audiourl'] = audiourl; uploadProgress.value = 0.0; diff --git a/lib/modules/meeting/controllers/meeting_details_controller.dart b/lib/modules/meeting/controllers/meeting_details_controller.dart index 19a9db30f..5d1669fc3 100644 --- a/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -245,18 +245,18 @@ class MeetingDetailsController extends GetxController } } - void summaryCreate() async { + void summaryCreate(String prompt, String outline) async { EasyLoading.show(); _everType = 2; String audiourl = meetingData.value.audiourl; String taskId = meetingDetails.value.taskid; - await _meetingTaskService.addTask(id, audiourl, taskId); + await _meetingTaskService.addTask(id, audiourl, taskId, prompt, outline); meetingDetails.value.tasktype = 1; meetingDetails.refresh(); EasyLoading.dismiss(); } - void refreshSummary() async { + void refreshSummary(String prompt, String outline) async { String text = ''; for (var element in textList) { if (element['speaker'].isNotEmpty) { @@ -267,6 +267,6 @@ class MeetingDetailsController extends GetxController _everType = 3; await SqfliteApi.editMeeting(id, {'tasktype': 2}); _meetingTaskService.tasktype.value = 2; - _meetingTaskService.aiServiceMessage(id, text); + _meetingTaskService.aiServiceMessage(id, text, prompt, outline); } } diff --git a/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart b/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart index 3537b4435..8b704ef7a 100644 --- a/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart +++ b/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart @@ -283,9 +283,15 @@ class _GenerateBottomSheetState extends State { _storage.write("meeting_template_list", _templateList); Get.back(); if (widget.isSummarizeAgain) { - _controller.refreshSummary(); + _controller.refreshSummary( + _templateData['prompt'], + _templateData['outline'], + ); } else { - _controller.summaryCreate(); + _controller.summaryCreate( + _templateData['prompt'], + _templateData['outline'], + ); } }, child: Container( From 652f0befb8eaaeadc5c23521eeb94df7f7473e7b Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Tue, 21 Oct 2025 19:49:11 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BC=9A=E8=AE=AE?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=A8=A1=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/data/services/db/sqflite_api.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/data/services/db/sqflite_api.dart b/lib/data/services/db/sqflite_api.dart index 5b5a8641a..aca96cf21 100644 --- a/lib/data/services/db/sqflite_api.dart +++ b/lib/data/services/db/sqflite_api.dart @@ -242,6 +242,12 @@ class SqfliteApi { 'prompt': item['template'], }); } + if (!categoryList.contains('自定义')) { + await txn.insert('meetingcategorytemplate', { + 'id': categoryList.length + 1, + 'name': '自定义', + }); + } }); } From d51b526c9a14f401772696e1b9dcb32a13e8b12a Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Tue, 21 Oct 2025 20:35:15 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BC=9A=E8=AE=AE?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=A8=A1=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/meeting/meeting_task_service.dart | 16 +++++++++------- .../services/meeting/meeting_upload_service.dart | 2 ++ .../controllers/meeting_details_controller.dart | 5 +++-- .../views/bottomSheet/generate_bottom_sheet.dart | 1 + 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/data/services/meeting/meeting_task_service.dart b/lib/data/services/meeting/meeting_task_service.dart index debff4b35..2f698bca1 100644 --- a/lib/data/services/meeting/meeting_task_service.dart +++ b/lib/data/services/meeting/meeting_task_service.dart @@ -56,8 +56,8 @@ class MeetingTaskService extends GetxService { _executeTask(); } - Future addTask(int id, String audiourl, String taskid, String prompt, - String outline) async { + Future addTask(int id, String audiourl, String taskid, String language, + String prompt, String outline) async { if (audiourl.isEmpty) { Map uploadData = _uploadService.uploadList.firstWhere( (element) => element['id'] == id, @@ -66,22 +66,23 @@ class MeetingTaskService extends GetxService { if (uploadData.isNotEmpty) { if (uploadData['audiourl'].isEmpty) { uploadData['isTask'] = true; + uploadData['language'] = language; uploadData['prompt'] = prompt; uploadData['outline'] = outline; } else { await addTaskList( - id, uploadData['audiourl'], taskid, prompt, outline); + id, uploadData['audiourl'], taskid, language, prompt, outline); } } } else { - await addTaskList(id, audiourl, taskid, prompt, outline); + await addTaskList(id, audiourl, taskid, language, prompt, outline); } } Future addTaskList(int id, String audiourl, String taskId, - String prompt, String outline) async { + String language, String prompt, String outline) async { if (taskId.isEmpty) { - taskId = await _submitTask(audiourl); + taskId = await _submitTask(audiourl, language); } await SqfliteApi.editMeeting(id, {'tasktype': 1, 'taskid': taskId}); _taskList.add({ @@ -130,7 +131,7 @@ class MeetingTaskService extends GetxService { } } - Future _submitTask(String audiourl) async { + Future _submitTask(String audiourl, String language) async { String format = _getFileType(audiourl); final requestBody = jsonEncode({ @@ -147,6 +148,7 @@ class MeetingTaskService extends GetxService { "url": audiourl, }, "additions": { + "language": language, "with_speaker_info": "True", } }); diff --git a/lib/data/services/meeting/meeting_upload_service.dart b/lib/data/services/meeting/meeting_upload_service.dart index 27e25ee47..5d0b8afa1 100644 --- a/lib/data/services/meeting/meeting_upload_service.dart +++ b/lib/data/services/meeting/meeting_upload_service.dart @@ -41,6 +41,7 @@ class MeetingUploadService extends GetxService { 'rootdir': rootDir, 'audiourl': '', 'isTask': false, + 'language': '', 'prompt': '', 'outline': '', }); @@ -76,6 +77,7 @@ class MeetingUploadService extends GetxService { element['id'], audiourl, '', + element['language'], element['prompt'], element['outline'], ); diff --git a/lib/modules/meeting/controllers/meeting_details_controller.dart b/lib/modules/meeting/controllers/meeting_details_controller.dart index 5d1669fc3..28800bce7 100644 --- a/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -245,12 +245,13 @@ class MeetingDetailsController extends GetxController } } - void summaryCreate(String prompt, String outline) async { + void summaryCreate(String language, String prompt, String outline) async { EasyLoading.show(); _everType = 2; String audiourl = meetingData.value.audiourl; String taskId = meetingDetails.value.taskid; - await _meetingTaskService.addTask(id, audiourl, taskId, prompt, outline); + await _meetingTaskService.addTask( + id, audiourl, taskId, language, prompt, outline); meetingDetails.value.tasktype = 1; meetingDetails.refresh(); EasyLoading.dismiss(); diff --git a/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart b/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart index 8b704ef7a..60ca335b7 100644 --- a/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart +++ b/lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart @@ -289,6 +289,7 @@ class _GenerateBottomSheetState extends State { ); } else { _controller.summaryCreate( + _language, _templateData['prompt'], _templateData['outline'], ); From b2bffea642fc30c4442cad8986a5ebc4e280c358 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Tue, 21 Oct 2025 20:48:46 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=B8=8A=E4=BC=A0bug=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/controllers/agent_controller.dart | 26 +++++--- .../chat_api/CustomSseClientTransport.kt | 54 +++++++++++---- .../chat_api/SystemFunctionHandler.kt | 65 ++++++++++--------- .../chat_api/SystemFunctionHandler.swift | 39 +++++------ 4 files changed, 112 insertions(+), 72 deletions(-) diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart index ad10e5d70..55169ac42 100644 --- a/lib/modules/agent/controllers/agent_controller.dart +++ b/lib/modules/agent/controllers/agent_controller.dart @@ -613,10 +613,20 @@ class AgentController extends GetxController with WidgetsBindingObserver { final sessionid = event.data['sessionid'] ?? ''; final text = event.data['text'] ?? ''; Logger.i(TAG, '[$sessionid]识别最终结果: $text'); + + if (currsessionid.value != "" && currsessionid.value != sessionid) { + final index = messages.lastIndexWhere( + (msg) => msg.sessionid == currsessionid.value && msg.isUser); + //出现了为识别结束的消息 + if (index >= 0) { + //异除去当前会话的识别中消息 + messages.removeAt(index); + } + } + currsessionid.value = sessionid; // 查找是否有正在识别中的消息 final index = messages.lastIndexWhere( (msg) => msg.sessionid == sessionid && msg.isUser); - if (text.isNotEmpty) { if (index >= 0) { // 将识别中的消息转换为最终消息 @@ -655,7 +665,7 @@ class AgentController extends GetxController with WidgetsBindingObserver { // 查找是否有正在识别中的消息 final index = messages.lastIndexWhere( (msg) => msg.sessionid == sessionid && msg.isUser); - + currsessionid.value = ''; if (currentText.value.isNotEmpty) { if (index >= 0) { // 将识别中的消息转换为最终消息 @@ -668,14 +678,14 @@ class AgentController extends GetxController with WidgetsBindingObserver { functionCalls: messages[index].functionCalls, isToolCallsExpanded: messages[index].isToolCallsExpanded, ); - // messages.refresh(); } else { // 如果没有找到识别中的消息,添加新消息 messages.add(Message( - sessionid: sessionid, - isUser: true, - text: currentText.value, - isRecognizing: false)); + sessionid: sessionid, + isUser: true, + text: currentText.value, + isRecognizing: false, + )); } isProcessing.value = true; @@ -685,8 +695,8 @@ class AgentController extends GetxController with WidgetsBindingObserver { } else if (index >= 0) { // 如果识别结果为空,移除临时的识别消息 messages.removeAt(index); - // messages.refresh(); } + messages.refresh(); break; case AgentServiceEventType.ttsStarted: isSpeaking.value = true; diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt index b515dedb2..da85cbaeb 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/CustomSseClientTransport.kt @@ -177,14 +177,39 @@ class CustomSseClientTransport( } } - // 添加查询参数 + // 添加查询参数,避免重复参数 val endpointWithParams = if (queryParams.isNotEmpty()) { + // 解析现有的查询参数 + val existingParams = mutableMapOf() if (validatedEndpoint.contains("?")) { - val queryString = queryParams.entries.joinToString("&") { "${it.key}=${it.value}" } - "$validatedEndpoint&$queryString" + val urlParts = validatedEndpoint.split("?", limit = 2) + if (urlParts.size == 2) { + urlParts[1].split("&").forEach { param -> + val parts = param.split("=", limit = 2) + if (parts.size == 2) { + existingParams[parts[0]] = parts[1] + } + } + } + } + + // 合并参数,避免重复 + val allParams = mutableMapOf() + allParams.putAll(existingParams) + allParams.putAll(queryParams) + + // 构建最终URL + val baseUrl = if (validatedEndpoint.contains("?")) { + validatedEndpoint.split("?")[0] } else { - val queryString = queryParams.entries.joinToString("&") { "${it.key}=${it.value}" } - "$validatedEndpoint?$queryString" + validatedEndpoint + } + + if (allParams.isNotEmpty()) { + val queryString = allParams.entries.joinToString("&") { "${it.key}=${it.value}" } + "$baseUrl?$queryString" + } else { + baseUrl } } else { validatedEndpoint @@ -280,7 +305,7 @@ class CustomSseClientTransport( } sessionScope = CoroutineScope(transportScope.coroutineContext + SupervisorJob()) - + Log.e(TAG, "$serviceidString 解析成功: start 会话") // 创建SSE会话 - 直接使用原始URL session = urlString?.let { val sseConnectUrl = if (queryParams.isNotEmpty()) { @@ -303,14 +328,14 @@ class CustomSseClientTransport( reconnectionTime = reconnectionTime, block = requestBuilder, ) - + Log.e(TAG, "$serviceidString: start 会话 collectEvents") // 收集SSE事件 collectEvents() - + Log.e(TAG, "$serviceidString: start 会话 endpoint") // 等待endpoint就绪 endpoint.await() - Log.d(TAG, "CustomSseClientTransport启动完成") + Log.d(TAG, "$serviceidString: CustomSseClientTransport启动完成") } /** @@ -322,15 +347,18 @@ class CustomSseClientTransport( Log.e(TAG, "发送失败: 未连接") error("Not connected") } - + try { val messageEndpoint = endpoint.getCompleted() + Log.d(TAG, "$serviceidString 准备发送消息到: $messageEndpoint") val jsonString = json.encodeToString(message) - val response = client.post(messageEndpoint) { - headers.append(HttpHeaders.ContentType, ContentType.Application.Json.toString()) - setBody(jsonString) + val response = withTimeout(15000) { // 减少超时时间到15秒 + client.post(messageEndpoint) { + headers.append(HttpHeaders.ContentType, ContentType.Application.Json.toString()) + setBody(jsonString) + } } // 优化处理百度API的202状态码 diff --git a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt index 756a7269a..94173554d 100644 --- a/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt +++ b/local_plugins/chat_api/android/src/main/kotlin/com/yunqiinnovation/chat_api/SystemFunctionHandler.kt @@ -60,6 +60,18 @@ class SystemFunctionHandler(private val context: Context? = null) { // handler = TranslationModeHandler(context) // ) + // 注册获取联系人列表函数 + client.registerLocalFunction( + name = "get_contacts_list", + description = "获取用户通信录联系人列表", + parameters = mapOf( + "type" to "object", + "properties" to emptyMap(), + "required" to emptyList() + ), + handler = GetContactsListHandler(context) + ) + // 注册发送短信函数 client.registerLocalFunction( name = "send_text_message", @@ -67,7 +79,7 @@ class SystemFunctionHandler(private val context: Context? = null) { parameters = mapOf( "type" to "object", "properties" to mapOf( - "contact" to mapOf( + "phone_number" to mapOf( "type" to "string", "description" to "电话号码" ), @@ -76,23 +88,11 @@ class SystemFunctionHandler(private val context: Context? = null) { "description" to "短信内容" ) ), - "required" to listOf("contact", "message") + "required" to listOf("phone_number", "message") ), handler = SendTextMessageHandler(context) ) - // 注册获取联系人列表函数 - client.registerLocalFunction( - name = "get_contacts_list", - description = "获取用户通信录联系人列表", - parameters = mapOf( - "type" to "object", - "properties" to emptyMap(), - "required" to emptyList() - ), - handler = GetContactsListHandler(context) - ) - // 注册拨打电话函数 client.registerLocalFunction( name = "make_phone_call", @@ -100,12 +100,12 @@ class SystemFunctionHandler(private val context: Context? = null) { parameters = mapOf( "type" to "object", "properties" to mapOf( - "contact" to mapOf( + "phone_number" to mapOf( "type" to "string", - "description" to "联系人姓名或电话号码" + "description" to "联系人电话号码" ) ), - "required" to listOf("contact") + "required" to listOf("phone_number") ), handler = MakePhoneCallHandler(context) ) @@ -495,10 +495,10 @@ private class TranslationModeHandler(private val context: Context?) : FunctionHa */ private class SendTextMessageHandler(private val context: Context?) : FunctionHandler { override suspend fun handle(arguments: Map): String { - val contact = arguments["contact"] as? String + val phone_number = arguments["phone_number"] as? String val message = arguments["message"] as? String - if (contact == null || message == null) { + if (phone_number == null || message == null) { return JSONObject().apply { put("error", JSONObject().apply { put("code", "invalid_arguments") @@ -529,12 +529,12 @@ private class SendTextMessageHandler(private val context: Context?) : FunctionHa }.toString() } - val phoneNumber = handler.getPhoneNumberForContact(contact) + val phoneNumber = handler.getPhoneNumberForContact(phone_number) if (phoneNumber.isEmpty()) { return JSONObject().apply { put("error", JSONObject().apply { put("code", "contact_not_found") - put("message", "未找到联系人信息: $contact") + put("message", "未找到联系人信息: $phone_number") }) }.toString() } @@ -556,7 +556,7 @@ private class SendTextMessageHandler(private val context: Context?) : FunctionHa } JSONObject().apply { - put("result", "已成功向${contact}发送短信") + put("result", "已成功向${phone_number}发送短信") put("phone", phoneNumber) put("message", message) }.toString() @@ -637,13 +637,13 @@ private class MakePhoneCallHandler(private val context: Context?) : FunctionHand } override suspend fun handle(arguments: Map): String { - val contact = arguments["contact"] as? String + val phone_number = arguments["phone_number"] as? String - if (contact == null) { + if (phone_number == null) { return JSONObject().apply { put("error", JSONObject().apply { put("code", "invalid_arguments") - put("message", "缺少必要参数:contact") + put("message", "缺少必要参数:phone_number") }) }.toString() } @@ -670,12 +670,12 @@ private class MakePhoneCallHandler(private val context: Context?) : FunctionHand }.toString() } - val phoneNumber = handler.getPhoneNumberForContact(contact) + val phoneNumber = handler.getPhoneNumberForContact(phone_number) if (phoneNumber.isEmpty()) { return JSONObject().apply { put("error", JSONObject().apply { put("code", "contact_not_found") - put("message", "未找到联系人信息: $contact") + put("message", "未找到联系人信息: $phone_number") }) }.toString() } @@ -688,7 +688,7 @@ private class MakePhoneCallHandler(private val context: Context?) : FunctionHand context.startActivity(intent) JSONObject().apply { - put("result", "正在拨打${contact}的电话") + put("result", "正在拨打${phone_number}的电话") put("phone", phoneNumber) }.toString() } catch (e: SecurityException) { @@ -1106,10 +1106,11 @@ private class GetCurrentLocationHandler(private val context: Context?) : Functio val result = JSONObject().apply { put("result", JSONObject().apply { - put("longitude", longitude) - put("latitude", latitude) - put("timestamp", System.currentTimeMillis()) - + put("经度", longitude) // 经度 + put("纬度", latitude) // 纬度 + put("经纬度", "$latitude,$longitude") + put("纬经度", "$longitude,$latitude") + put("时间戳", System.currentTimeMillis()) }) }.toString() diff --git a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift index 1b892350a..cc7613322 100644 --- a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift +++ b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift @@ -71,12 +71,13 @@ public class SystemFunctionHandler: NSObject { // 注册翻译模式函数 // registerTranslationModeFunction(client: client) - // 注册发送短信函数 - registerSendTextMessageFunction(client: client) - // 注册查询通讯录函数 registerGetContactsFunction(client: client) + // 注册发送短信函数 + registerSendTextMessageFunction(client: client) + + // 注册拨打电话函数 registerMakePhoneCallFunction(client: client) @@ -163,16 +164,16 @@ public class SystemFunctionHandler: NSObject { let parameters: [String: Any] = [ "type": "object", "properties": [ - "contact": [ + "phone_number": [ "type": "string", - "description": "联系人姓名或电话号码" + "description": "联系人电话号码" ], "message": [ "type": "string", "description": "要发送的短信内容" ] ], - "required": ["contact", "message"] + "required": ["phone_number", "message"] ] let handler = SendTextMessageHandler() @@ -194,8 +195,8 @@ public class SystemFunctionHandler: NSObject { let handler = GetContactsHandler() _ = client.registerLocalFunction( - name: "get_contacts", - description: "获取联系人列表,读取通讯录信息,联系人名称和电话", + name: "get_contacts_list", + description: "获取用户通信录联系人列表", parameters: parameters, handler: handler ) @@ -206,12 +207,12 @@ public class SystemFunctionHandler: NSObject { let parameters: [String: Any] = [ "type": "object", "properties": [ - "contact": [ + "phone_number": [ "type": "string", - "description": "联系人姓名或电话号码" + "description": "联系人电话号码" ] ], - "required": ["contact"] + "required": ["phone_number"] ] let handler = MakePhoneCallHandler() @@ -628,22 +629,22 @@ private class SendTextMessageHandler: NSObject, FunctionHandler, MFMessageCompos private var continuation: CheckedContinuation? func handle(arguments: [String: Any]) async throws -> String { - guard let contact = arguments["contact"] as? String, + guard let phoneNumber = arguments["phone_number"] as? String, let message = arguments["message"] as? String else { throw ChatApiException("缺少必要参数") } - let result = await sendTextMessage(contact: contact, message: message) + let result = await sendTextMessage(phoneNumber: phoneNumber, message: message) return "{\"result\": \"\(result.message)\"}" } - private func sendTextMessage(contact: String, message: String) async -> Result { + private func sendTextMessage(phoneNumber: String, message: String) async -> Result { return await withCheckedContinuation { continuation in self.continuation = continuation DispatchQueue.main.async { if MFMessageComposeViewController.canSendText() { let messageVC = MFMessageComposeViewController() - messageVC.recipients = [contact] + messageVC.recipients = [phoneNumber] messageVC.body = message messageVC.messageComposeDelegate = self // 设置 delegate @@ -693,16 +694,16 @@ private class SendTextMessageHandler: NSObject, FunctionHandler, MFMessageCompos /// 拨打电话处理器 private class MakePhoneCallHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { - guard let contact = arguments["contact"] as? String else { + guard let phoneNumber = arguments["phone_number"] as? String else { throw ChatApiException("缺少联系人参数") } - let result = await makePhoneCall(contact: contact) + let result = await makePhoneCall(phoneNumber: phoneNumber) return "{\"result\": \"\(result.message)\"}" } - private func makePhoneCall(contact: String) async -> Result { - guard let url = URL(string: "tel:\(contact)") else { + private func makePhoneCall(phoneNumber: String) async -> Result { + guard let url = URL(string: "tel:\(phoneNumber)") else { return Result(success: false, message: "无法创建电话URL") } return await withCheckedContinuation { continuation in