1.聊天接口接入

2.聊天和成员底部弹窗刷新优化
This commit is contained in:
fuenmao 2024-11-28 11:22:50 +08:00
parent 3a1dde6e19
commit 06a9eb44d0
5 changed files with 217 additions and 136 deletions

View File

@ -0,0 +1,23 @@
import 'package:json_annotation/json_annotation.dart';
part 'meeting_room_msg.g.dart';
@JsonSerializable()
class MeetingRoomMsg extends Object{
String uid;
String userName;
String message;
// 01
int source;
MeetingRoomMsg(this.uid,this.userName,this.message,this.source);
factory MeetingRoomMsg.fromJson(Map<String, dynamic> srcJson) => _$MeetingRoomMsgFromJson(srcJson);
}

View File

@ -90,7 +90,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
state.meetingRooms[index].roomName,
state.meetingRooms.value[index].roomName,
style: TextStyle(
fontSize: 14.sp,
color: ColorUtil.Color_89_88_88,
@ -105,7 +105,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
height: 16.h,
),
Text(
'${state.meetingRooms[index].onlineUserCount}',
'${state.meetingRooms.value[index].onlineUserCount}',
style: TextStyle(
fontSize: 12.sp,
color: ColorUtil.Color_177_177_177,
@ -122,7 +122,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
Row(
children: [
Text(
state.meetingRooms[index].roomNum,
state.meetingRooms.value[index].roomNum,
style: TextStyle(
fontSize: 12.sp,
color: ColorUtil.Color_177_177_177,
@ -136,7 +136,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
height: 16.h,
),
onTap: (){
Clipboard.setData(ClipboardData(text: state.meetingRooms[index].roomNum));
Clipboard.setData(ClipboardData(text: state.meetingRooms.value[index].roomNum));
ToastUtils.showSuccess("复制成功");
},
)
@ -169,7 +169,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
),
),
onTap: (){
Get.toNamed(Routes.meetingMainPage, arguments: {"roomNumber": state.meetingRooms[index].roomNum});
Get.toNamed(Routes.meetingMainPage, arguments: {"roomNumber": state.meetingRooms.value[index].roomNum});
},
)
],
@ -178,7 +178,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
),
);
},
itemCount: state.meetingRooms.length,
itemCount: state.meetingRooms.value.length,
),
),
),

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
@ -10,6 +9,7 @@ import '../../common/config/request_config.dart';
import '../../common/mixins/request_tool_mixin.dart';
import '../../common/models/common/base_structure_result.dart';
import '../../common/models/meeting_room_info.dart';
import '../../common/models/meeting_room_msg.dart';
import '../../common/models/meeting_room_user.dart';
import '../../utils/permission_handler.dart';
import '../../utils/toast_utils.dart';
@ -33,6 +33,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
void onClose() {
super.onClose();
state.memberNameSearchController.dispose();
state.sendMsgController.dispose();
stopTime();
leaveMeetingToRtc();
leaveMeetingToSocket();
@ -154,7 +155,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
///
state.hubConnection.value?.on("UserJoined", (user){
var jsonStr = json.encode(user);
var jsonStr = const Utf8Decoder().convert(json.encode(user).runes.toList());
var listDynamic = jsonDecode(jsonStr);
List<MeetingRoomUser> meetingRoomUsers = (listDynamic as List<dynamic>).map((e) => MeetingRoomUser.fromJson((e as Map<String,dynamic>))).toList();
state.cacheUsers.value.addAll(meetingRoomUsers);
@ -164,7 +165,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
///
state.hubConnection.value?.on("UserLeave", (uid){
var jsonStr = json.encode(uid);
var jsonStr = const Utf8Decoder().convert(json.encode(uid).runes.toList());
List listDynamic = jsonDecode(jsonStr);
for(String uidStr in listDynamic){
for(var j = 0; j < state.cacheUsers.value.length; j++){
@ -179,7 +180,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
/// /-
state.hubConnection.value?.on("ManagerRefresh", (e){
var jsonStr = json.encode(e?[0]);
var jsonStr = const Utf8Decoder().convert(json.encode(e?[0]).runes.toList());
var listDynamic = jsonDecode(jsonStr);
MeetingRoomUser meetingRoomUser = MeetingRoomUser.fromJson(listDynamic);
if(meetingRoomUser.isRoomManager == true){
@ -205,7 +206,20 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
state.isSpeak.value = false;
setEnableLocalAudio(false);
}
update();
});
///
state.hubConnection.value?.on("ReceiveMessage", (e){
var jsonStr = const Utf8Decoder().convert(json.encode(e).runes.toList());
List list = json.decode(jsonStr);
MeetingRoomMsg meetingRoomMsg = MeetingRoomMsg(list[0],list[1],list[2],0);
state.meetingRoomMsgs.value.add(meetingRoomMsg);
update();
Future.delayed(const Duration(milliseconds: 100), () {
state.chatController.jumpTo(state.chatController.position.maxScrollExtent);
});
debugPrint("wgs输出===Socket-会议室接收消息:$jsonStr");
});
}
@ -220,6 +234,20 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
await state.hubConnection.value?.invoke("levelChannel", args: [state.roomNumber.value]);
}
///
Future<void> sendMsg(String msg) async {
MeetingRoomMsg meetingRoomMsg = MeetingRoomMsg(
UserStore.to.userInfoEntity.value!.uid,
UserStore.to.userInfoEntity.value!.userName,
msg,1);
state.meetingRoomMsgs.value.add(meetingRoomMsg);
update();
Future.delayed(const Duration(milliseconds: 100), () {
state.chatController.jumpTo(state.chatController.position.maxScrollExtent);
});
await state.hubConnection.value?.invoke("sendChannelMsg", args: [state.roomNumber.value, msg]);
}
/// --------------------------SDK相关
/// SDK
Future<void> initRtc() async {

View File

@ -7,6 +7,7 @@ import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:signalr_core/signalr_core.dart';
import '../../common/models/meeting_room_info.dart';
import '../../common/models/meeting_room_msg.dart';
import '../../common/models/meeting_room_user.dart';
class MeetingMainState {
@ -16,6 +17,7 @@ class MeetingMainState {
}
late TextEditingController memberNameSearchController = TextEditingController();
late TextEditingController sendMsgController = TextEditingController();
///
late RxBool isShowMeetingInfoFloatingLayer = false.obs;
@ -52,6 +54,9 @@ class MeetingMainState {
///
late RxBool isSpeak = false.obs;
///
late RxList<MeetingRoomMsg> meetingRoomMsgs = RxList([]);
/// signalR
late RxString serviceUrl = "http://192.168.2.9:5192/session-manage".obs;
late Rx<HubConnection?> hubConnection = Rx(null);

View File

@ -148,7 +148,7 @@ class MeetingMainPage extends StatelessWidget {
//
Visibility(
visible: true,
child: MeetingMainVoiceComponent(users: state.cacheUsers)
child: MeetingMainVoiceComponent(users: state.cacheUsers.value)
),
//
@ -324,7 +324,7 @@ class MeetingMainPage extends StatelessWidget {
onTap: () {
Get.bottomSheet(
isScrollControlled: true,
Obx(() => queryMemberFloatingLayer(context)),
queryMemberFloatingLayer(context),
);
},
),
@ -880,121 +880,124 @@ class MeetingMainPage extends StatelessWidget {
margin:
const EdgeInsets.only(top: 18, left: 16, right: 16, bottom: 16),
child: Text(
'会议中(${state.users.length}',
'会议中(${state.users.value.length}',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: ColorUtil.Color_85_117_242),
),
),
Expanded(
child: ScrollConfiguration(
behavior: CusBehavior(),
child: ListView.builder(
itemBuilder: (context, index) {
return Container(
width: double.infinity,
margin: EdgeInsets.only(bottom: index == 9 ? 18 : 0),
child: Column(
children: [
Container(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: ColorUtil.Color_85_117_242
),
margin: const EdgeInsets.only(right: 8),
width: 36.w,
height: 36.h,
alignment: Alignment.center,
child: Text(
state.users[index].userName.length > 3
? state.users[index].userName.substring(state.users[index].userName.length - 2,state.users[index].userName.length)
: state.users[index].userName,
style: TextStyle(
fontSize: 12.sp,
color: ColorUtil.Color_244_244_244
child: GetBuilder<MeetingMainLogic>(builder: (controll){
return ListView.builder(
itemBuilder: (context, index) {
return Container(
width: double.infinity,
margin: EdgeInsets.only(bottom: index == 9 ? 18 : 0),
child: Column(
children: [
Container(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: ColorUtil.Color_85_117_242
),
margin: const EdgeInsets.only(right: 8),
width: 36.w,
height: 36.h,
alignment: Alignment.center,
child: Text(
state.users.value[index].userName.length > 3
? state.users.value[index].userName.substring(state.users.value[index].userName.length - 2,state.users.value[index].userName.length)
: state.users.value[index].userName,
style: TextStyle(
fontSize: 12.sp,
color: ColorUtil.Color_244_244_244
),
),
),
),
Text(
state.users[index].userName,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: ColorUtil.Color_243_243_243),
),
SizedBox(width: 8.w),
Visibility(
visible: state.users[index].roleId == "1" || state.users[index].roleId == "3" ? true : false,
child: Text(
'主持人',
Text(
state.users.value[index].userName,
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: ColorUtil.Color_2_177_136),
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: ColorUtil.Color_243_243_243),
),
),
Visibility(
visible: state.users[index].roleId == "2" && state.users[index].isRoomManager == true ? true : false,
child: Text(
'发言人',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: ColorUtil.Color_2_177_136),
SizedBox(width: 8.w),
Visibility(
visible: state.users.value[index].roleId == "1" || state.users.value[index].roleId == "3" ? true : false,
child: Text(
'主持人',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: ColorUtil.Color_2_177_136),
),
),
)
],
),
Row(
children: [
Container(
child: Image.asset(
'assets/images/meeting_main_share_currently.png',
width: 17.w,
height: 17.h,
Visibility(
visible: state.users.value[index].roleId == "2" && state.users.value[index].isRoomManager == true ? true : false,
child: Text(
'发言人',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: ColorUtil.Color_2_177_136),
),
)
],
),
Row(
children: [
Container(
child: Image.asset(
'assets/images/meeting_main_share_currently.png',
width: 17.w,
height: 17.h,
),
),
),
Container(
margin: const EdgeInsets.only(left: 12),
child: Image.asset(
state.users[index].enableMicr == true ? 'assets/images/meeting_main_microphone_default.png' : 'assets/images/meeting_main_microphone_close.png',
width: 17.w,
height: 17.h,
Container(
margin: const EdgeInsets.only(left: 12),
child: Image.asset(
state.users.value[index].enableMicr == true ? 'assets/images/meeting_main_microphone_default.png' : 'assets/images/meeting_main_microphone_close.png',
width: 17.w,
height: 17.h,
),
),
),
Container(
margin: const EdgeInsets.only(left: 12),
child: Image.asset(
state.users[index].enableCamera == true ? 'assets/images/meeting_main_camera_default.png' : 'assets/images/meeting_main_camera_close.png',
width: 17.w,
height: 17.h,
),
)
],
)
],
Container(
margin: const EdgeInsets.only(left: 12),
child: Image.asset(
state.users.value[index].enableCamera == true ? 'assets/images/meeting_main_camera_default.png' : 'assets/images/meeting_main_camera_close.png',
width: 17.w,
height: 17.h,
),
)
],
)
],
),
),
),
Container(
width: double.infinity,
height: 0.5.h,
margin: const EdgeInsets.only(top: 12, bottom: 12),
color: ColorUtil.Color_49_47_47,
)
],
),
);
},
itemCount: state.users.length,
)
Container(
width: double.infinity,
height: 0.5.h,
margin: const EdgeInsets.only(top: 12, bottom: 12),
color: ColorUtil.Color_49_47_47,
)
],
),
);
},
itemCount: state.users.value.length,
);
})
),
)
],
@ -1049,13 +1052,15 @@ class MeetingMainPage extends StatelessWidget {
Expanded(
child: ScrollConfiguration(
behavior: CusBehavior(),
child: ListView.builder(
controller: state.chatController,
itemBuilder: (context, index) {
return index == 0 || index == 2 ? chartItemToOthers(index) : chartItemToOwn(index);
},
itemCount: 6,
)
child: GetBuilder<MeetingMainLogic>(builder: (controll){
return ListView.builder(
controller: state.chatController,
itemBuilder: (context, index) {
return state.meetingRoomMsgs.value[index].source == 0 ? chartItemToOthers(index) : chartItemToOwn(index);
},
itemCount: state.meetingRoomMsgs.value.length,
);
})
),
),
Container(
@ -1070,17 +1075,27 @@ class MeetingMainPage extends StatelessWidget {
color: ColorUtil.Color_53_53_53,
),
child: TextField(
controller: state.sendMsgController,
style: TextStyle(
fontSize: 14.sp,
color: ColorUtil.Color_235_235_235
),
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0),
border: OutlineInputBorder(borderSide: BorderSide.none),
contentPadding: const EdgeInsets.all(0),
border: const OutlineInputBorder(borderSide: BorderSide.none),
hintText: '请输入内容...',
hintStyle: TextStyle(
color: ColorUtil.Color_235_235_235,
fontSize: 14.sp)),
fontSize: 14.sp)
),
onSubmitted: (value){
if(value.isNotEmpty){
logic.sendMsg(value);
state.sendMsgController.text = "";
}else{
ToastUtils.showError("请输入内容");
}
},
),
),
)
@ -1102,15 +1117,20 @@ class MeetingMainPage extends StatelessWidget {
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(99),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"https://ts4.cn.mm.bing.net/th?id=OIP-C.QDl_Z7HdQWX_XbVYgBLJLQAAAA&w=250&h=250&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2",
),
),
color: ColorUtil.Color_85_117_242
),
width: 50.w,
height: 50.h,
alignment: Alignment.center,
child: Text(
state.meetingRoomMsgs.value[index].userName.length > 3
? state.meetingRoomMsgs.value[index].userName.substring(state.meetingRoomMsgs.value[index].userName.length - 2,state.meetingRoomMsgs.value[index].userName.length)
: state.meetingRoomMsgs.value[index].userName,
style: TextStyle(
fontSize: 14.sp,
color: ColorUtil.Color_244_244_244
),
),
),
Expanded(
child: Column(
@ -1119,7 +1139,7 @@ class MeetingMainPage extends StatelessWidget {
Container(
margin: const EdgeInsets.only(left: 6),
child: Text(
'晓晓',
state.meetingRoomMsgs.value[index].userName,
style: TextStyle(
fontSize: 10.sp,
color: ColorUtil.Color_202_202_202),
@ -1138,7 +1158,7 @@ class MeetingMainPage extends StatelessWidget {
color: ColorUtil.Color_53_53_53,
),
child: Text(
'你好啊...............你好啊...............',
state.meetingRoomMsgs.value[index].message,
style: TextStyle(
fontSize: 12.sp,
color: ColorUtil.Color_235_235_235),
@ -1169,7 +1189,7 @@ class MeetingMainPage extends StatelessWidget {
Container(
margin: const EdgeInsets.only(right: 6),
child: Text(
'晓晓',
state.meetingRoomMsgs.value[index].userName,
style: TextStyle(
fontSize: 10.sp,
color: ColorUtil.Color_202_202_202),
@ -1189,7 +1209,7 @@ class MeetingMainPage extends StatelessWidget {
color: ColorUtil.Color_85_117_242,
),
child: Text(
'你好啊...............你好啊...............',
state.meetingRoomMsgs.value[index].message,
style: TextStyle(
fontSize: 12.sp,
color: ColorUtil.Color_235_235_235),
@ -1201,15 +1221,20 @@ class MeetingMainPage extends StatelessWidget {
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(99),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"https://ts4.cn.mm.bing.net/th?id=OIP-C.QDl_Z7HdQWX_XbVYgBLJLQAAAA&w=250&h=250&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2",
),
),
color: ColorUtil.Color_85_117_242
),
width: 50.w,
height: 50.h,
alignment: Alignment.center,
child: Text(
state.meetingRoomMsgs.value[index].userName.length > 3
? state.meetingRoomMsgs.value[index].userName.substring(state.meetingRoomMsgs.value[index].userName.length - 2,state.meetingRoomMsgs.value[index].userName.length)
: state.meetingRoomMsgs.value[index].userName,
style: TextStyle(
fontSize: 14.sp,
color: ColorUtil.Color_244_244_244
),
),
)
],
),