老师端几乎ok

This commit is contained in:
zhutao
2025-11-20 23:03:49 +08:00
parent b7239292d1
commit 9c94ee31fd
7 changed files with 325 additions and 94 deletions

View File

@@ -1,35 +1,123 @@
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:app/config/config.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../viewmodel/students_view_model.dart';
import 'student_item.dart';
class ContentView extends StatelessWidget {
class ContentView extends StatefulWidget {
const ContentView({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10),
child: Row(
spacing: 15,
children: [
Expanded(
child: StudentItem(),
),
SizedBox(
width: 300,
child: ListView.separated(
itemBuilder: (_, index) {
return SizedBox(
height: 250,
child: StudentItem(),
);
},
separatorBuilder: (_, __) => SizedBox(height: 15),
itemCount: 7,
),
),
],
State<ContentView> createState() => _ContentViewState();
}
class _ContentViewState extends State<ContentView> {
// bool isLoading = true;
//声网数据
RtcEngine? _engine;
void _initRtc() async {
final vm = context.read<StudentsViewModel>();
_engine = createAgoraRtcEngine();
//初始化 RtcEngine设置频道场景为 channelProfileLiveBroadcasting直播场景
await _engine!.initialize(
RtcEngineContext(
appId: Config.swAppId,
channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
),
);
//添加回调
_engine!.registerEventHandler(
RtcEngineEventHandler(
// 成功加入频道回调
onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
setState(() {});
},
// 远端用户或主播加入当前频道回调
onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {},
// 远端用户或主播离开当前频道回调
onUserOffline: (RtcConnection connection, int remoteUid, UserOfflineReasonType reason) {},
),
);
//启动视频模块
await _engine!.enableVideo();
//加入频道
await _engine!.joinChannel(
token: vm.rtcToken!.token,
channelId: vm.rtcToken!.channel,
uid: int.parse(vm.rtcToken!.uid),
options: ChannelMediaOptions(
// 自动订阅所有视频流
autoSubscribeVideo: true,
// 自动订阅所有音频流
autoSubscribeAudio: true,
// 发布摄像头采集的视频
publishCameraTrack: true,
// 发布麦克风采集的音频
publishMicrophoneTrack: true,
// 设置用户角色为 clientRoleBroadcaster主播或 clientRoleAudience观众
clientRoleType: ClientRoleType.clientRoleBroadcaster,
),
);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
final vm = context.read<StudentsViewModel>();
if (_engine == null && vm.students.isNotEmpty) {
_initRtc();
}
}
@override
Widget build(BuildContext context) {
return Consumer<StudentsViewModel>(
builder: (context, vm, _) {
if (vm.students.isEmpty) {
return Center(
child: Text('无学生在场,请通知学生入场'),
);
}
//选中的学生
final activeStudent = vm.students.firstWhere((t) => t.userId == vm.activeSId);
//其他学生
final otherStudents = vm.students.where((t) => t.userId != vm.activeSId).toList()
..sort((a, b) => b.handup.compareTo(a.handup));
return Padding(
padding: const EdgeInsets.all(10),
child: Row(
spacing: 15,
children: [
Expanded(
child: StudentItem(
user: activeStudent,
),
),
SizedBox(
width: 300,
child: ListView.separated(
itemBuilder: (_, index) {
var item = otherStudents.elementAt(index);
return SizedBox(
height: 250,
child: StudentItem(
user: item,
),
);
},
separatorBuilder: (_, __) => SizedBox(height: 15),
itemCount: otherStudents.length,
),
),
],
),
);
},
);
}
}