Browse Source

Merge commit '78a9b0f666c34de7eafe2ae25cce277b3c68f6da' into lxm

weicu
lxm 2 years ago
parent
commit
1674506058
  1. 30
      lib/data/providers/agent_provider.dart
  2. 2
      lib/data/services/ai_service.dart
  3. 11
      lib/data/services/deapsound_ai_service.dart
  4. 1
      lib/main.dart
  5. 9
      lib/modules/chat/bindings/chat_binding.dart
  6. 81
      lib/modules/chat/controllers/chat_controller.dart
  7. 8
      lib/modules/chat/models/message_model.dart
  8. 107
      lib/modules/chat/views/chat_music_card.dart
  9. 179
      lib/modules/chat/views/chat_navigation_card.dart
  10. 58
      lib/modules/chat/views/chat_view.dart
  11. 94
      lib/modules/chat/views/weather_day_card.dart
  12. 21
      lib/modules/meeting/controllers/meeting_record_controller.dart

30
lib/data/providers/agent_provider.dart

@ -1,18 +1,18 @@
import '../models/agent.dart';
import 'package:get/get.dart';
class AgentProvider {
static final List<Agent> predefinedAgents = [
Agent(// 个人助理 Emma
const Agent(
// 个人助理 Emma
id: 'personal_assistant',
name: 'personalAssistantName',
avatarUrl: 'assets/images/agents/assistant.png',
description:
'personalAssistantDescription',
description: 'personalAssistantDescription',
tag: 'assistantTag', // '助理'
isOnline: true,
voice: "zh-CN-XiaoxiaoNeural",
welcomeMessage: 'personalAssistantWelcome',// "你好!我是 Emma,很高兴成为你的私人助理。我可以帮你处理各种任务,比如时间管理、目标规划、信息整理等。有什么我可以帮你的吗?",
welcomeMessage:
'personalAssistantWelcome', // "你好!我是 Emma,很高兴成为你的私人助理。我可以帮你处理各种任务,比如时间管理、目标规划、信息整理等。有什么我可以帮你的吗?",
voiceWelcomeMessage: "personalAssistantVoiceWelcome", // "我在呢!"
systemPrompt: '''
你是一位名叫 Emma 的全能型个人助理,擅长处理各类工作和生活事务。
@ -57,7 +57,7 @@ class AgentProvider {
请始终以专业、高效、周到的态度,协助用户更好地管理工作和生活, 不要输出表情符号或非可读的符号。
'''),
Agent(
const Agent(
id: 'simultaneous_interpreter',
name: 'interpreterName',
avatarUrl: 'assets/images/agents/interpreter.png',
@ -65,10 +65,9 @@ class AgentProvider {
tag: 'interpreterTag',
isOnline: true,
voice: 'zh-CN-XiaoxiaoNeural',
welcomeMessage:
'interpreterWelcome',
welcomeMessage: 'interpreterWelcome',
systemPrompt: ""),
Agent(
const Agent(
id: 'cyber_girlfriend',
name: 'companionName',
avatarUrl: 'assets/images/agents/girlfriend.png',
@ -76,8 +75,7 @@ class AgentProvider {
tag: 'companionTag',
isOnline: true,
voice: "zh-CN-XiaoxiaoNeural",
welcomeMessage:
"companionWelcome",
welcomeMessage: "companionWelcome",
systemPrompt: '''
你是一位名叫芯愿的亲子陪伴,性格温柔体贴,善解人意,富有同理心。
@ -128,14 +126,14 @@ class AgentProvider {
请始终以温暖、真诚的态度与用户互动,创造一种被理解、被关心的感受。
'''),
Agent(
const Agent(
id: 'health_advisor',
name: 'healthAdvisorName',
avatarUrl: 'assets/images/agents/doctor.png',
description: 'healthAdvisorDescription',
tag: 'healthAdvisorTag',
isOnline: true,
voice: "zh_male_shaonianzixin_moon_bigtts",
voice: "zh-CN-XiaoxiaoNeural",
welcomeMessage: "healthAdvisorWelcome",
voiceWelcomeMessage: 'healthAdvisorVoiceWelcome',
systemPrompt: '''
@ -205,7 +203,7 @@ class AgentProvider {
请始终以专业、关怀的态度为用户提供健康指导,帮助他们迈向更健康的生活。
'''),
Agent(
const Agent(
id: 'speaking_coach',
name: 'Sarah (英语口语教练)',
avatarUrl: 'assets/images/agents/speaking_coach.png',
@ -252,7 +250,7 @@ class AgentProvider {
Please keep your tone friendly, encouraging, and always in English.
''',
),
Agent(
const Agent(
id: 'shopping_assistant',
name: '购物顾问 张媛',
avatarUrl: 'assets/images/agents/shopping.png',
@ -285,7 +283,7 @@ Please keep your tone friendly, encouraging, and always in English.
'''),
Agent(
const Agent(
id: 'tarot.png',
name: '命理师 玄易',
avatarUrl: 'assets/images/agents/tarot.png',

2
lib/data/services/ai_service.dart

@ -7,7 +7,7 @@ abstract class AiService {
});
/// 流式输出方法
Stream<String> sendMessageStream({
Stream sendMessageStream({
required List<Map<String, String>> messages,
required String systemPrompt,
});

11
lib/data/services/deapsound_ai_service.dart

@ -23,7 +23,7 @@ class DeapsoundAIService implements AiService {
}
@override
Stream<String> sendMessageStream({
Stream sendMessageStream({
required List<Map<String, String>> messages,
required String systemPrompt,
}) async* {
@ -67,10 +67,13 @@ class DeapsoundAIService implements AiService {
try {
final data = jsonDecode(jsonStr);
if (data['event'] == 'workflow_finished') {
break;
if (data['role'] == 'card') {
yield data['meta'];
if (data['meta']['musicaudio'] != null) {
break;
}
}
if (data['content'] != null) {
if (data['role'] == 'ai') {
String content = data['content'] ?? '';
if (content.isNotEmpty) {
yield content;

1
lib/main.dart

@ -67,7 +67,6 @@ class MainApp extends StatelessWidget {
builder: (_, child) {
return GetMaterialApp(
title: 'DeepSound',
defaultTransition: Transition.noTransition, // 设置默认过渡动画为无动画
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: themeMode, // 使用提前获取的主题模式

9
lib/modules/chat/bindings/chat_binding.dart

@ -1,17 +1,10 @@
import 'package:get/get.dart';
import '../controllers/chat_controller.dart';
import '../../../data/services/speech_impl/azure_asr_service.dart';
import '../../../data/services/speech_impl/azure_tts_service.dart';
import '../../../data/services/asr_service.dart';
import '../../../data/services/tts_service.dart';
import '../../../data/services/volcano_ai_service.dart';
import '../../../data/services/chat_history_service.dart';
class ChatBinding extends Bindings {
@override
void dependencies() {
// 注册控制器
Get.lazyPut<ChatController>(() => ChatController());
}
}
}

81
lib/modules/chat/controllers/chat_controller.dart

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:get/get.dart';
import 'package:flutter/widgets.dart';
import 'package:get_storage/get_storage.dart';
import 'package:just_audio/just_audio.dart';
import '../../../data/services/ai_service.dart';
import '../../../data/services/deapsound_ai_service.dart';
import '../../../data/services/kouzi_ai_service.dart';
@ -72,6 +73,10 @@ class ChatController extends GetxController {
// 记录最后一次活动时间
DateTime _lastActivityTime = DateTime.now();
final player = AudioPlayer();
final RxString audiourl = ''.obs;
final RxBool isPlay = false.obs;
@override
Future<void> onInit() async {
super.onInit();
@ -152,6 +157,14 @@ class ChatController extends GetxController {
// 订阅VoiceInteractionService事件
_subscribeToVoiceInteractionEvents();
player.playerStateStream.listen((state) async {
if (state.processingState == ProcessingState.completed) {
await player.seek(Duration.zero);
player.pause();
isPlay.value = false;
}
});
// 使用微任务在布局完成后自动滚动到底部
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToBottom();
@ -248,6 +261,8 @@ class ChatController extends GetxController {
_historyService.saveHistory(agent.id!, messages.toList());
}
player.dispose();
super.onClose();
}
@ -343,14 +358,21 @@ class ChatController extends GetxController {
(chunk) {
if (_shouldCancelAiResponse) return;
fullResponse += chunk;
// 更新加载中的消息内容
_updateLoadingMessage(fullResponse);
// 如果TTS启用,使用流式处理发送到TTS
if (isTtsEnabled.value) {
_ttsService.speakStream(chunk);
if (chunk is Map) {
_updateLoadingMessage(data: chunk);
if (chunk['musicaudio'] != null) {
play(chunk['musicaudio']);
}
} else {
fullResponse += chunk;
// 更新加载中的消息内容
_updateLoadingMessage(content: fullResponse);
// 如果TTS启用,使用流式处理发送到TTS
if (isTtsEnabled.value) {
_ttsService.speakStream(chunk);
}
}
},
onDone: () {
@ -402,18 +424,51 @@ class ChatController extends GetxController {
}
// 更新加载中的消息
void _updateLoadingMessage(String content) {
void _updateLoadingMessage({Map? data, String? content}) {
final index = messages.indexWhere((m) => m.isLoading);
if (index != -1) {
messages[index] = messages[index].copyWith(
content: content,
isLoading: true,
);
if (data != null) {
Map messagesData = messages[index].data ?? {};
messages[index] = messages[index].copyWith(
data: {...messagesData, ...data},
isLoading: true,
);
}
if (content != null) {
messages[index] = messages[index].copyWith(
content: content,
isLoading: true,
);
}
messages.refresh();
_scrollToBottom();
}
}
// 播放音乐
void play(Map musicaudio) async {
try {
isPlay.value = false;
if (audiourl.value != musicaudio['audiourl']) {
audiourl.value = '';
await player.setUrl(musicaudio['audiourl']);
audiourl.value = musicaudio['audiourl'];
player.play();
} else {
player.play();
}
isPlay.value = true;
} catch (e) {
Logger.error('加载异常: $e');
}
}
// 暂停播放音乐
void pause() async {
await player.pause();
isPlay.value = false;
}
// 完成响应
void _finalizeResponse(String content) {
final index = messages.indexWhere((m) => m.isLoading);

8
lib/modules/chat/models/message_model.dart

@ -1,6 +1,7 @@
class Message {
final String role; // 'user' or 'assistant'
final String content;
final Map? data;
final DateTime timestamp;
final bool isLoading;
@ -8,6 +9,7 @@ class Message {
required this.role,
required this.content,
required this.timestamp,
this.data,
this.isLoading = false,
});
@ -16,6 +18,7 @@ class Message {
return Message(
role: json['role'] as String,
content: json['content'] as String,
data: json['data'],
timestamp: DateTime.parse(json['timestamp'] as String),
isLoading: json['isLoading'] as bool? ?? false,
);
@ -26,6 +29,7 @@ class Message {
return {
'role': role,
'content': content,
'data': data,
'timestamp': timestamp.toIso8601String(),
'isLoading': isLoading,
};
@ -45,14 +49,16 @@ class Message {
Message copyWith({
String? role,
String? content,
Map? data,
DateTime? timestamp,
bool? isLoading,
}) {
return Message(
role: role ?? this.role,
content: content ?? this.content,
data: data ?? this.data,
timestamp: timestamp ?? this.timestamp,
isLoading: isLoading ?? this.isLoading,
);
}
}
}

107
lib/modules/chat/views/chat_music_card.dart

@ -0,0 +1,107 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import '../controllers/chat_controller.dart';
class ChatMusicCard extends GetView<ChatController> {
final Map? data;
final bool isDarkMode;
const ChatMusicCard(this.data, this.isDarkMode, {super.key});
@override
Widget build(BuildContext context) {
final Map musiccards = data?['musiccards'].first;
final Map musicaudio = data?['musicaudio'];
return Row(
children: [
Container(
width: 60.w,
height: 60.w,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
),
child: Image.network(
musiccards['image'],
fit: BoxFit.cover,
),
),
10.horizontalSpace,
Expanded(
child: Text(
musiccards['name'],
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 16.sp,
height: 1.5,
),
),
),
10.horizontalSpace,
Obx(
() => controller.audiourl == musicaudio['audiourl'] &&
controller.isPlay.value
? GestureDetector(
onTap: () {
controller.pause();
},
child: Stack(
alignment: Alignment.center,
children: [
SizedBox(
width: 38.w,
height: 38.w,
child: StreamBuilder<Duration>(
stream: controller.player.positionStream,
builder: (context, snapshot) {
final position = snapshot.data ?? Duration.zero;
final total =
controller.player.duration ?? Duration.zero;
final progress = total.inSeconds > 0
? position.inSeconds / total.inSeconds
: 0.0;
return CircularProgressIndicator(
value: progress,
backgroundColor: isDarkMode
? Colors.grey[700]!
: Colors.grey[300]!,
valueColor: AlwaysStoppedAnimation<Color>(
isDarkMode ? Colors.white : Colors.black),
strokeWidth: 2, // 线条粗细
);
},
),
),
Icon(
Icons.pause_rounded,
color: isDarkMode ? Colors.white : Colors.black,
),
],
),
)
: GestureDetector(
onTap: () {
controller.play(musicaudio);
},
child: Container(
width: 38.w,
height: 38.w,
decoration: BoxDecoration(
color: isDarkMode ? Colors.white : Colors.black,
shape: BoxShape.circle,
),
child: Icon(
Icons.play_arrow_rounded,
color: isDarkMode ? Colors.black : Colors.white,
),
),
),
),
],
);
}
}

179
lib/modules/chat/views/chat_navigation_card.dart

@ -0,0 +1,179 @@
import 'dart:convert';
import 'dart:math';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class ChatNavigationCard extends StatefulWidget {
final Map? data;
final bool isDarkMode;
const ChatNavigationCard(this.data, this.isDarkMode, {super.key});
@override
State<ChatNavigationCard> createState() => _ChatNavigationCardState();
}
class _ChatNavigationCardState extends State<ChatNavigationCard> {
final String apiKey = '8bde023b7e5e00f321ea17929f10fbae';
LatLng startPoint = LatLng(116.397428, 39.90923); // 起点坐标
LatLng endPoint = LatLng(116.397026, 39.903303); // 终点坐标
@override
void initState() {
super.initState();
_getMapUrl();
}
Future<String> _getMapUrl() async {
// 1. 获取路径数据
final route = await _fetchRouteData();
// 2. 解析并简化路径
List<LatLng> simplified = _simplifyPath(route, epsilon: 0.0001);
// 3. 计算地图参数
final zoom = _calculateAutoZoom(simplified);
// 4. 生成静态地图URL
return _buildStaticMapUrl(simplified, zoom);
}
Future<List<LatLng>> _fetchRouteData() async {
final url = 'https://restapi.amap.com/v3/direction/driving?'
'origin=${startPoint.lng},${startPoint.lat}&'
'destination=${endPoint.lng},${endPoint.lat}&'
'key=$apiKey';
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final data = json.decode(response.body);
return _parsePolyline(data['route']['paths'][0]['steps']);
}
throw Exception('Failed to load route');
}
List<LatLng> _parsePolyline(List<dynamic> steps) {
final List<LatLng> path = [];
for (final step in steps) {
final points = (step['polyline'] as String).split(';');
for (final point in points) {
final coords = point.split(',').map(double.parse).toList();
path.add(LatLng(coords[0], coords[1]));
}
}
return path;
}
List<LatLng> _simplifyPath(List<LatLng> points, {double epsilon = 0.0001}) {
return douglasPeucker(points, epsilon);
}
int _calculateAutoZoom(List<LatLng> points,
{int mapWidth = 1024, int mapHeight = 512}) {
if (points.isEmpty) return 15; // 默认缩放级别
// 1. 计算坐标范围
double minLng = double.infinity;
double maxLng = -double.infinity;
double minLat = double.infinity;
double maxLat = -double.infinity;
for (final p in points) {
final lng = p.lng;
final lat = p.lat;
minLng = math.min(minLng, lng);
maxLng = math.max(maxLng, lng);
minLat = math.min(minLat, lat);
maxLat = math.max(maxLat, lat);
}
// 3. 计算缩放级别(基于Leaflet算法改进)
const worldWidth = 256; // 高德瓦片尺寸
const worldHeight = 256;
const zoomMax = 18; // 高德最大缩放级别
double latRad(double lat) {
final sin = math.sin(lat * math.pi / 180);
return math.log((1 + sin) / (1 - sin)) / 2;
}
final latFraction = (latRad(maxLat) - latRad(minLat)) / math.pi;
final lngDiff = maxLng - minLng;
final lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;
final latZoom =
math.log((mapHeight / worldHeight) / latFraction) / math.ln2;
final lngZoom = math.log((mapWidth / worldWidth) / lngFraction) / math.ln2;
return math.min(math.min(latZoom, lngZoom).floor(), zoomMax);
}
String _buildStaticMapUrl(List<LatLng> path, int zoom) {
final pathParam = path.map((p) => '${p.lng},${p.lat}').join(';');
return 'https://restapi.amap.com/v3/staticmap?'
'zoom=$zoom&'
'size=1024*512&'
'paths=10,0x0000ff,1,,:$pathParam&'
'markers=mid,,A:${startPoint.lng},${startPoint.lat}|'
'mid,,B:${endPoint.lng},${endPoint.lat}&'
'key=$apiKey';
}
List<LatLng> douglasPeucker(List<LatLng> points, double epsilon) {
if (points.length < 3) return points;
double maxDistance = 0;
int index = 0;
for (int i = 1; i < points.length - 1; i++) {
double d = _perpendicularDistance(points[i], points.first, points.last);
if (d > maxDistance) {
index = i;
maxDistance = d;
}
}
if (maxDistance > epsilon) {
return [
...douglasPeucker(points.sublist(0, index + 1), epsilon),
...douglasPeucker(points.sublist(index), epsilon).skip(1)
];
}
return [points.first, points.last];
}
double _perpendicularDistance(LatLng point, LatLng start, LatLng end) {
final area = (end.lng - start.lng) * (point.lat - start.lat) -
(end.lat - start.lat) * (point.lng - start.lng);
final length =
sqrt(pow(end.lng - start.lng, 2) + pow(end.lat - start.lat, 2));
return area.abs() / length;
}
@override
Widget build(BuildContext context) {
return Column(
children: [
FutureBuilder(
future: _getMapUrl(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Image.network(snapshot.data);
}
return const CircularProgressIndicator();
},
),
],
);
}
}
class LatLng {
final double lat;
final double lng;
LatLng(this.lng, this.lat); // 高德使用经度在前纬度在后的格式
}

58
lib/modules/chat/views/chat_view.dart

@ -5,6 +5,9 @@ import 'dart:math';
import '../controllers/chat_controller.dart';
import '../models/message_model.dart';
import '../../../core/theme/app_colors.dart';
import 'chat_music_card.dart';
import 'chat_navigation_card.dart';
import 'weather_day_card.dart';
class ChatView extends GetView<ChatController> {
const ChatView({Key? key}) : super(key: key);
@ -297,19 +300,7 @@ class ChatView extends GetView<ChatController> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 消息内容
if (message.content.isNotEmpty)
SelectableText(
'${message.content}'.tr,
style: TextStyle(
color: isUser
? Colors.white
: isDarkMode
? Colors.white
: Colors.black,
fontSize: 16.sp,
height: 1.5,
),
),
_buildMessageContent(message, isDarkMode, isUser),
// 加载中动画
if (message.isLoading)
@ -348,6 +339,36 @@ class ChatView extends GetView<ChatController> {
);
}
Widget _buildMessageContent(Message message, bool isDarkMode, bool isUser) {
Widget box = const SizedBox();
if (message.content.isNotEmpty) {
box = SelectableText(
message.content.tr,
style: TextStyle(
color: isUser
? Colors.white
: isDarkMode
? Colors.white
: Colors.black,
fontSize: 16.sp,
height: 1.5,
),
);
}
if (message.data != null) {
if (message.data?['weatherDays'] != null) {
box = WeatherDayCard(message.data, isDarkMode);
}
if (message.data?['musicaudio'] != null) {
box = ChatMusicCard(message.data, isDarkMode);
}
if (message.data?['navigationcard'] != null) {
box = ChatNavigationCard(message.data, isDarkMode);
}
}
return box;
}
// 构建输入区域
Widget _buildInputArea(bool isDarkMode) {
final textController =
@ -715,21 +736,22 @@ class ChatView extends GetView<ChatController> {
);
}
// 格式化时间
// 格式化时间
String _formatTime(DateTime time) {
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
//final yesterday = today.subtract(const Duration(days: 1));
final messageDate = DateTime(time.year, time.month, time.day);
String timeStr = '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}';
String timeStr =
'${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}';
if (messageDate == today) {
return timeStr; // 只显示时间,如 "14:30"
}
return timeStr; // 只显示时间,如 "14:30"
}
// else if (messageDate == yesterday) {
// return 'Yesterday $timeStr'; // 如 "Yesterday 14:30"
// }
// }
else {
// 国际通用日期格式 "MM-dd HH:mm"
return '${time.month.toString().padLeft(2, '0')}-${time.day.toString().padLeft(2, '0')} $timeStr';

94
lib/modules/chat/views/weather_day_card.dart

@ -0,0 +1,94 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class WeatherDayCard extends StatelessWidget {
final Map? data;
final bool isDarkMode;
const WeatherDayCard(this.data, this.isDarkMode, {super.key});
@override
Widget build(BuildContext context) {
final Map weatherDays = data?['weatherDays'].first;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
weatherDays['date'],
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 10.sp,
),
),
Text(
'${weatherDays['maxTemperature']}°',
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 30.sp,
),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Icon(
Icons.sunny,
color: isDarkMode ? Colors.white : Colors.amber[600]!,
size: 18.w,
),
Text(
'${weatherDays['weatherCondition']},${weatherDays['windDirection']}',
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 14.sp,
),
),
Row(
children: [
Text(
'最\n高',
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 10.sp,
height: 1,
),
),
5.horizontalSpace,
Text(
'${weatherDays['maxTemperature']}°',
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 20.sp,
),
),
10.horizontalSpace,
Text(
'最\n低',
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 10.sp,
height: 1,
),
),
5.horizontalSpace,
Text(
'${weatherDays['minTemperature']}°',
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black,
fontSize: 20.sp,
),
),
],
),
],
),
],
);
}
}

21
lib/modules/meeting/controllers/meeting_record_controller.dart

@ -158,19 +158,9 @@ class MeetingRecordController extends GetxController
// 完成
void complete() async {
if (await Permission.storage.request().isGranted) {
EasyLoading.show();
await _pause();
_aiSummary();
} else {
Get.snackbar(
'error'.tr, // 错误
'请开启文件存储权限',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.1),
colorText: Colors.red,
);
}
EasyLoading.show();
await _pause();
_aiSummary();
}
void _aiSummary() async {
@ -217,8 +207,11 @@ class MeetingRecordController extends GetxController
meetingController.dataList.insert(0, {
'id': result,
'title': title,
'content': firstContent,
'content': firstContent.replaceAll("\n", ""),
'seconds': seconds.value,
'address': address.value,
'longitude': _longitude,
'latitude': _latitude,
'creationtime': creationTime,
});
Get.back();

Loading…
Cancel
Save