ChatApp/lib/tools/home/HomePage.dart
2024-07-05 10:00:00 +08:00

362 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_client_sse/constants/sse_request_type_enum.dart';
import 'package:flutter_client_sse/flutter_client_sse.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import '../../network/NetworkConfig.dart';
import 'HomeModel.dart';
import '../../beans/MessageBean.dart';
class Homepage extends StatefulWidget {
const Homepage({super.key});
@override
State<Homepage> createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
late StreamSubscription subscription;
final HomeModel viewModel = HomeModel();
final TextEditingController _chatController = TextEditingController();
final ScrollController _scrollController = ScrollController();
String text = "";
String data = '';
List<MessageBean> list = [];
int created = 0;
String msg = "";
Future<void> chat() async {
EasyLoading.show(status: 'loading...');
List<Map<String, dynamic>> jsonList =
list.map((user) => user.toJson()).toList();
// String jsonList = jsonEncode(list.map((user) => user.toJson()).toList());
viewModel.chat(jsonList, 'assistant');
}
void _textFieldChanged(String str) {
text = str;
}
late WebSocketChannel channel;
bool isConnected = false;
String outputImg = "";
void connectToWebSocket(String serverAddress, String clientId) async {
final url = 'ws://$serverAddress/ws?clientId=$clientId';
Uri uri = Uri.parse(url);
WebSocketChannel channel = WebSocketChannel.connect(uri);
channel.stream.listen((message) {
Map<String, dynamic> responseData = jsonDecode(message);
// 处理接收到的消息
if (responseData["type"] != 'crystools.monitor') {
print('Received: $message');
if ((responseData["type"] == 'executed' &&
responseData["data"]['node'] == '384') ||
(responseData["type"] == 'executed' &&
responseData["data"]['node'] == '13')) {
print("responseData: " +
responseData["data"]['output']['images'][0]['filename']);
outputImg = "${"http://$serverAddress/view?filename=" +
responseData["data"]['output']['images'][0]['filename']}&type=output";
list[list.length - 1].img = outputImg;
setState(() {
EasyLoading.dismiss();
});
}
}
// 如果我们还没有标记为已连接,现在标记为已连接
}, onError: (error) {
// 处理错误
print('WebSocket error: $error');
isConnected = false; // 连接已关闭或出错
}, onDone: () {
// 连接关闭时的处理
print('WebSocket closed');
isConnected = false; // 连接已关闭
}, cancelOnError: true);
}
@override
void initState() {
// TODO: implement initState
super.initState();
var nowTime = DateTime.now(); //获取当前时间
var nTime = nowTime.millisecondsSinceEpoch; //单位是毫秒(千分之一秒)13位时间戳
NetworkConfig.clientId = nTime.toString();
connectToWebSocket(NetworkConfig.serverAddress, NetworkConfig.clientId);
MessageBean a = MessageBean("user", "Start a new Chat", "");
MessageBean b = MessageBean(
"assistant",
"这天,小猫娘身穿粉色的内衣,黑色丝袜,在家里玩耍,看到主人正在沙发上玩手机,小猫娘忽然对主人看的内容很感兴趣,也想要看看,就跑到主人面前一脸希翼的看着主人",
"assets/images/20240622145935.png");
list.add(a);
list.add(b);
// SSEClient.subscribeToSSE(
// method: SSERequestType.GET,
// url:
// 'http://127.0.0.1:5000/v1/chat/completions',
// header: {
// "Cookie":
// 'jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2NDMyMTAyMzEsImV4cCI6MTY0MzgxNTAzMX0.U0aCAM2fKE1OVnGFbgAU_UVBvNwOMMquvPY8QaLD138; Path=/; Expires=Wed, 02 Feb 2022 15:17:11 GMT; HttpOnly; SameSite=Strict',
// "Accept": "text/event-stream",
// "Cache-Control": "no-cache",
// }).listen(
// (event) {
// print('Id: ' + event.id!);
// print('Event: ' + event.event!);
// print('Data: ' + event.data!);
// },
// );
// 监听输入变化
_chatController.addListener(() {
print(_chatController.text);
});
subscription = viewModel.streamController.stream.listen((newData) {
String code = newData['code'];
if (code.isNotEmpty) {
if (code == "chat") {
//有数据
data = newData['data'];
list.add(MessageBean("assistant", data, ""));
setState(() {});
Future.delayed(const Duration(milliseconds: 500), () {
_scrollController
.jumpTo(_scrollController.position.maxScrollExtent);
});
//EasyLoading.showToast(data);
//print("data" + data.toString());
}
EasyLoading.dismiss();
} else {
EasyLoading.dismiss();
}
});
}
@override
void dispose() {
// TODO: implement dispose
_chatController.dispose();
subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(
"家辉",
style: TextStyle(fontSize: 18),
),
backgroundColor: Colors.white,
centerTitle: true,
actions: <Widget>[
GestureDetector(
onTap: () {
Navigator.pushNamed(context, "/UploadPage");
},
child: Container(
margin: const EdgeInsets.only(right: 20),
width: 70,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFF006CFF),
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: Text(
"生图",
style: TextStyle(color: Colors.white),
),
),
)
],
),
body: Container(
child: Column(
children: [
Container(
width: double.infinity,
height: 1,
color: Color(0xFFDFDFDF),
),
Expanded(
child: Container(
alignment: Alignment.topCenter,
child: ListView.builder(
// reverse: true,
controller: _scrollController,
itemCount: list.length,
itemBuilder: (Context, index) {
return _item(index);
}),
)),
Card(
elevation: 5,
color: Colors.white,
margin: EdgeInsets.only(left: 16, right: 16, bottom: 30),
child: Row(
children: [
//输入框
Expanded(
child: Container(
margin: EdgeInsets.only(left: 16),
child: TextField(
controller: _chatController,
onChanged: _textFieldChanged,
decoration: InputDecoration(
border: InputBorder.none, // 移除非聚焦状态下的边框
enabledBorder: InputBorder.none, // 移除获得焦点但未输入内容时的边框
focusedBorder: InputBorder.none, // 移除输入时的边框
),
),
),
),
GestureDetector(
onTap: () {
list.add(MessageBean("user", text, ""));
_chatController.clear();
Future.delayed(const Duration(milliseconds: 200), () {
_scrollController
.jumpTo(_scrollController.position.maxScrollExtent);
});
setState(() {});
chat();
},
child: Container(
width: 70,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFF006CFF),
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: Text(
"发送",
style: TextStyle(color: Colors.white),
),
),
)
],
),
),
],
),
),
);
}
_item(index) {
if (index == 0) {
return Container();
}
return Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: list[index].role != 'user'
? Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 45,
height: 45,
margin: EdgeInsets.only(left: 16, top: 4),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image(
fit: BoxFit.cover,
image: AssetImage('assets/images/20240622145440.png'),
),
),
),
ConstrainedBox(
constraints: BoxConstraints(
maxWidth:
MediaQuery.of(context).size.width - 80, // 确保不超过屏幕宽度
),
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 16.0, vertical: 4.0),
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Color(0xFFECECEC),
borderRadius: BorderRadius.circular(16.0),
),
child: Text(
list[index].content!,
style: TextStyle(
fontSize: 16,
color: Colors.black,
),
),
),
),
],
),
list[index].img != ""
? SizedBox(
width: MediaQuery.of(context).size.width,
child: Image.network(list[index].img!))
: Container(
child: Text("正在生图中"),
)
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ConstrainedBox(
constraints: BoxConstraints(
maxWidth:
MediaQuery.of(context).size.width - 100, // 确保不超过屏幕宽度
),
child: Container(
margin:
EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Color(0xFF006CFF),
borderRadius: BorderRadius.circular(16.0),
),
child: Text(
list[index].content!,
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
),
),
Container(
width: 45,
height: 45,
margin: EdgeInsets.only(right: 16, top: 4),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image(
fit: BoxFit.cover,
image: AssetImage('assets/images/avatar1.png'),
),
),
),
],
),
);
}
}