初始化
This commit is contained in:
28
lib/pages/teacher/home/t_home_page.dart
Normal file
28
lib/pages/teacher/home/t_home_page.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:app/config/theme/base/app_theme_ext.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'widgets/header.dart';
|
||||
import 'widgets/today_card.dart';
|
||||
|
||||
class THomePage extends StatefulWidget {
|
||||
const THomePage({super.key});
|
||||
|
||||
@override
|
||||
State<THomePage> createState() => _THomePageState();
|
||||
}
|
||||
|
||||
class _THomePageState extends State<THomePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
|
||||
appBar: Header(),
|
||||
body: ListView(
|
||||
padding: EdgeInsets.symmetric(vertical: 20, horizontal: context.pagePadding),
|
||||
children: [
|
||||
TodayCard(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
49
lib/pages/teacher/home/widgets/header.dart
Normal file
49
lib/pages/teacher/home/widgets/header.dart
Normal file
@@ -0,0 +1,49 @@
|
||||
import 'package:app/config/theme/base/app_theme_ext.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:remixicon/remixicon.dart';
|
||||
|
||||
class Header extends StatelessWidget implements PreferredSizeWidget {
|
||||
const Header({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
child: SafeArea(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: context.pagePadding),
|
||||
height: preferredSize.height,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"学光自习室",
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
Text(
|
||||
"在线陪伴、用心教学",
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: Icon(RemixIcons.user_line),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
128
lib/pages/teacher/home/widgets/today_card.dart
Normal file
128
lib/pages/teacher/home/widgets/today_card.dart
Normal file
@@ -0,0 +1,128 @@
|
||||
import 'package:app/router/route_paths.dart';
|
||||
import 'package:app/widgets/base/button/index.dart';
|
||||
import 'package:app/widgets/base/card/g_card.dart';
|
||||
import 'package:app/widgets/base/config/config.dart';
|
||||
import 'package:app/widgets/base/tag/index.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:remixicon/remixicon.dart';
|
||||
|
||||
class TodayCard extends StatelessWidget {
|
||||
const TodayCard({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/// item
|
||||
Widget item({
|
||||
required String title,
|
||||
required String value,
|
||||
required IconData icon,
|
||||
required Color color,
|
||||
}) {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: color.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Container(
|
||||
width: 45,
|
||||
height: 45,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title, style: Theme.of(context).textTheme.labelLarge),
|
||||
Text(value),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return GCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Text("高三数学冲刺班"),
|
||||
Tag(text: "待开始"),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
"和学生们一起专注学习、共同进步",
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Icon(RemixIcons.arrow_right_s_line, size: 30),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 30),
|
||||
child: Row(
|
||||
spacing: 15,
|
||||
children: [
|
||||
item(
|
||||
title: "开始时间",
|
||||
value: "14:00",
|
||||
icon: RemixIcons.time_line,
|
||||
color: Color(0xff2b7efd),
|
||||
),
|
||||
item(
|
||||
title: "学生人数",
|
||||
value: "8 名",
|
||||
icon: RemixIcons.group_line,
|
||||
color: Color(0xff00c74f),
|
||||
),
|
||||
item(
|
||||
title: "时长",
|
||||
value: "120 分钟",
|
||||
icon: RemixIcons.book_open_line,
|
||||
color: Color(0xffac45fd),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 30),
|
||||
height: 45,
|
||||
child: Button(
|
||||
text: "开始自习室",
|
||||
type: ThemeType.success,
|
||||
onPressed: () {
|
||||
context.push(RoutePaths.tRoom);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
74
lib/pages/teacher/room/controls/top_bar.dart
Normal file
74
lib/pages/teacher/room/controls/top_bar.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:remixicon/remixicon.dart';
|
||||
|
||||
class TopBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
const TopBar({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//标题子显示内容
|
||||
Widget infoItem({required String title, required IconData icon}) {
|
||||
return Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Icon(icon, color: Colors.white54, size: 14),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(fontSize: 12, color: Colors.white54),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
//操作按钮
|
||||
Widget actionButton({required IconData icon, required String title}) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
margin: EdgeInsets.only(right: 15),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xff4a4f4f),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(icon, size: 16),
|
||||
Text(title, style: TextStyle(fontSize: 14)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return AppBar(
|
||||
backgroundColor: Color(0xff373c3e),
|
||||
foregroundColor: Colors.white,
|
||||
title: Column(
|
||||
spacing: 5,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("高三数学重置版", style: TextStyle(color: Colors.white, fontSize: 18)),
|
||||
Row(
|
||||
spacing: 15,
|
||||
children: [
|
||||
infoItem(title: "剩余 1小时23分钟", icon: RemixIcons.time_line),
|
||||
infoItem(title: "8 名学生", icon: RemixIcons.group_line),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
actionButton(
|
||||
icon: RemixIcons.video_on_ai_line,
|
||||
title: "关闭全部",
|
||||
),
|
||||
actionButton(
|
||||
icon: RemixIcons.volume_up_line,
|
||||
title: "全部静音",
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
46
lib/pages/teacher/room/t_room_page.dart
Normal file
46
lib/pages/teacher/room/t_room_page.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'controls/top_bar.dart';
|
||||
import 'view/student_item.dart';
|
||||
import 'view/waiting_start.dart';
|
||||
|
||||
class TRoomPage extends StatefulWidget {
|
||||
const TRoomPage({super.key});
|
||||
|
||||
@override
|
||||
State<TRoomPage> createState() => _TRoomPageState();
|
||||
}
|
||||
|
||||
class _TRoomPageState extends State<TRoomPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xff2c3032),
|
||||
appBar: TopBar(),
|
||||
body: true ? WaitingStart() : 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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
105
lib/pages/teacher/room/view/student_item.dart
Normal file
105
lib/pages/teacher/room/view/student_item.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
import 'package:app/widgets/room/file_drawer.dart';
|
||||
import 'package:app/widgets/room/video_surface.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:remixicon/remixicon.dart';
|
||||
|
||||
class StudentItem extends StatefulWidget {
|
||||
const StudentItem({super.key});
|
||||
|
||||
@override
|
||||
State<StudentItem> createState() => _StudentItemState();
|
||||
}
|
||||
|
||||
class _StudentItemState extends State<StudentItem> {
|
||||
///打开文件列表
|
||||
void _openFileList(){
|
||||
showFileDialog(context,isUpload: false);
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Container(
|
||||
color: Color(0xFF404649),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Stack(
|
||||
children: [
|
||||
VideoSurface(
|
||||
),
|
||||
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(
|
||||
"李明辉",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
ColoredBox(
|
||||
color: Color(0xFF232426),
|
||||
child: Row(
|
||||
children: [
|
||||
_actionItem(icon: RemixIcons.video_on_fill, isActive: false),
|
||||
_actionItem(
|
||||
icon: RemixIcons.mic_off_fill,
|
||||
),
|
||||
_actionItem(
|
||||
icon: RemixIcons.volume_mute_fill,
|
||||
),
|
||||
_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,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
80
lib/pages/teacher/room/view/waiting_start.dart
Normal file
80
lib/pages/teacher/room/view/waiting_start.dart
Normal file
@@ -0,0 +1,80 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:app/utils/time.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class WaitingStart extends StatefulWidget {
|
||||
const WaitingStart({super.key});
|
||||
|
||||
@override
|
||||
State<WaitingStart> createState() => _WaitingStartState();
|
||||
}
|
||||
|
||||
class _WaitingStartState extends State<WaitingStart> {
|
||||
///剩余秒
|
||||
int _seconds = 0;
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
startCountDown();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
///开始倒计时
|
||||
void startCountDown() {
|
||||
//当前时间
|
||||
DateTime now = DateTime.now();
|
||||
//远端时间
|
||||
DateTime remote = DateTime.parse("2025-11-19 17:10:00".replaceFirst(' ', 'T'));
|
||||
setState(() {
|
||||
_seconds = remote.difference(now).inSeconds;
|
||||
});
|
||||
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
|
||||
setState(() {
|
||||
_seconds--;
|
||||
});
|
||||
if (_seconds <= 0) {
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
_start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///倒计时结束开始
|
||||
void _start() {}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Align(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"未到开播时间,到点后自动开播",
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
formatSeconds(_seconds),
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user