Files
xueguang_flutter_app/lib/pages/teacher/room/widgets/student_item.dart
2025-11-28 13:31:23 +08:00

196 lines
6.3 KiB
Dart

import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:app/pages/teacher/room/viewmodel/type.dart';
import 'package:app/request/dto/room/room_user_dto.dart';
import 'package:app/widgets/room/file_drawer.dart';
import 'package:app/widgets/room/other_widget.dart';
import 'package:app/widgets/room/video_surface.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:remixicon/remixicon.dart';
import '../viewmodel/tch_room_vm.dart';
class StudentItem extends StatefulWidget {
final RoomUserDto user;
final RtcEngine? engine;
const StudentItem({
super.key,
required this.user,
this.engine,
});
@override
State<StudentItem> createState() => _StudentItemState();
}
class _StudentItemState extends State<StudentItem> {
///打开文件列表
void _openFileList() {
showFileDialog(
context,
isUpload: false,
files: widget.user.filesList,
);
}
@override
Widget build(BuildContext context) {
final vm = context.read<TchRoomVM>();
//摄像头是否开启
bool isCameraOpen = widget.user.cameraStatus == 1;
///麦克风是否开启
bool isMicOpen = widget.user.microphoneStatus == 1;
///声音是否开启
bool isSpeakerOpen = widget.user.speekerStatus == 1;
return ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
color: Color(0xFF404649),
child: Column(
children: [
Expanded(
child: SizedBox(
width: double.infinity,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
if (widget.engine != null)
VideoSurface(
user: widget.user,
child: AgoraVideoView(
controller: VideoViewController(
rtcEngine: widget.engine!,
canvas: VideoCanvas(uid: widget.user.rtcUid),
),
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0x0b050505), Color(0x54050505)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: Text(
widget.user.userName,
style: TextStyle(color: Colors.white, fontSize: 14),
),
),
),
///右上角选中
if (widget.user.userId != vm.activeSId)
Positioned(
right: 5,
top: 5,
child: InkWell(
onTap: () {
vm.selectStudent(widget.user.userId);
},
child: Container(
width: 25,
height: 25,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black12,
borderRadius: BorderRadius.circular(5),
),
child: Icon(RemixIcons.fullscreen_line, color: Colors.white),
),
),
),
///举手
if (widget.user.handup == 1)
Positioned(
bottom: 40,
child: HandRaiseButton(
onTap: () {
vm.clearHandUp(widget.user.userId);
},
),
),
],
),
),
),
ColoredBox(
color: Color(0xFF232426),
child: Row(
spacing: 1,
children: [
_actionItem(
icon: isCameraOpen ? RemixIcons.video_on_fill : RemixIcons.video_off_fill,
isActive: isCameraOpen,
onTap: () {
vm.closeStudentAction(
uId: widget.user.userId,
action: StudentAction.camera,
);
},
),
_actionItem(
icon: isMicOpen ? RemixIcons.mic_fill : RemixIcons.mic_off_fill,
isActive: isMicOpen,
onTap: () {
vm.closeStudentAction(
uId: widget.user.userId,
action: StudentAction.microphone,
);
},
),
_actionItem(
icon: isSpeakerOpen
? RemixIcons.volume_up_fill
: RemixIcons.volume_mute_fill,
isActive: isSpeakerOpen,
onTap: () {
vm.closeStudentAction(
uId: widget.user.userId,
action: StudentAction.speaker,
);
},
),
_actionItem(icon: RemixIcons.file_list_3_fill, onTap: _openFileList),
],
),
),
],
),
),
);
}
///
Widget _actionItem({
required IconData icon,
bool isActive = true,
void Function()? onTap,
}) {
Color offColor = Color(0xFFE75B61);
return Expanded(
child: Container(
height: 50,
color: isActive ? null : offColor.withValues(alpha: 0.3),
child: IconButton(
onPressed: onTap,
icon: Icon(
icon,
color: isActive ? Colors.white : offColor,
size: 20,
),
),
),
);
}
}