Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
F
flutter-chat
Project
Project
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
Graph
比较
统计图
议题
0
议题
0
列表
看板
标记
Milestones
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
songchuancai
flutter-chat
Commits
c2c63647
提交
c2c63647
authored
11月 12, 2024
作者:
songchuancai
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
增加会话名称自动生成
上级
0f950dc7
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
982 行增加
和
910 行删除
+982
-910
home_page.dart
lib/home_page.dart
+939
-908
chat_page.dart
lib/pages/chat_page.dart
+10
-0
chat_service.dart
lib/services/chat_service.dart
+31
-0
GeneratedPluginRegistrant.swift
macos/Flutter/GeneratedPluginRegistrant.swift
+2
-2
没有找到文件。
lib/home_page.dart
浏览文件 @
c2c63647
import
'package:allen/pallete.dart'
;
import
'package:allen/pallete.dart'
;
import
'package:animate_do/animate_do.dart'
;
import
'package:animate_do/animate_do.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_tts/flutter_tts.dart'
;
import
'package:flutter_tts/flutter_tts.dart'
;
import
'package:speech_to_text/speech_recognition_result.dart'
;
import
'package:speech_to_text/speech_recognition_result.dart'
;
import
'package:speech_to_text/speech_to_text.dart'
;
import
'package:speech_to_text/speech_to_text.dart'
;
import
'package:flutter/foundation.dart'
show
kIsWeb
;
import
'package:flutter/foundation.dart'
show
kIsWeb
;
import
'package:uuid/uuid.dart'
;
import
'package:uuid/uuid.dart'
;
import
'models/conversation.dart'
;
import
'models/conversation.dart'
;
import
'services/storage_service.dart'
;
import
'services/storage_service.dart'
;
import
'services/chat_service.dart'
;
import
'services/chat_service.dart'
;
import
'models/chat_message.dart'
;
import
'models/chat_message.dart'
;
import
'models/user.dart'
;
import
'models/user.dart'
;
import
'package:shared_preferences/shared_preferences.dart'
;
import
'package:shared_preferences/shared_preferences.dart'
;
import
'pages/apps_page.dart'
;
import
'pages/apps_page.dart'
;
import
'pages/chat_bubble.dart'
;
import
'pages/chat_bubble.dart'
;
class
HomePage
extends
StatefulWidget
{
class
HomePage
extends
StatefulWidget
{
final
String
?
customTitle
;
final
String
?
customTitle
;
final
String
?
customDescription
;
final
String
?
customDescription
;
final
String
?
customImageUrl
;
final
String
?
customImageUrl
;
final
bool
hideNavigation
;
final
bool
hideNavigation
;
const
HomePage
({
final
OpenAIService
?
openAIService
;
super
.
key
,
this
.
customTitle
,
const
HomePage
({
this
.
customDescription
,
super
.
key
,
this
.
customImageUrl
,
this
.
customTitle
,
this
.
hideNavigation
=
false
,
this
.
customDescription
,
});
this
.
customImageUrl
,
this
.
hideNavigation
=
false
,
@override
this
.
openAIService
,
State
<
HomePage
>
createState
()
=>
_HomePageState
();
});
}
@override
class
_HomePageState
extends
State
<
HomePage
>
{
State
<
HomePage
>
createState
()
=>
_HomePageState
();
final
speechToText
=
SpeechToText
();
}
final
flutterTts
=
FlutterTts
();
class
_HomePageState
extends
State
<
HomePage
>
{
final
speechToText
=
SpeechToText
();
String
lastWords
=
''
;
final
flutterTts
=
FlutterTts
();
final
OpenAIService
openAIService
=
OpenAIService
();
String
lastWords
=
''
;
String
?
generatedContent
;
late
OpenAIService
openAIService
;
String
?
generatedImageUrl
;
String
?
generatedContent
;
int
start
=
200
;
String
?
generatedImageUrl
;
int
delay
=
200
;
int
start
=
200
;
final
TextEditingController
_messageController
=
TextEditingController
();
int
delay
=
200
;
String
currentStreamedContent
=
''
;
final
TextEditingController
_messageController
=
TextEditingController
();
List
<
ChatMessage
>
messages
=
[];
String
currentStreamedContent
=
''
;
bool
_isLoading
=
false
;
List
<
ChatMessage
>
messages
=
[];
bool
_isVoiceMode
=
true
;
bool
_isLoading
=
false
;
bool
_isListeningPressed
=
false
;
bool
_isVoiceMode
=
true
;
String
_currentVoiceText
=
''
;
bool
_isListeningPressed
=
false
;
late
StorageService
_storageService
;
String
_currentVoiceText
=
''
;
late
SharedPreferences
_prefs
;
late
StorageService
_storageService
;
late
Conversation
_currentConversation
;
late
SharedPreferences
_prefs
;
List
<
Conversation
>
_conversations
=
[];
late
Conversation
_currentConversation
;
int
_currentIndex
=
0
;
List
<
Conversation
>
_conversations
=
[];
bool
_hasSpeechPermission
=
false
;
int
_currentIndex
=
0
;
@override
void
initState
()
{
bool
_hasSpeechPermission
=
false
;
super
.
initState
();
@override
_initializeStorage
();
void
initState
()
{
super
.
initState
();
initSpeechToText
();
_initializeStorage
();
_initTts
();
}
initSpeechToText
();
Future
<
void
>
_initializeStorage
()
async
{
_initTts
();
_prefs
=
await
SharedPreferences
.
getInstance
();
openAIService
=
widget
.
openAIService
??
OpenAIService
();
_storageService
=
StorageService
(
_prefs
);
}
_conversations
=
await
_storageService
.
getConversations
();
Future
<
void
>
_initializeStorage
()
async
{
_prefs
=
await
SharedPreferences
.
getInstance
();
// 每次进入应用创建一个新的会话
_createNewConversation
();
_storageService
=
StorageService
(
_prefs
);
// if (_conversations.isEmpty) {
// _createNewConversation();
_conversations
=
await
_storageService
.
getConversations
();
// } else {
// _currentConversation = _conversations.first;
// 每次进入应用创建一个新的会话
// setState(() {
_createNewConversation
();
// messages = _currentConversation.messages;
// });
// if (_conversations.isEmpty) {
// }
}
// _createNewConversation();
Future
<
void
>
_createNewConversation
()
async
{
// } else {
final
newConversation
=
Conversation
(
id:
const
Uuid
().
v4
(),
// _currentConversation = _conversations.first;
title:
'新会话
${_conversations.length + 1}
'
,
createdAt:
DateTime
.
now
(),
// setState(() {
messages:
[],
);
// messages = _currentConversation.messages;
await
_storageService
.
addConversation
(
newConversation
);
// });
setState
(()
{
// }
_conversations
.
insert
(
0
,
newConversation
);
}
_currentConversation
=
newConversation
;
Future
<
void
>
_createNewConversation
()
async
{
final
newConversation
=
Conversation
(
messages
=
[];
id:
const
Uuid
().
v4
(),
});
title:
'新会话
${_conversations.length + 1}
'
,
}
createdAt:
DateTime
.
now
(),
messages:
[],
Future
<
void
>
_updateCurrentConversation
()
async
{
);
_currentConversation
=
Conversation
(
id:
_currentConversation
.
id
,
await
_storageService
.
addConversation
(
newConversation
);
title:
_currentConversation
.
title
,
createdAt:
_currentConversation
.
createdAt
,
setState
(()
{
messages:
messages
,
_conversations
.
insert
(
0
,
newConversation
);
);
_currentConversation
=
newConversation
;
await
_storageService
.
updateConversation
(
_currentConversation
);
}
messages
=
[];
});
Future
<
void
>
_initTts
()
async
{
}
if
(!
kIsWeb
)
{
await
flutterTts
.
setSharedInstance
(
true
);
Future
<
void
>
_updateCurrentConversation
()
async
{
}
_currentConversation
=
Conversation
(
id:
_currentConversation
.
id
,
setState
(()
{});
title:
_currentConversation
.
title
,
}
createdAt:
_currentConversation
.
createdAt
,
messages:
messages
,
Future
<
void
>
initSpeechToText
()
async
{
);
try
{
_hasSpeechPermission
=
await
speechToText
.
initialize
(
await
_storageService
.
updateConversation
(
_currentConversation
);
onStatus:
(
status
)
{
}
print
(
'语音状态:
$status
'
);
if
(
status
==
'notListening'
)
{
Future
<
void
>
_initTts
()
async
{
setState
(()
=>
_isListeningPressed
=
false
);
if
(!
kIsWeb
)
{
}
await
flutterTts
.
setSharedInstance
(
true
);
},
}
onError:
(
error
)
{
print
(
'语音错误:
$error
'
);
setState
(()
{});
setState
(()
=>
_isListeningPressed
=
false
);
}
_showErrorDialog
(
'语音初始化失败,请检查麦克风权限'
);
},
Future
<
void
>
initSpeechToText
()
async
{
);
try
{
}
catch
(
e
)
{
_hasSpeechPermission
=
await
speechToText
.
initialize
(
print
(
'语音初始化错误:
$e
'
);
onStatus:
(
status
)
{
_hasSpeechPermission
=
false
;
print
(
'语音状态:
$status
'
);
}
setState
(()
{});
if
(
status
==
'notListening'
)
{
}
setState
(()
=>
_isListeningPressed
=
false
);
}
Future
<
void
>
startListening
()
async
{
},
if
(!
_hasSpeechPermission
)
{
onError:
(
error
)
{
_showErrorDialog
(
'请先授予麦克风权限'
);
print
(
'语音错误:
$error
'
);
setState
(()
=>
_isListeningPressed
=
false
);
return
;
setState
(()
=>
_isListeningPressed
=
false
);
}
_showErrorDialog
(
'语音初始化失败,请检查麦克风权限'
);
try
{
},
await
speechToText
.
listen
(
);
onResult:
onSpeechResult
,
}
catch
(
e
)
{
localeId:
'zh_CN'
,
print
(
'语音初始化错误:
$e
'
);
listenMode:
ListenMode
.
confirmation
,
cancelOnError:
true
,
_hasSpeechPermission
=
false
;
partialResults:
true
,
}
);
}
catch
(
e
)
{
setState
(()
{});
print
(
'开始录音失败:
$e
'
);
}
setState
(()
=>
_isListeningPressed
=
false
);
_showErrorDialog
(
'启动语音识别失败,请重试'
);
Future
<
void
>
startListening
()
async
{
}
if
(!
_hasSpeechPermission
)
{
}
_showErrorDialog
(
'请先授予麦克风权限'
);
Future
<
void
>
stopListening
()
async
{
setState
(()
=>
_isListeningPressed
=
false
);
await
speechToText
.
stop
();
return
;
setState
(()
{});
}
}
try
{
Future
<
void
>
onSpeechResult
(
SpeechRecognitionResult
result
)
async
{
await
speechToText
.
listen
(
setState
(()
{
onResult:
onSpeechResult
,
lastWords
=
result
.
recognizedWords
;
localeId:
'zh_CN'
,
listenMode:
ListenMode
.
confirmation
,
_currentVoiceText
=
result
.
recognizedWords
;
cancelOnError:
true
,
});
partialResults:
true
,
}
);
}
catch
(
e
)
{
Future
<
void
>
systemSpeak
(
String
content
)
async
{
print
(
'开始录音失败:
$e
'
);
try
{
if
(
kIsWeb
)
{
setState
(()
=>
_isListeningPressed
=
false
);
// 设置语速
_showErrorDialog
(
'启动语音识别失败,请重试'
);
await
flutterTts
.
setSpeechRate
(
1
);
}
}
// 音调
Future
<
void
>
stopListening
()
async
{
await
flutterTts
.
setPitch
(
0.8
);
await
speechToText
.
stop
();
await
flutterTts
.
speak
(
content
);
setState
(()
{});
}
else
{
}
await
flutterTts
.
setSharedInstance
(
true
);
Future
<
void
>
onSpeechResult
(
SpeechRecognitionResult
result
)
async
{
await
flutterTts
.
speak
(
content
);
setState
(()
{
}
lastWords
=
result
.
recognizedWords
;
}
catch
(
e
)
{
print
(
'TTS Error:
$e
'
);
_currentVoiceText
=
result
.
recognizedWords
;
}
});
}
}
Future
<
void
>
_sendMessage
()
async
{
Future
<
void
>
systemSpeak
(
String
content
)
async
{
if
(!
mounted
)
return
;
// 添加这行
try
{
if
(
kIsWeb
)
{
if
(
_messageController
.
text
.
isEmpty
)
return
;
// 设置语速
String
userMessage
=
_messageController
.
text
;
await
flutterTts
.
setSpeechRate
(
1
);
_messageController
.
clear
();
// 音调
setState
(()
{
await
flutterTts
.
setPitch
(
0.8
);
messages
.
add
(
ChatMessage
(
text:
userMessage
,
await
flutterTts
.
speak
(
content
);
isUserMessage:
true
,
}
else
{
));
await
flutterTts
.
setSharedInstance
(
true
);
currentStreamedContent
=
''
;
await
flutterTts
.
speak
(
content
);
}
_isLoading
=
true
;
}
catch
(
e
)
{
});
print
(
'TTS Error:
$e
'
);
}
try
{
}
String
fullResponse
=
''
;
Future
<
void
>
_sendMessage
()
async
{
bool
isFirstChunk
=
true
;
if
(!
mounted
)
return
;
// 添加这行
// 创建一个缓冲区来存储收到的文本
if
(
_messageController
.
text
.
isEmpty
)
return
;
StringBuffer
buffer
=
StringBuffer
();
String
userMessage
=
_messageController
.
text
;
await
for
(
final
chunk
in
openAIService
.
chatGPTAPI
(
userMessage
))
{
_messageController
.
clear
();
buffer
.
write
(
chunk
);
setState
(()
{
// 逐字显示文本
messages
.
add
(
ChatMessage
(
text:
userMessage
,
for
(
int
i
=
fullResponse
.
length
;
i
<
buffer
.
length
;
i
++)
{
isUserMessage:
true
,
setState
(()
{
));
fullResponse
+=
buffer
.
toString
()[
i
];
currentStreamedContent
=
''
;
if
(
isFirstChunk
&&
i
==
0
)
{
messages
.
add
(
ChatMessage
(
_isLoading
=
true
;
text:
fullResponse
,
});
isUserMessage:
false
,
));
try
{
String
fullResponse
=
''
;
isFirstChunk
=
false
;
}
else
{
bool
isFirstChunk
=
true
;
messages
.
last
=
ChatMessage
(
text:
fullResponse
,
// 创建一个缓冲区来存储收到的文本
isUserMessage:
false
,
);
StringBuffer
buffer
=
StringBuffer
();
}
});
await
for
(
final
chunk
in
openAIService
.
chatGPTAPI
(
userMessage
))
{
buffer
.
write
(
chunk
);
// 添加短暂延迟以创建打字效果
// 逐字显示文本
await
Future
.
delayed
(
const
Duration
(
milliseconds:
50
));
}
for
(
int
i
=
fullResponse
.
length
;
i
<
buffer
.
length
;
i
++)
{
}
setState
(()
{
fullResponse
+=
buffer
.
toString
()[
i
];
//await systemSpeak(fullResponse);
if
(
isFirstChunk
&&
i
==
0
)
{
await
_updateCurrentConversation
();
messages
.
add
(
ChatMessage
(
}
catch
(
e
)
{
text:
fullResponse
,
setState
(()
{
isUserMessage:
false
,
messages
.
add
(
ChatMessage
(
));
text:
'抱歉,出现了一些错误:
$e
'
,
isUserMessage:
false
,
isFirstChunk
=
false
;
));
}
else
{
});
messages
.
last
=
ChatMessage
(
}
finally
{
text:
fullResponse
,
setState
(()
{
isUserMessage:
false
,
_isLoading
=
false
;
);
});
}
}
});
}
// 添加短暂延迟以创建打字效果
Future
<
void
>
_processAIResponse
(
String
userInput
)
async
{
try
{
await
Future
.
delayed
(
const
Duration
(
milliseconds:
50
));
String
fullResponse
=
''
;
}
}
bool
isFirstChunk
=
true
;
//await systemSpeak(fullResponse);
// 创建一个缓冲区来储收到的文本
await
_updateCurrentConversation
();
StringBuffer
buffer
=
StringBuffer
();
}
catch
(
e
)
{
setState
(()
{
await
for
(
final
chunk
in
openAIService
.
chatGPTAPI
(
userInput
))
{
messages
.
add
(
ChatMessage
(
buffer
.
write
(
chunk
);
text:
'抱歉,出现了一些错误:
$e
'
,
isUserMessage:
false
,
// 逐字显示文本
));
});
for
(
int
i
=
fullResponse
.
length
;
i
<
buffer
.
length
;
i
++)
{
}
finally
{
setState
(()
{
setState
(()
{
fullResponse
+=
buffer
.
toString
()[
i
];
_isLoading
=
false
;
});
if
(
isFirstChunk
&&
i
==
0
)
{
}
messages
.
add
(
ChatMessage
(
}
text:
fullResponse
,
isUserMessage:
false
,
Future
<
void
>
_processAIResponse
(
String
userInput
)
async
{
));
try
{
String
fullResponse
=
''
;
isFirstChunk
=
false
;
}
else
{
bool
isFirstChunk
=
true
;
messages
.
last
=
ChatMessage
(
text:
fullResponse
,
// 创建一个缓冲区来储收到的文本
isUserMessage:
false
,
);
StringBuffer
buffer
=
StringBuffer
();
}
});
await
for
(
final
chunk
in
openAIService
.
chatGPTAPI
(
userInput
))
{
buffer
.
write
(
chunk
);
// 添加短暂延迟以创建打字效果
// 逐字显示文本
await
Future
.
delayed
(
const
Duration
(
milliseconds:
50
));
}
for
(
int
i
=
fullResponse
.
length
;
i
<
buffer
.
length
;
i
++)
{
}
setState
(()
{
fullResponse
+=
buffer
.
toString
()[
i
];
// await systemSpeak(fullResponse);
if
(
isFirstChunk
&&
i
==
0
)
{
await
_updateCurrentConversation
();
messages
.
add
(
ChatMessage
(
}
catch
(
e
)
{
text:
fullResponse
,
setState
(()
{
isUserMessage:
false
,
messages
.
add
(
ChatMessage
(
));
text:
'抱歉,出现了一些错误:
$e
'
,
isUserMessage:
false
,
isFirstChunk
=
false
;
));
}
else
{
});
messages
.
last
=
ChatMessage
(
}
finally
{
text:
fullResponse
,
setState
(()
{
isUserMessage:
false
,
_isLoading
=
false
;
);
});
}
}
});
}
// 添加短暂延迟以创建打字效果
@override
void
dispose
()
{
await
Future
.
delayed
(
const
Duration
(
milliseconds:
50
));
super
.
dispose
();
}
}
speechToText
.
stop
();
// await systemSpeak(fullResponse);
flutterTts
.
stop
();
await
_updateCurrentConversation
();
_messageController
.
dispose
();
}
catch
(
e
)
{
}
setState
(()
{
messages
.
add
(
ChatMessage
(
Widget
_buildBottomInput
()
{
text:
'抱歉,出现了一些错误:
$e
'
,
return
Container
(
isUserMessage:
false
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
));
decoration:
BoxDecoration
(
});
color:
Colors
.
white
,
}
finally
{
boxShadow:
[
setState
(()
{
BoxShadow
(
_isLoading
=
false
;
color:
Colors
.
grey
.
withOpacity
(
0.1
),
});
spreadRadius:
1
,
}
blurRadius:
3
,
}
offset:
const
Offset
(
0
,
-
1
),
),
@override
],
void
dispose
()
{
),
super
.
dispose
();
child:
Row
(
children:
[
speechToText
.
stop
();
Expanded
(
child:
_isVoiceMode
flutterTts
.
stop
();
?
GestureDetector
(
onTap:
()
async
{
_messageController
.
dispose
();
if
(!
_isListeningPressed
)
{
}
// 开始录音
setState
(()
{
Widget
_buildBottomInput
()
{
_isListeningPressed
=
true
;
return
Container
(
_currentVoiceText
=
''
;
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
});
decoration:
BoxDecoration
(
await
startListening
();
color:
Colors
.
white
,
}
else
{
boxShadow:
[
// 停止录音
BoxShadow
(
setState
(()
=>
_isListeningPressed
=
false
);
color:
Colors
.
grey
.
withOpacity
(
0.1
),
await
stopListening
();
spreadRadius:
1
,
blurRadius:
3
,
// 确保有语音文本才处理
offset:
const
Offset
(
0
,
-
1
),
if
(
_currentVoiceText
.
isNotEmpty
)
{
),
setState
(()
{
],
messages
.
add
(
ChatMessage
(
),
text:
_currentVoiceText
,
child:
Row
(
isUserMessage:
true
,
children:
[
));
Expanded
(
_isLoading
=
true
;
child:
_isVoiceMode
});
?
GestureDetector
(
await
_processAIResponse
(
_currentVoiceText
);
onTap:
()
async
{
}
if
(!
_isListeningPressed
)
{
setState
(()
=>
_currentVoiceText
=
''
);
// 开始录音
}
},
setState
(()
{
child:
Container
(
_isListeningPressed
=
true
;
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
_currentVoiceText
=
''
;
vertical:
10
,
});
),
decoration:
BoxDecoration
(
await
startListening
();
color:
Colors
.
grey
[
100
],
}
else
{
borderRadius:
BorderRadius
.
circular
(
25
),
// 停止录音
),
child:
Row
(
setState
(()
=>
_isListeningPressed
=
false
);
mainAxisSize:
MainAxisSize
.
min
,
children:
[
await
stopListening
();
Icon
(
_isListeningPressed
?
Icons
.
stop
:
Icons
.
mic
,
// 确保有语音文本才处理
color:
_isListeningPressed
?
Pallete
.
firstSuggestionBoxColor
if
(
_currentVoiceText
.
isNotEmpty
)
{
:
Colors
.
grey
[
600
],
setState
(()
{
),
messages
.
add
(
ChatMessage
(
const
SizedBox
(
width:
8
),
text:
_currentVoiceText
,
Text
(
isUserMessage:
true
,
_isListeningPressed
));
?
(
_currentVoiceText
.
isEmpty
?
'点击停止'
:
_currentVoiceText
)
:
'点击说话'
,
_isLoading
=
true
;
textAlign:
TextAlign
.
center
,
});
style:
TextStyle
(
color:
_isListeningPressed
await
_processAIResponse
(
_currentVoiceText
);
?
Pallete
.
firstSuggestionBoxColor
}
:
Colors
.
grey
[
600
],
),
setState
(()
=>
_currentVoiceText
=
''
);
),
}
],
},
),
child:
Container
(
),
padding:
const
EdgeInsets
.
symmetric
(
)
horizontal:
20
,
:
TextField
(
vertical:
10
,
controller:
_messageController
,
),
decoration:
InputDecoration
(
decoration:
BoxDecoration
(
hintText:
'输入消息...'
,
color:
Colors
.
grey
[
100
],
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
25
),
borderRadius:
BorderRadius
.
circular
(
25
),
),
borderSide:
BorderSide
.
none
,
child:
Row
(
),
mainAxisSize:
MainAxisSize
.
min
,
filled:
true
,
children:
[
fillColor:
Colors
.
grey
[
100
],
Icon
(
contentPadding:
const
EdgeInsets
.
symmetric
(
_isListeningPressed
?
Icons
.
stop
:
Icons
.
mic
,
horizontal:
20
,
color:
_isListeningPressed
vertical:
10
,
?
Pallete
.
firstSuggestionBoxColor
),
:
Colors
.
grey
[
600
],
),
),
),
const
SizedBox
(
width:
8
),
),
Text
(
const
SizedBox
(
width:
8
),
_isListeningPressed
IconButton
(
?
(
_currentVoiceText
.
isEmpty
icon:
Icon
(
?
'点击停止'
_isVoiceMode
?
Icons
.
keyboard
:
Icons
.
mic
,
:
_currentVoiceText
)
color:
Pallete
.
firstSuggestionBoxColor
,
:
'点击说话'
,
),
textAlign:
TextAlign
.
center
,
onPressed:
()
{
style:
TextStyle
(
setState
(()
=>
_isVoiceMode
=
!
_isVoiceMode
);
color:
_isListeningPressed
},
?
Pallete
.
firstSuggestionBoxColor
),
:
Colors
.
grey
[
600
],
if
(!
_isVoiceMode
)
),
IconButton
(
),
icon:
const
Icon
(
],
Icons
.
send
,
),
color:
Pallete
.
firstSuggestionBoxColor
,
),
),
)
onPressed:
_sendMessage
,
:
TextField
(
),
controller:
_messageController
,
],
decoration:
InputDecoration
(
),
hintText:
'输入消息...'
,
);
border:
OutlineInputBorder
(
}
borderRadius:
BorderRadius
.
circular
(
25
),
borderSide:
BorderSide
.
none
,
AppBar
_buildAppBar
()
{
),
return
AppBar
(
filled:
true
,
title:
Row
(
fillColor:
Colors
.
grey
[
100
],
mainAxisAlignment:
MainAxisAlignment
.
center
,
contentPadding:
const
EdgeInsets
.
symmetric
(
children:
[
horizontal:
20
,
TextButton
(
vertical:
10
,
onPressed:
()
{
),
setState
(()
=>
_currentIndex
=
0
);
),
},
),
child:
Text
(
),
'对话'
,
const
SizedBox
(
width:
8
),
style:
TextStyle
(
IconButton
(
fontSize:
_currentIndex
==
0
?
20
:
16
,
icon:
Icon
(
fontWeight:
_isVoiceMode
?
Icons
.
keyboard
:
Icons
.
mic
,
_currentIndex
==
0
?
FontWeight
.
bold
:
FontWeight
.
normal
,
color:
Pallete
.
firstSuggestionBoxColor
,
color:
_currentIndex
==
0
),
?
Pallete
.
firstSuggestionBoxColor
onPressed:
()
{
:
Colors
.
grey
,
setState
(()
=>
_isVoiceMode
=
!
_isVoiceMode
);
),
},
),
),
),
if
(!
_isVoiceMode
)
const
SizedBox
(
width:
20
),
IconButton
(
TextButton
(
icon:
const
Icon
(
onPressed:
()
{
Icons
.
send
,
setState
(()
=>
_currentIndex
=
1
);
color:
Pallete
.
firstSuggestionBoxColor
,
},
),
child:
Text
(
onPressed:
_sendMessage
,
'应用'
,
),
style:
TextStyle
(
],
fontSize:
_currentIndex
==
1
?
20
:
16
,
),
fontWeight:
);
_currentIndex
==
1
?
FontWeight
.
bold
:
FontWeight
.
normal
,
}
color:
_currentIndex
==
1
?
Pallete
.
firstSuggestionBoxColor
AppBar
_buildAppBar
()
{
:
Colors
.
grey
,
return
AppBar
(
),
title:
Row
(
),
mainAxisAlignment:
MainAxisAlignment
.
center
,
),
children:
[
],
TextButton
(
),
onPressed:
()
{
leading:
Builder
(
setState
(()
=>
_currentIndex
=
0
);
builder:
(
context
)
=>
IconButton
(
},
icon:
const
Icon
(
Icons
.
menu
),
child:
Text
(
onPressed:
()
=>
Scaffold
.
of
(
context
).
openDrawer
(),
'对话'
,
),
style:
TextStyle
(
),
fontSize:
_currentIndex
==
0
?
20
:
16
,
);
fontWeight:
}
_currentIndex
==
0
?
FontWeight
.
bold
:
FontWeight
.
normal
,
color:
_currentIndex
==
0
Widget
_buildDrawer
(
BuildContext
context
)
{
?
Pallete
.
firstSuggestionBoxColor
return
Drawer
(
:
Colors
.
grey
,
child:
Column
(
),
children:
[
),
DrawerHeader
(
),
decoration:
BoxDecoration
(
const
SizedBox
(
width:
20
),
color:
Pallete
.
firstSuggestionBoxColor
,
TextButton
(
),
onPressed:
()
{
child:
const
Center
(
setState
(()
=>
_currentIndex
=
1
);
child:
Text
(
},
'会话列表'
,
child:
Text
(
style:
TextStyle
(
'应用'
,
color:
Colors
.
white
,
style:
TextStyle
(
fontSize:
24
,
fontSize:
_currentIndex
==
1
?
20
:
16
,
),
fontWeight:
),
_currentIndex
==
1
?
FontWeight
.
bold
:
FontWeight
.
normal
,
),
color:
_currentIndex
==
1
),
?
Pallete
.
firstSuggestionBoxColor
ListTile
(
:
Colors
.
grey
,
leading:
const
Icon
(
Icons
.
add
),
),
title:
const
Text
(
'新建会话'
),
),
onTap:
()
{
),
_createNewConversation
();
],
),
Navigator
.
pop
(
context
);
leading:
Builder
(
},
builder:
(
context
)
=>
IconButton
(
),
icon:
const
Icon
(
Icons
.
menu
),
Expanded
(
onPressed:
()
=>
Scaffold
.
of
(
context
).
openDrawer
(),
child:
ListView
.
builder
(
),
itemCount:
_conversations
.
length
,
),
itemBuilder:
(
context
,
index
)
{
);
final
conversation
=
_conversations
[
index
];
}
return
ListTile
(
Widget
_buildDrawer
(
BuildContext
context
)
{
leading:
const
Icon
(
Icons
.
chat
),
return
Drawer
(
title:
Text
(
conversation
.
title
),
child:
Column
(
subtitle:
Text
(
children:
[
conversation
.
messages
.
isEmpty
DrawerHeader
(
?
'暂无消息'
decoration:
BoxDecoration
(
:
conversation
.
messages
.
last
.
text
,
color:
Pallete
.
firstSuggestionBoxColor
,
maxLines:
1
,
),
overflow:
TextOverflow
.
ellipsis
,
child:
const
Center
(
),
child:
Text
(
selected:
_currentConversation
.
id
==
conversation
.
id
,
'会话列表'
,
onTap:
()
{
style:
TextStyle
(
setState
(()
{
color:
Colors
.
white
,
_currentConversation
=
conversation
;
fontSize:
24
,
),
messages
=
conversation
.
messages
;
),
});
),
),
Navigator
.
pop
(
context
);
ListTile
(
},
leading:
const
Icon
(
Icons
.
add
),
trailing:
IconButton
(
title:
const
Text
(
'新建会话'
),
icon:
const
Icon
(
Icons
.
delete
),
onTap:
()
{
onPressed:
()
async
{
_createNewConversation
();
await
_storageService
.
deleteConversation
(
conversation
.
id
);
Navigator
.
pop
(
context
);
setState
(()
{
},
_conversations
.
removeAt
(
index
);
),
Expanded
(
if
(
_currentConversation
.
id
==
conversation
.
id
)
{
child:
ListView
.
builder
(
if
(
_conversations
.
isEmpty
)
{
itemCount:
_conversations
.
length
,
_createNewConversation
();
itemBuilder:
(
context
,
index
)
{
}
else
{
final
conversation
=
_conversations
[
index
];
_currentConversation
=
_conversations
.
first
;
return
ListTile
(
messages
=
_currentConversation
.
messages
;
leading:
const
Icon
(
Icons
.
chat
),
}
title:
Text
(
conversation
.
title
),
}
subtitle:
Text
(
});
conversation
.
messages
.
isEmpty
},
?
'暂无消息'
),
:
conversation
.
messages
.
last
.
text
,
);
maxLines:
1
,
},
overflow:
TextOverflow
.
ellipsis
,
),
),
),
selected:
_currentConversation
.
id
==
conversation
.
id
,
const
Spacer
(),
onTap:
()
{
const
Divider
(
height:
1
),
setState
(()
{
FutureBuilder
<
User
?>(
_currentConversation
=
conversation
;
future:
StorageService
.
getUser
(),
builder:
(
context
,
snapshot
)
{
messages
=
conversation
.
messages
;
if
(!
snapshot
.
hasData
)
return
const
SizedBox
();
});
return
Container
(
Navigator
.
pop
(
context
);
padding:
const
EdgeInsets
.
all
(
16
),
},
decoration:
BoxDecoration
(
trailing:
IconButton
(
color:
Colors
.
grey
[
50
],
icon:
const
Icon
(
Icons
.
delete
),
),
onPressed:
()
async
{
child:
Column
(
await
_storageService
.
deleteConversation
(
conversation
.
id
);
children:
[
Row
(
setState
(()
{
children:
[
_conversations
.
removeAt
(
index
);
Container
(
width:
50
,
if
(
_currentConversation
.
id
==
conversation
.
id
)
{
height:
50
,
if
(
_conversations
.
isEmpty
)
{
decoration:
BoxDecoration
(
_createNewConversation
();
color:
Pallete
.
firstSuggestionBoxColor
,
}
else
{
shape:
BoxShape
.
circle
,
_currentConversation
=
_conversations
.
first
;
),
child:
Center
(
messages
=
_currentConversation
.
messages
;
child:
Text
(
}
snapshot
.
data
!.
username
[
0
].
toUpperCase
(),
}
style:
const
TextStyle
(
});
color:
Colors
.
white
,
},
fontSize:
24
,
),
fontWeight:
FontWeight
.
bold
,
);
),
},
),
),
),
),
),
const
Spacer
(),
const
SizedBox
(
width:
16
),
const
Divider
(
height:
1
),
Expanded
(
FutureBuilder
<
User
?>(
child:
Column
(
future:
StorageService
.
getUser
(),
crossAxisAlignment:
CrossAxisAlignment
.
start
,
builder:
(
context
,
snapshot
)
{
children:
[
if
(!
snapshot
.
hasData
)
return
const
SizedBox
();
Text
(
snapshot
.
data
!.
username
,
return
Container
(
style:
const
TextStyle
(
padding:
const
EdgeInsets
.
all
(
16
),
fontSize:
18
,
decoration:
BoxDecoration
(
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
grey
[
50
],
),
),
),
child:
Column
(
const
SizedBox
(
height:
4
),
children:
[
Text
(
Row
(
'在线'
,
children:
[
style:
TextStyle
(
Container
(
fontSize:
14
,
width:
50
,
color:
Colors
.
green
[
600
],
height:
50
,
),
decoration:
BoxDecoration
(
),
color:
Pallete
.
firstSuggestionBoxColor
,
],
shape:
BoxShape
.
circle
,
),
),
),
child:
Center
(
],
child:
Text
(
),
snapshot
.
data
!.
username
[
0
].
toUpperCase
(),
const
SizedBox
(
height:
16
),
style:
const
TextStyle
(
InkWell
(
color:
Colors
.
white
,
onTap:
()
async
{
fontSize:
24
,
final
confirmed
=
await
showDialog
<
bool
>(
fontWeight:
FontWeight
.
bold
,
context:
context
,
),
builder:
(
context
)
=>
AlertDialog
(
),
title:
const
Text
(
'确认退出'
),
),
content:
const
Text
(
'您确定要退出登录吗?'
),
),
actions:
[
const
SizedBox
(
width:
16
),
TextButton
(
Expanded
(
onPressed:
()
=>
Navigator
.
pop
(
context
,
false
),
child:
Column
(
child:
const
Text
(
'取消'
),
crossAxisAlignment:
CrossAxisAlignment
.
start
,
),
children:
[
TextButton
(
Text
(
onPressed:
()
=>
Navigator
.
pop
(
context
,
true
),
snapshot
.
data
!.
username
,
child:
const
Text
(
style:
const
TextStyle
(
'退出'
,
fontSize:
18
,
style:
TextStyle
(
color:
Colors
.
red
),
fontWeight:
FontWeight
.
bold
,
),
),
),
),
],
const
SizedBox
(
height:
4
),
),
Text
(
);
'在线'
,
style:
TextStyle
(
if
(
confirmed
==
true
&&
context
.
mounted
)
{
fontSize:
14
,
await
StorageService
.
clearUser
();
color:
Colors
.
green
[
600
],
),
Navigator
.
of
(
context
).
pushReplacementNamed
(
'/login'
);
),
}
],
},
),
child:
Container
(
),
padding:
const
EdgeInsets
.
symmetric
(
],
vertical:
12
,
),
horizontal:
16
,
const
SizedBox
(
height:
16
),
),
InkWell
(
decoration:
BoxDecoration
(
onTap:
()
async
{
color:
Colors
.
red
[
50
],
final
confirmed
=
await
showDialog
<
bool
>(
borderRadius:
BorderRadius
.
circular
(
8
),
context:
context
,
),
builder:
(
context
)
=>
AlertDialog
(
child:
Row
(
title:
const
Text
(
'确认退出'
),
mainAxisAlignment:
MainAxisAlignment
.
center
,
content:
const
Text
(
'您确定要退出登录吗?'
),
children:
[
actions:
[
Icon
(
TextButton
(
Icons
.
logout
,
onPressed:
()
=>
Navigator
.
pop
(
context
,
false
),
color:
Colors
.
red
[
700
],
child:
const
Text
(
'取消'
),
size:
20
,
),
),
TextButton
(
const
SizedBox
(
width:
8
),
onPressed:
()
=>
Navigator
.
pop
(
context
,
true
),
Text
(
child:
const
Text
(
'出登录'
,
'退出'
,
style:
TextStyle
(
style:
TextStyle
(
color:
Colors
.
red
),
color:
Colors
.
red
[
700
],
),
fontSize:
16
,
),
fontWeight:
FontWeight
.
w500
,
],
),
),
),
);
],
),
if
(
confirmed
==
true
&&
context
.
mounted
)
{
),
await
StorageService
.
clearUser
();
),
],
Navigator
.
of
(
context
).
pushReplacementNamed
(
'/login'
);
),
}
);
},
},
child:
Container
(
),
padding:
const
EdgeInsets
.
symmetric
(
],
vertical:
12
,
),
horizontal:
16
,
);
),
}
decoration:
BoxDecoration
(
color:
Colors
.
red
[
50
],
void
_showErrorDialog
(
String
message
)
{
borderRadius:
BorderRadius
.
circular
(
8
),
showDialog
(
),
context:
context
,
child:
Row
(
builder:
(
context
)
=>
AlertDialog
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
title:
const
Text
(
'提示'
),
children:
[
content:
Text
(
message
),
Icon
(
actions:
[
Icons
.
logout
,
TextButton
(
color:
Colors
.
red
[
700
],
onPressed:
()
=>
Navigator
.
pop
(
context
),
size:
20
,
child:
const
Text
(
'确定'
),
),
),
const
SizedBox
(
width:
8
),
],
Text
(
),
'出登录'
,
);
style:
TextStyle
(
}
color:
Colors
.
red
[
700
],
fontSize:
16
,
@override
fontWeight:
FontWeight
.
w500
,
Widget
build
(
BuildContext
context
)
{
),
return
Scaffold
(
),
appBar:
widget
.
hideNavigation
?
null
:
_buildAppBar
(),
],
drawer:
widget
.
hideNavigation
?
null
:
_buildDrawer
(
context
),
),
body:
IndexedStack
(
),
index:
_currentIndex
,
),
children:
[
],
Column
(
),
children:
[
);
Expanded
(
},
child:
ListView
.
builder
(
),
padding:
const
EdgeInsets
.
all
(
16
),
],
itemCount:
messages
.
isEmpty
?
1
:
messages
.
length
,
),
itemBuilder:
(
context
,
index
)
{
);
if
(
messages
.
isEmpty
)
{
}
return
Center
(
child:
Column
(
void
_showErrorDialog
(
String
message
)
{
mainAxisAlignment:
MainAxisAlignment
.
center
,
showDialog
(
children:
[
context:
context
,
ZoomIn
(
builder:
(
context
)
=>
AlertDialog
(
child:
Stack
(
title:
const
Text
(
'提示'
),
children:
[
content:
Text
(
message
),
Center
(
actions:
[
child:
Container
(
TextButton
(
height:
120
,
onPressed:
()
=>
Navigator
.
pop
(
context
),
width:
120
,
child:
const
Text
(
'确定'
),
margin:
const
EdgeInsets
.
only
(
top:
4
),
),
decoration:
const
BoxDecoration
(
],
color:
Pallete
.
assistantCircleColor
,
),
shape:
BoxShape
.
circle
,
);
),
}
),
),
@override
Container
(
Widget
build
(
BuildContext
context
)
{
height:
123
,
return
Scaffold
(
decoration:
BoxDecoration
(
appBar:
widget
.
hideNavigation
?
null
:
_buildAppBar
(),
shape:
BoxShape
.
circle
,
drawer:
widget
.
hideNavigation
?
null
:
_buildDrawer
(
context
),
image:
DecorationImage
(
body:
IndexedStack
(
image:
widget
.
customImageUrl
!=
null
index:
_currentIndex
,
?
NetworkImage
(
children:
[
widget
.
customImageUrl
!)
Column
(
:
const
AssetImage
(
children:
[
'assets/images/virtualAssistant.png'
,
Expanded
(
)
as
ImageProvider
,
child:
ListView
.
builder
(
onError:
(
exception
,
stackTrace
)
{
padding:
const
EdgeInsets
.
all
(
16
),
print
(
itemCount:
messages
.
isEmpty
?
1
:
messages
.
length
,
'Error loading image:
$exception
'
);
itemBuilder:
(
context
,
index
)
{
},
if
(
messages
.
isEmpty
)
{
),
return
Center
(
),
child:
Column
(
),
mainAxisAlignment:
MainAxisAlignment
.
center
,
],
children:
[
),
ZoomIn
(
),
child:
Stack
(
const
SizedBox
(
height:
20
),
children:
[
Text
(
Center
(
widget
.
customDescription
??
child:
Container
(
'你好!我是你的快际新云AI助手,请问有什么可以帮你的吗?'
,
height:
120
,
style:
const
TextStyle
(
width:
120
,
fontSize:
20
,
margin:
const
EdgeInsets
.
only
(
top:
4
),
color:
Pallete
.
mainFontColor
,
decoration:
const
BoxDecoration
(
),
color:
Pallete
.
assistantCircleColor
,
textAlign:
TextAlign
.
center
,
shape:
BoxShape
.
circle
,
),
),
],
),
),
),
);
Container
(
}
height:
123
,
decoration:
BoxDecoration
(
final
message
=
messages
[
index
];
shape:
BoxShape
.
circle
,
image:
DecorationImage
(
return
Column
(
image:
widget
.
customImageUrl
!=
null
children:
[
?
NetworkImage
(
ChatBubble
(
widget
.
customImageUrl
!)
message:
message
,
:
const
AssetImage
(
isTyping:
_isLoading
&&
'assets/images/virtualAssistant.png'
,
index
==
messages
.
length
-
1
&&
)
as
ImageProvider
,
!
message
.
isUserMessage
,
onError:
(
exception
,
stackTrace
)
{
),
print
(
if
(
_isLoading
&&
'Error loading image:
$exception
'
);
index
==
messages
.
length
-
1
&&
},
message
.
isUserMessage
)
),
Padding
(
),
padding:
const
EdgeInsets
.
all
(
8.0
),
),
child:
Align
(
],
alignment:
Alignment
.
centerLeft
,
),
child:
Row
(
),
mainAxisSize:
MainAxisSize
.
min
,
const
SizedBox
(
height:
20
),
children:
[
Text
(
SizedBox
(
widget
.
customDescription
??
width:
20
,
'你好!我是你的快际新云AI助手,请问有什么可以帮你的吗?'
,
height:
20
,
style:
const
TextStyle
(
child:
CircularProgressIndicator
(
fontSize:
20
,
strokeWidth:
2
,
color:
Pallete
.
mainFontColor
,
valueColor:
AlwaysStoppedAnimation
<
Color
>(
),
Pallete
.
firstSuggestionBoxColor
,
textAlign:
TextAlign
.
center
,
),
),
),
],
),
),
const
SizedBox
(
width:
8
),
);
const
Text
(
}
'正在思考中...'
,
style:
TextStyle
(
final
message
=
messages
[
index
];
color:
Pallete
.
mainFontColor
,
fontSize:
14
,
return
Column
(
),
children:
[
),
ChatBubble
(
],
message:
message
,
),
isTyping:
_isLoading
&&
),
index
==
messages
.
length
-
1
&&
),
!
message
.
isUserMessage
,
],
),
);
if
(
_isLoading
&&
},
index
==
messages
.
length
-
1
&&
),
message
.
isUserMessage
)
),
Padding
(
_buildBottomInput
(),
padding:
const
EdgeInsets
.
all
(
8.0
),
],
child:
Align
(
),
alignment:
Alignment
.
centerLeft
,
if
(!
widget
.
hideNavigation
)
AppsPage
(),
child:
Row
(
],
mainAxisSize:
MainAxisSize
.
min
,
),
children:
[
);
SizedBox
(
}
width:
20
,
}
height:
20
,
child:
CircularProgressIndicator
(
\ No newline at end of file
strokeWidth:
2
,
valueColor:
AlwaysStoppedAnimation
<
Color
>(
Pallete
.
firstSuggestionBoxColor
,
),
),
),
const
SizedBox
(
width:
8
),
const
Text
(
'正在思考中...'
,
style:
TextStyle
(
color:
Pallete
.
mainFontColor
,
fontSize:
14
,
),
),
],
),
),
),
],
);
},
),
),
_buildBottomInput
(),
],
),
if
(!
widget
.
hideNavigation
)
AppsPage
(),
],
),
);
}
}
lib/pages/chat_page.dart
浏览文件 @
c2c63647
...
@@ -6,6 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart';
...
@@ -6,6 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import
'../models/app_item.dart'
;
import
'../models/app_item.dart'
;
import
'../services/chat_service.dart'
;
import
'../services/storage_service.dart'
;
import
'../services/storage_service.dart'
;
import
'../home_page.dart'
;
import
'../home_page.dart'
;
...
@@ -22,6 +23,8 @@ class ChatPage extends ConsumerStatefulWidget {
...
@@ -22,6 +23,8 @@ class ChatPage extends ConsumerStatefulWidget {
}
}
class
_ChatPageState
extends
ConsumerState
<
ChatPage
>
{
class
_ChatPageState
extends
ConsumerState
<
ChatPage
>
{
final
OpenAIService
openAIService
=
OpenAIService
();
@override
@override
void
initState
()
{
void
initState
()
{
super
.
initState
();
super
.
initState
();
...
@@ -46,6 +49,12 @@ class _ChatPageState extends ConsumerState<ChatPage> {
...
@@ -46,6 +49,12 @@ class _ChatPageState extends ConsumerState<ChatPage> {
}
}
@override
@override
void
dispose
()
{
openAIService
.
clearConversation
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
return
Scaffold
(
appBar:
AppBar
(
appBar:
AppBar
(
...
@@ -78,6 +87,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
...
@@ -78,6 +87,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
customDescription:
widget
.
app
.
description
,
customDescription:
widget
.
app
.
description
,
customImageUrl:
widget
.
app
.
iconUrl
,
customImageUrl:
widget
.
app
.
iconUrl
,
hideNavigation:
true
,
hideNavigation:
true
,
openAIService:
openAIService
,
),
),
);
);
}
}
...
...
lib/services/chat_service.dart
浏览文件 @
c2c63647
...
@@ -8,6 +8,32 @@ class OpenAIService {
...
@@ -8,6 +8,32 @@ class OpenAIService {
// final String apiKey = 'sk-OVjS7VE9mT68Uvg7kSFoMnbU6EU836FO';
// final String apiKey = 'sk-OVjS7VE9mT68Uvg7kSFoMnbU6EU836FO';
// final String appKey = 'app-FRP2s2wSx01rsE67';
// final String appKey = 'app-FRP2s2wSx01rsE67';
String
?
conversationId
;
String
?
conversationId
;
bool
_isFirstMessage
=
true
;
Future
<
void
>
_generateConversationName
()
async
{
if
(
conversationId
==
null
)
return
;
var
prefs
=
await
SharedPreferences
.
getInstance
();
var
storageService
=
StorageService
(
prefs
);
String
appKey
=
storageService
.
getWorkbenchToken
()
??
''
;
try
{
final
response
=
await
http
.
post
(
Uri
.
parse
(
'
$baseUrl
/api/conversations/
$conversationId
/name'
),
headers:
{
'Content-Type'
:
'application/json'
,
'Authorization'
:
'Bearer
$appKey
'
,
},
body:
jsonEncode
({
"auto_generate"
:
true
}),
);
if
(
response
.
statusCode
!=
200
)
{
print
(
'生成会话名称失败:
${response.statusCode}
'
);
}
}
catch
(
e
)
{
print
(
'生成会话名称异常:
$e
'
);
}
}
Stream
<
String
>
chatGPTAPI
(
String
message
)
async
*
{
Stream
<
String
>
chatGPTAPI
(
String
message
)
async
*
{
final
client
=
http
.
Client
();
final
client
=
http
.
Client
();
...
@@ -85,11 +111,16 @@ class OpenAIService {
...
@@ -85,11 +111,16 @@ class OpenAIService {
}
catch
(
e
)
{
}
catch
(
e
)
{
throw
Exception
(
e
.
toString
());
throw
Exception
(
e
.
toString
());
}
finally
{
}
finally
{
if
(
_isFirstMessage
&&
conversationId
!=
null
)
{
await
_generateConversationName
();
_isFirstMessage
=
false
;
}
client
.
close
();
client
.
close
();
}
}
}
}
void
clearConversation
()
{
void
clearConversation
()
{
conversationId
=
null
;
conversationId
=
null
;
_isFirstMessage
=
true
;
}
}
}
}
macos/Flutter/GeneratedPluginRegistrant.swift
浏览文件 @
c2c63647
...
@@ -9,12 +9,12 @@ import audioplayers_darwin
...
@@ -9,12 +9,12 @@ import audioplayers_darwin
import
flutter_tts
import
flutter_tts
import
path_provider_foundation
import
path_provider_foundation
import
shared_preferences_foundation
import
shared_preferences_foundation
import
speech_to_text
_macos
import
speech_to_text
func
RegisterGeneratedPlugins
(
registry
:
FlutterPluginRegistry
)
{
func
RegisterGeneratedPlugins
(
registry
:
FlutterPluginRegistry
)
{
AudioplayersDarwinPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"AudioplayersDarwinPlugin"
))
AudioplayersDarwinPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"AudioplayersDarwinPlugin"
))
FlutterTtsPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FlutterTtsPlugin"
))
FlutterTtsPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"FlutterTtsPlugin"
))
PathProviderPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"PathProviderPlugin"
))
PathProviderPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"PathProviderPlugin"
))
SharedPreferencesPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"SharedPreferencesPlugin"
))
SharedPreferencesPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"SharedPreferencesPlugin"
))
SpeechToText
MacosPlugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"SpeechToTextMacos
Plugin"
))
SpeechToText
Plugin
.
register
(
with
:
registry
.
registrar
(
forPlugin
:
"SpeechToText
Plugin"
))
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论