Browse Source

feat(meeting): 支持多语言会议模板筛选

添加语言字段至数据库表,根据用户设备语言自动筛选对应模板
weicu
lxm 8 months ago
parent
commit
14ad58b374
  1. 6
      lib/data/services/db/database_helper.dart
  2. 58
      lib/data/services/db/sqflite_api.dart
  3. 505
      lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart

6
lib/data/services/db/database_helper.dart

@ -94,7 +94,8 @@ class DatabaseHelper {
batch.execute(''' batch.execute('''
CREATE TABLE IF NOT EXISTS meetingcategorytemplate ( CREATE TABLE IF NOT EXISTS meetingcategorytemplate (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT name TEXT,
language TEXT
) )
'''); ''');
// 商务会议助手模版 // 商务会议助手模版
@ -107,7 +108,8 @@ class DatabaseHelper {
tag TEXT, tag TEXT,
desc TEXT, desc TEXT,
outline TEXT, outline TEXT,
prompt TEXT prompt TEXT,
language TEXT
) )
'''); ''');
batch.insert('user', { batch.insert('user', {

58
lib/data/services/db/sqflite_api.dart

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '/core/utils/logger.dart';
import 'database_helper.dart'; import 'database_helper.dart';
@ -182,6 +183,42 @@ class SqfliteApi {
}); });
} }
static String _getMeetingTemplateLanguageCode() {
final locale = Get.locale ?? Get.deviceLocale;
if (locale == null) {
return 'en-US';
}
final code = locale.languageCode.toLowerCase();
switch (code) {
case 'zh':
return 'zh-CN';
case 'en':
return 'en-US';
case 'ja':
return 'ja-JP';
case 'ko':
return 'ko-KR';
case 'fr':
return 'fr-FR';
case 'de':
return 'de-DE';
case 'es':
return 'es-ES';
case 'it':
return 'it-IT';
case 'pt':
return 'pt-BR';
case 'ru':
return 'ru-RU';
case 'ar':
return 'ar-SA';
case 'hi':
return 'hi-IN';
default:
return 'en-US';
}
}
// 获取商务会议助手Ask AI列表 // 获取商务会议助手Ask AI列表
static Future getMeetingAiList(int id) async { static Future getMeetingAiList(int id) async {
final db = await DatabaseHelper().database; final db = await DatabaseHelper().database;
@ -223,6 +260,7 @@ class SqfliteApi {
'desc': item['description'], 'desc': item['description'],
'outline': item['outline'], 'outline': item['outline'],
'prompt': item['template'], 'prompt': item['template'],
'language': item['language'],
}; };
if (result != null) { if (result != null) {
result['templates'].add(template); result['templates'].add(template);
@ -230,6 +268,7 @@ class SqfliteApi {
categoryList.add({ categoryList.add({
'name': item['ttype'], 'name': item['ttype'],
'templates': [template], 'templates': [template],
'language': item['language'],
}); });
} }
} }
@ -252,6 +291,7 @@ class SqfliteApi {
await txn.insert('meetingcategorytemplate', { await txn.insert('meetingcategorytemplate', {
'id': categoryId, 'id': categoryId,
'name': item['name'], 'name': item['name'],
'language': item['language'],
}); });
for (var j = 0; j < item['templates'].length; j++) { for (var j = 0; j < item['templates'].length; j++) {
Map template = item['templates'][j]; Map template = item['templates'][j];
@ -264,6 +304,7 @@ class SqfliteApi {
'desc': template['desc'], 'desc': template['desc'],
'outline': template['outline'], 'outline': template['outline'],
'prompt': template['prompt'], 'prompt': template['prompt'],
'language': template['language'],
}); });
} }
} }
@ -272,15 +313,22 @@ class SqfliteApi {
// 获取商务会议助手所有分类模版列表 // 获取商务会议助手所有分类模版列表
static Future getMeetingCategoryTemplateList() async { static Future getMeetingCategoryTemplateList() async {
final language = _getMeetingTemplateLanguageCode();
Logger.info('language: $language');
final db = await DatabaseHelper().database; final db = await DatabaseHelper().database;
List categorytemplateList = await db.query('meetingcategorytemplate'); List categorytemplateList = await db.query(
'meetingcategorytemplate',
where: '(language = ? OR language IS NULL OR language = "")',
whereArgs: [language],
);
Logger.info('categorytemplateList: $categorytemplateList');
final dataList = final dataList =
categorytemplateList.map((item) => Map.from(item)).toList(); categorytemplateList.map((item) => Map.from(item)).toList();
for (var element in dataList) { for (var element in dataList) {
final List templateList = await db.query( final List templateList = await db.query(
'meetingtemplate', 'meetingtemplate',
limit: 4, limit: 4,
where: 'categoryid = ?', where: 'categoryid = ? ',
whereArgs: [element['id']], whereArgs: [element['id']],
orderBy: 'id ${element['name'] == '自定义' ? 'DESC' : 'ASC'}', orderBy: 'id ${element['name'] == '自定义' ? 'DESC' : 'ASC'}',
); );
@ -296,11 +344,13 @@ class SqfliteApi {
// 获取商务会议助手模版列表 // 获取商务会议助手模版列表
static Future getMeetingTemplateList(int id, {bool isCustom = false}) async { static Future getMeetingTemplateList(int id, {bool isCustom = false}) async {
final language = _getMeetingTemplateLanguageCode();
Logger.info('language: $language');
final db = await DatabaseHelper().database; final db = await DatabaseHelper().database;
return await db.query( return await db.query(
'meetingtemplate', 'meetingtemplate',
where: 'categoryid = ?', where: 'categoryid = ? AND language = ?',
whereArgs: [id], whereArgs: [id, language],
orderBy: 'id ${isCustom ? 'DESC' : 'ASC'}', orderBy: 'id ${isCustom ? 'DESC' : 'ASC'}',
); );
} }

505
lib/modules/meeting/views/bottomSheet/generate_bottom_sheet.dart

@ -93,285 +93,288 @@ class _GenerateBottomSheetState extends State<GenerateBottomSheet> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.w), padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.w),
child: Row( child: Row(
children: [ children: [
Icon( Icon(
Icons.audio_file_outlined, Icons.audio_file_outlined,
color: Colors.grey, color: Colors.grey,
size: 32.w, size: 32.w,
), ),
5.horizontalSpace, 5.horizontalSpace,
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
_controller.meetingData.value.title, _controller.meetingData.value.title,
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
color: Colors.black87, color: Colors.black87,
),
), ),
), Text(
Text( '${_controller.meetingData.value.seconds}s',
'${_controller.meetingData.value.seconds}s', style: TextStyle(
style: TextStyle( fontSize: 12.sp,
fontSize: 12.sp, color: Colors.grey,
color: Colors.grey, ),
), ),
), ],
],
),
),
GestureDetector(
onTap: () => Get.back(),
child: Container(
width: 26.w,
height: 26.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(26.r),
),
child: Icon(
Icons.close,
size: 18.w,
color: Colors.grey[400],
),
),
)
],
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 12.w),
margin: EdgeInsets.only(bottom: 10.w),
child: Divider(
height: 1,
color: Colors.grey[300],
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.w),
child: Row(
children: [
Expanded(
child: Text(
'selectSummaryTemplate'.tr, // 对应中文:选择总结模版
style: TextStyle(
fontSize: 14.sp,
color: Colors.black87,
), ),
), ),
), GestureDetector(
GestureDetector( onTap: () => Get.back(),
onTap: () async { child: Container(
var result = await Get.to( width: 26.w,
() => TemplateView( height: 26.w,
_templateData, decoration: BoxDecoration(
_lastTemplateData['id'] ?? 0, color: Colors.white,
borderRadius: BorderRadius.circular(26.r),
), ),
preventDuplicates: false, child: Icon(
); Icons.close,
if (result != null) { size: 18.w,
_scrollController.jumpTo(0); color: Colors.grey[400],
List list = List.from(_originalTemplate);
int index = list
.indexWhere((element) => element['id'] == result['id']);
if (index != -1) {
Map itemToMove = list.removeAt(index);
list.insert(0, itemToMove);
} else {
list.insert(0, result);
}
setState(() {
_templateData = result;
_templateList = list;
});
}
if (_controller.editTemplate.isNotEmpty) {
Map? editMap = _templateList.firstWhere(
(element) =>
element['id'] == _controller.editTemplate['id'],
orElse: () => null);
if (editMap != null) {
editMap['name'] = _controller.editTemplate['name'];
editMap['desc'] = _controller.editTemplate['desc'];
editMap['prompt'] = _controller.editTemplate['prompt'];
}
if (_controller.editTemplate['id'] == _templateData['id']) {
_templateData['name'] = _controller.editTemplate['name'];
_templateData['desc'] = _controller.editTemplate['desc'];
_templateData['prompt'] =
_controller.editTemplate['prompt'];
}
setState(() {});
}
if (_controller.deleteTemplateId != 0) {
_templateList.removeWhere((element) =>
element['id'] == _controller.deleteTemplateId);
if (_controller.deleteTemplateId == _templateData['id']) {
_templateData = _templateList[0];
}
setState(() {});
_storage.write("meeting_last_template_Data", {});
_storage.write("meeting_template_list", _templateList);
}
},
child: Row(
children: [
Text(
'viewAll'.tr, // 对应中文:查看全部
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey,
),
), ),
const Icon( ),
Icons.keyboard_arrow_right, )
color: Colors.grey, ],
) ),
],
),
),
],
),
),
Container(
height: 130.w,
margin: EdgeInsets.only(bottom: 16.w),
child: ListView.builder(
controller: _scrollController,
itemCount: _templateList.length,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(horizontal: 4.w),
itemBuilder: (BuildContext context, int index) {
Map data = _templateList[index];
return _item(data);
},
), ),
),
if (!widget.isSummarizeAgain)
Container( Container(
margin: EdgeInsets.symmetric(horizontal: 12.w), padding: EdgeInsets.symmetric(horizontal: 12.w),
decoration: BoxDecoration( margin: EdgeInsets.only(bottom: 10.w),
color: Colors.white, child: Divider(
borderRadius: BorderRadius.circular(8.r), height: 1,
color: Colors.grey[300],
), ),
child: Column( ),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.w),
child: Row(
children: [ children: [
_row( Expanded(
'speakerIdentification'.tr, // 对应中文:区分说话人 child: Text(
widget: Transform.scale( 'selectSummaryTemplate'.tr, // 对应中文:选择总结模版
scale: 0.8, style: TextStyle(
alignment: Alignment.centerRight, fontSize: 14.sp,
child: Switch( color: Colors.black87,
value: _isSpeaker,
onChanged: (bool value) {
setState(() {
_isSpeaker = value;
});
},
), ),
), ),
), ),
_row( GestureDetector(
'recordingLanguage'.tr, // 对应中文:录音语言 onTap: () async {
value: _formlanguageText, var result = await Get.to(
onTap: () { () => TemplateView(
Get.bottomSheet( _templateData,
RecordLanguageBottomSheet(_formlanguage), _lastTemplateData['id'] ?? 0,
isScrollControlled: true,
backgroundColor: Colors.grey[100],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(12.r),
),
), ),
).then((value) { preventDuplicates: false,
if (value != null) { );
setState(() { if (result != null) {
_formlanguageText = value['name']; _scrollController.jumpTo(0);
_formlanguage = value['value']; List list = List.from(_originalTemplate);
}); int index = list.indexWhere(
(element) => element['id'] == result['id']);
if (index != -1) {
Map itemToMove = list.removeAt(index);
list.insert(0, itemToMove);
} else {
list.insert(0, result);
}
setState(() {
_templateData = result;
_templateList = list;
});
}
if (_controller.editTemplate.isNotEmpty) {
Map? editMap = _templateList.firstWhere(
(element) =>
element['id'] == _controller.editTemplate['id'],
orElse: () => null);
if (editMap != null) {
editMap['name'] = _controller.editTemplate['name'];
editMap['desc'] = _controller.editTemplate['desc'];
editMap['prompt'] = _controller.editTemplate['prompt'];
}
if (_controller.editTemplate['id'] ==
_templateData['id']) {
_templateData['name'] =
_controller.editTemplate['name'];
_templateData['desc'] =
_controller.editTemplate['desc'];
_templateData['prompt'] =
_controller.editTemplate['prompt'];
}
setState(() {});
}
if (_controller.deleteTemplateId != 0) {
_templateList.removeWhere((element) =>
element['id'] == _controller.deleteTemplateId);
if (_controller.deleteTemplateId == _templateData['id']) {
_templateData = _templateList[0];
} }
}); setState(() {});
_storage.write("meeting_last_template_Data", {});
_storage.write("meeting_template_list", _templateList);
}
}, },
), child: Row(
_row( children: [
'targetLanguage'.tr, // 对应中文:目标语言 Text(
value: _tolanguageText, 'viewAll'.tr, // 对应中文:查看全部
isBorder: false, style: TextStyle(
onTap: () { fontSize: 12.sp,
Get.bottomSheet( color: Colors.grey,
RecordLanguageBottomSheet(_tolanguage),
isScrollControlled: true,
backgroundColor: Colors.grey[100],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(12.r),
), ),
), ),
).then((value) { const Icon(
if (value != null) { Icons.keyboard_arrow_right,
setState(() { color: Colors.grey,
_tolanguageText = value['name']; )
_tolanguage = value['value']; ],
}); ),
}
});
},
), ),
], ],
), ),
), ),
Padding( Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 20.w), height: 130.w,
child: GestureDetector( margin: EdgeInsets.only(bottom: 16.w),
onTap: () { child: ListView.builder(
if (User.isLoggedIn() && User.instance.meetintegral <= 0) { controller: _scrollController,
showRechargeDialog('meeting'); itemCount: _templateList.length,
return; scrollDirection: Axis.horizontal,
} padding: EdgeInsets.symmetric(horizontal: 4.w),
if (_templateData['id'] != _templateList[0]['id']) { itemBuilder: (BuildContext context, int index) {
int index = _templateList Map data = _templateList[index];
.indexWhere((v) => v['id'] == _templateData['id']); return _item(data);
if (index != -1) { },
Map itemToMove = _templateList.removeAt(index); ),
_templateList.insert(0, itemToMove); ),
} if (!widget.isSummarizeAgain)
} Container(
_storage.write("meeting_last_template_Data", _templateData); margin: EdgeInsets.symmetric(horizontal: 12.w),
_storage.write("meeting_template_list", _templateList);
Get.back();
if (widget.isSummarizeAgain) {
_controller.refreshSummary(_templateData['id']);
} else {
_controller.summaryCreate(
_formlanguage,
_tolanguage,
_isSpeaker,
_templateData['id'],
);
}
},
child: Container(
height: 48.w,
alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.black, color: Colors.white,
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(8.r),
), ),
child: Text( child: Column(
'meetingGenerateNow'.tr, // 对应中文:立即生成 children: [
style: TextStyle( _row(
fontSize: 16.sp, 'speakerIdentification'.tr, // 对应中文:区分说话人
color: Colors.white, widget: Transform.scale(
scale: 0.8,
alignment: Alignment.centerRight,
child: Switch(
value: _isSpeaker,
onChanged: (bool value) {
setState(() {
_isSpeaker = value;
});
},
),
),
),
_row(
'recordingLanguage'.tr, // 对应中文:录音语言
value: _formlanguageText,
onTap: () {
Get.bottomSheet(
RecordLanguageBottomSheet(_formlanguage),
isScrollControlled: true,
backgroundColor: Colors.grey[100],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(12.r),
),
),
).then((value) {
if (value != null) {
setState(() {
_formlanguageText = value['name'];
_formlanguage = value['value'];
});
}
});
},
),
_row(
'targetLanguage'.tr, // 对应中文:目标语言
value: _tolanguageText,
isBorder: false,
onTap: () {
Get.bottomSheet(
RecordLanguageBottomSheet(_tolanguage),
isScrollControlled: true,
backgroundColor: Colors.grey[100],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(12.r),
),
),
).then((value) {
if (value != null) {
setState(() {
_tolanguageText = value['name'];
_tolanguage = value['value'];
});
}
});
},
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 20.w),
child: GestureDetector(
onTap: () {
if (User.isLoggedIn() && User.instance.meetintegral <= 0) {
showRechargeDialog('meeting');
return;
}
if (_templateData['id'] != _templateList[0]['id']) {
int index = _templateList
.indexWhere((v) => v['id'] == _templateData['id']);
if (index != -1) {
Map itemToMove = _templateList.removeAt(index);
_templateList.insert(0, itemToMove);
}
}
_storage.write("meeting_last_template_Data", _templateData);
_storage.write("meeting_template_list", _templateList);
Get.back();
if (widget.isSummarizeAgain) {
_controller.refreshSummary(_templateData['id']);
} else {
_controller.summaryCreate(
_formlanguage,
_tolanguage,
_isSpeaker,
_templateData['id'],
);
}
},
child: Container(
height: 48.w,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(12.r),
),
child: Text(
'meetingGenerateNow'.tr, // 对应中文:立即生成
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
),
), ),
), ),
), ),
), ),
),
], ],
), ),
); );

Loading…
Cancel
Save