同步 oneApp 的代码

This commit is contained in:
2025-09-17 15:09:05 +08:00
parent 62924296b2
commit 33aef48f84
21 changed files with 597 additions and 186 deletions

View File

@@ -1,18 +0,0 @@
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'app.dart';
import 'package:provider/provider.dart';
import 'services/message_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!await Permission.microphone.isGranted) {
await Permission.microphone.request();
}
runApp(
ChangeNotifierProvider(
create: (_) => MessageService(),
child: const ChatAssistantApp(),
),
);
}

View File

@@ -1,4 +1,3 @@
import 'package:ai_chat_assistant/utils/assets_util.dart';
import 'package:flutter/material.dart';
import 'dart:ui';
import '../widgets/chat_box.dart';
@@ -127,18 +126,14 @@ class _PartScreenState extends State<PartScreen> {
children: [
Padding(
padding: const EdgeInsets.only(
top: 50,
left: 6,
right: 6,
bottom: 30),
top: 50, left: 6, right: 6, bottom: 30),
child: LayoutBuilder(
builder: (context, boxConstraints) {
return ChatBox(
scrollController: _scrollController,
messages: messageService.messages,
);
}
),
builder: (context, boxConstraints) {
return ChatBox(
scrollController: _scrollController,
messages: messageService.messages,
);
}),
),
Positioned(
top: 6,

View File

@@ -59,7 +59,8 @@ class ChatSseService {
txt = txt.substring(0, imgStart) + txt.substring(imgEnd + 1);
imgStart = txt.indexOf('![');
}
// 彻底移除 markdown 有序/无序列表序号(如 1.、2.、-、*、+
txt = txt.replaceAll(RegExp(r'(^|\n)[ \t]*[0-9]+\.[ \t]*'), '\n');
txt = txt.replaceAll(RegExp(r'(^|\n)[ \t]*[-\*\+][ \t]+'), '\n');
// 分句符
RegExp enders = isChinese ? zhEnders : enEnders;
@@ -76,14 +77,8 @@ class ChatSseService {
}
// 只在达到完整句子时调用 TtsUtil.send
for (final s in sentences) {
String ttsStr=CommonUtil.cleanText(s, true)+"\n";
ttsStr = ttsStr.replaceAllMapped(
RegExp(r'(?<!\s)(\d+)(?!\s)'),
(m) => ' ${m.group(1)} ',
);
print("发送数据到TTS: $ttsStr");
String ttsStr=CommonUtil.cleanText(s, true);
// print("发送数据到TTS: $ttsStr");
TtsUtil.send(ttsStr);
}
// 缓存剩余不完整部分

View File

@@ -21,7 +21,7 @@ import 'command_service.dart';
import 'package:fluttertoast/fluttertoast.dart';
class MessageService extends ChangeNotifier {
static const MethodChannel _asrChannel = MethodChannel('com.example.ai_chat_assistant/asr');
static const MethodChannel _asrChannel = MethodChannel('com.example.ai_chat_assistant/ali_sdk');
static final MessageService _instance = MessageService._internal();
@@ -61,7 +61,7 @@ class MessageService extends ChangeNotifier {
// final AudioRecorderService _audioService = AudioRecorderService();
// final VoiceRecognitionService _recognitionService = VoiceRecognitionService();
final TextClassificationService _classificationService =
TextClassificationService();
TextClassificationService();
final VehicleCommandService _vehicleCommandService = VehicleCommandService();
final List<ChatMessage> _messages = [];
@@ -106,7 +106,6 @@ class MessageService extends ChangeNotifier {
abortReply();
_latestUserMessageId = null;
_latestAssistantMessageId = null;
_isReplyAborted = false;
changeState(MessageServiceState.recording);
_latestUserMessageId = addMessage("", true, MessageStatus.listening);
_asrChannel.invokeMethod("startAsr");
@@ -138,6 +137,7 @@ class MessageService extends ChangeNotifier {
return;
}
try {
_isReplyAborted = false;
changeState(MessageServiceState.recognizing);
_asrChannel.invokeMethod("stopAsr");
_asrCompleter = Completer<String>();
@@ -227,7 +227,7 @@ class MessageService extends ChangeNotifier {
return;
}
final vehicleCommandResponse =
await _vehicleCommandService.getCommandFromText(text);
await _vehicleCommandService.getCommandFromText(text);
if (vehicleCommandResponse == null) {
if (_isReplyAborted) {
return;
@@ -269,12 +269,12 @@ class MessageService extends ChangeNotifier {
bool isSuccess;
if (containOpenAC && command.type == VehicleCommandType.changeACTemp) {
isSuccess = await Future.delayed(const Duration(milliseconds: 2000),
() => processCommand(command, isChinese));
() => processCommand(command, isChinese));
} else {
isSuccess = await processCommand(command, isChinese);
}
if (isSuccess) {
successCommandList.add(command.type.name);
successCommandList.add(isChinese ? command.type.chinese : command.type.english);
}
}
replaceMessage(
@@ -286,7 +286,7 @@ class MessageService extends ChangeNotifier {
return;
}
String controlResponse =
await _vehicleCommandService.getControlResponse(successCommandList);
await _vehicleCommandService.getControlResponse(successCommandList);
if (_isReplyAborted || controlResponse.isEmpty) {
return;
}

View File

@@ -2,7 +2,7 @@ import 'package:flutter/services.dart';
class TtsUtil {
static const MethodChannel _channel =
MethodChannel('com.example.ai_chat_assistant/tts');
MethodChannel('com.example.ai_chat_assistant/ali_sdk');
static Future<T?> execute<T>(String method,
[Map<Object, Object>? arguments]) {

View File

@@ -123,7 +123,12 @@ class _ChatBubbleState extends State<ChatBubble> {
break;
case MessageStatus.completed:
case MessageStatus.success:
icon = Image.asset('assets/images/checked.png', width: 20, height: 20, package: 'ai_chat_assistant',);
icon = Image.asset(
'assets/images/checked.png',
width: 20,
height: 20,
package: 'ai_chat_assistant',
);
color = Colors.white;
break;
case MessageStatus.failure:
@@ -301,8 +306,10 @@ class _ChatBubbleState extends State<ChatBubble> {
},
child: Padding(
padding: const EdgeInsets.only(left: 12),
child: Image.asset('assets/images/copy.png',package: 'ai_chat_assistant',
width: 22, height: 22),
child: Image.asset('assets/images/copy.png',
package: 'ai_chat_assistant',
width: 22,
height: 22),
),
),
InkWell(
@@ -315,10 +322,14 @@ class _ChatBubbleState extends State<ChatBubble> {
child: Padding(
padding: const EdgeInsets.only(left: 12),
child: _liked
? Image.asset('assets/images/liked2.png',package: 'ai_chat_assistant',
width: 22, height: 22)
: Image.asset('assets/images/liked1.png',package: 'ai_chat_assistant',
width: 22, height: 22),
? Image.asset('assets/images/liked2.png',
package: 'ai_chat_assistant',
width: 22,
height: 22)
: Image.asset('assets/images/liked1.png',
package: 'ai_chat_assistant',
width: 22,
height: 22),
),
),
InkWell(
@@ -331,10 +342,14 @@ class _ChatBubbleState extends State<ChatBubble> {
child: Padding(
padding: const EdgeInsets.only(left: 12),
child: _disliked
? Image.asset('assets/images/disliked2.png',package: 'ai_chat_assistant',
width: 22, height: 22)
: Image.asset('assets/images/disliked1.png',package: 'ai_chat_assistant',
width: 22, height: 22)),
? Image.asset('assets/images/disliked2.png',
package: 'ai_chat_assistant',
width: 22,
height: 22)
: Image.asset('assets/images/disliked1.png',
package: 'ai_chat_assistant',
width: 22,
height: 22)),
),
],
),

View File

@@ -44,7 +44,7 @@ class ChatHeader extends StatelessWidget {
? '您的专属看、选、买、用车助手'
: 'Your exclusive assistant',
style: TextStyle(
fontSize: 12,
fontSize: 11,
color: Colors.white70,
),
),