新增赛事信息页
This commit is contained in:
@@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:recording_tool/app/router/app_navigator.dart';
|
||||
import 'package:recording_tool/features/auth/view_model_auth/view_model_auth.dart';
|
||||
import 'package:recording_tool/features/scan_qrcode/pages/page_scan_qrcode.dart';
|
||||
import 'package:recording_tool/features/events/pages/page_event_info.dart';
|
||||
import 'package:recording_tool/shared/widgets/widgets.dart';
|
||||
|
||||
class AuthPageWidget extends ConsumerStatefulWidget {
|
||||
@@ -62,7 +62,7 @@ class _AuthPageWidgetState extends ConsumerState<AuthPageWidget> {
|
||||
.auth(code ?? '');
|
||||
if (!mounted) return;
|
||||
if (success) {
|
||||
AppNavigator.push(const ScanQrCodePage());
|
||||
AppNavigator.push(const EventInfoPage());
|
||||
return;
|
||||
}
|
||||
final message = ref.read(authProvider).errorMessage;
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:recording_tool/app/router/app_navigator.dart';
|
||||
import 'package:recording_tool/features/recording/pages/page_record.dart';
|
||||
|
||||
class EventInfoPage extends StatelessWidget {
|
||||
const EventInfoPage({super.key});
|
||||
|
||||
static const _profile = EventProfile(
|
||||
avatarLabel: '头像',
|
||||
name: '王东方',
|
||||
phone: '199966666527',
|
||||
eventTitle: '全国青少年无人机大赛',
|
||||
);
|
||||
|
||||
static const _items = [
|
||||
EventScheduleItem(
|
||||
name: '个人飞行赛',
|
||||
group: '小学组',
|
||||
venue: '场地 1',
|
||||
time: '7月1日 12:00-15:00',
|
||||
laneNo: '10号',
|
||||
),
|
||||
EventScheduleItem(
|
||||
name: '空中足球赛',
|
||||
group: '小学组',
|
||||
venue: '场地 1',
|
||||
time: '7月2日 12:00-15:00',
|
||||
status: '已完成',
|
||||
),
|
||||
EventScheduleItem(
|
||||
name: '穿越竞速赛',
|
||||
group: '小学组',
|
||||
venue: '场地 2',
|
||||
time: '7月3日 09:00-11:30',
|
||||
laneNo: '06号',
|
||||
),
|
||||
EventScheduleItem(
|
||||
name: '编队飞行赛',
|
||||
group: '小学组',
|
||||
venue: '场地 3',
|
||||
time: '7月3日 14:00-16:00',
|
||||
status: '待开始',
|
||||
),
|
||||
];
|
||||
void onItemTap(EventScheduleItem item) {
|
||||
debugPrint('item tapped: ${item.name}');
|
||||
AppNavigator.push(const RecordingPage());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_Header(onBack: () => AppNavigator.pop(context: context)),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.fromLTRB(62.w, 8.h, 62.w, 40.h),
|
||||
child: Column(
|
||||
children: [
|
||||
const _ProfileSection(profile: _profile),
|
||||
SizedBox(height: 82.h),
|
||||
Text(
|
||||
_profile.eventTitle,
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp,
|
||||
height: 1.2,
|
||||
color: const Color(0xFF2F2F2F),
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.h),
|
||||
SizedBox(
|
||||
height: 400.h,
|
||||
child: ListView.builder(
|
||||
itemCount: _items.length,
|
||||
itemBuilder: (context, index) => _ScheduleCard(
|
||||
item: _items[index],
|
||||
onTap: () => onItemTap(_items[index]),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EventProfile {
|
||||
const EventProfile({
|
||||
required this.avatarLabel,
|
||||
required this.name,
|
||||
required this.phone,
|
||||
required this.eventTitle,
|
||||
});
|
||||
|
||||
final String avatarLabel;
|
||||
final String name;
|
||||
final String phone;
|
||||
final String eventTitle;
|
||||
}
|
||||
|
||||
class EventScheduleItem {
|
||||
const EventScheduleItem({
|
||||
required this.name,
|
||||
required this.group,
|
||||
required this.venue,
|
||||
required this.time,
|
||||
this.laneNo,
|
||||
this.status,
|
||||
});
|
||||
|
||||
final String name;
|
||||
final String group;
|
||||
final String venue;
|
||||
final String time;
|
||||
final String? laneNo;
|
||||
final String? status;
|
||||
}
|
||||
|
||||
class _Header extends StatelessWidget {
|
||||
const _Header({required this.onBack});
|
||||
|
||||
final VoidCallback onBack;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 52.h,
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: IconButton(
|
||||
onPressed: onBack,
|
||||
icon: Icon(Icons.arrow_back_ios_new, size: 32.r),
|
||||
color: Colors.black,
|
||||
tooltip: '返回',
|
||||
padding: EdgeInsets.only(left: 16.w),
|
||||
constraints: BoxConstraints(minWidth: 56.w, minHeight: 52.h),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ProfileSection extends StatelessWidget {
|
||||
const _ProfileSection({required this.profile});
|
||||
|
||||
final EventProfile profile;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
// width: 225.w,
|
||||
// height: 184.h,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: const Color(0xFF7A7A7A)),
|
||||
),
|
||||
child: Text(
|
||||
profile.avatarLabel,
|
||||
style: TextStyle(fontSize: 20.sp, color: const Color(0xFF2F2F2F)),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 28.w),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 30.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
profile.name,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 22.sp,
|
||||
height: 1.2,
|
||||
color: const Color(0xFF2F2F2F),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 36.h),
|
||||
Text(
|
||||
profile.phone,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 22.sp,
|
||||
height: 1.2,
|
||||
color: const Color(0xFF2F2F2F),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ScheduleCard extends StatelessWidget {
|
||||
const _ScheduleCard({required this.item, required this.onTap});
|
||||
|
||||
final EventScheduleItem item;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
color: Colors.white,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
constraints: BoxConstraints(minHeight: 138.h),
|
||||
padding: EdgeInsets.fromLTRB(10.w, 14.h, 14.w, 0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: const Color(0xFF7A7A7A)),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${item.name} (${item.group})',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp,
|
||||
height: 1.2,
|
||||
color: const Color(0xFF2F2F2F),
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 26.h),
|
||||
Text(
|
||||
item.venue,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp,
|
||||
height: 1.2,
|
||||
color: const Color(0xFF2F2F2F),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 26.h),
|
||||
Text(
|
||||
item.time,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp,
|
||||
height: 1.2,
|
||||
color: const Color(0xFF2F2F2F),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12.w),
|
||||
SizedBox(
|
||||
width: 148.w,
|
||||
height: 120.h,
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: _ScheduleBadge(item: item),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ScheduleBadge extends StatelessWidget {
|
||||
const _ScheduleBadge({required this.item});
|
||||
|
||||
final EventScheduleItem item;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (item.status != null) {
|
||||
return CustomPaint(
|
||||
painter: _CutCornerBorderPainter(color: const Color(0xFF7A7A7A)),
|
||||
child: SizedBox(
|
||||
width: 148.w,
|
||||
height: 90.h,
|
||||
child: Center(
|
||||
child: Text(
|
||||
item.status!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 20.sp, color: const Color(0xFF2F2F2F)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Text(
|
||||
item.laneNo ?? '',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 34.sp,
|
||||
height: 1,
|
||||
color: const Color(0xFF2F2F2F),
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CutCornerBorderPainter extends CustomPainter {
|
||||
const _CutCornerBorderPainter({required this.color});
|
||||
|
||||
final Color color;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final side = 12.r;
|
||||
final path = Path()
|
||||
..moveTo(side, 0)
|
||||
..lineTo(size.width - side, 0)
|
||||
..lineTo(size.width, side)
|
||||
..lineTo(size.width, size.height - side)
|
||||
..lineTo(size.width - side, size.height)
|
||||
..lineTo(side, size.height)
|
||||
..lineTo(0, size.height - side)
|
||||
..lineTo(0, side)
|
||||
..close();
|
||||
final paint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1
|
||||
..color = color;
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant _CutCornerBorderPainter oldDelegate) {
|
||||
return oldDelegate.color != color;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:recording_tool/app/router/app_navigator.dart';
|
||||
import 'package:recording_tool/features/recording/pages/page_record.dart';
|
||||
import 'package:recording_tool/features/scan_qrcode/pages/page_push_test.dart';
|
||||
import 'package:recording_tool/shared/widgets/app_bar.dart';
|
||||
import 'package:recording_tool/shared/widgets/app_button.dart';
|
||||
import 'package:recording_tool/shared/widgets/app_qr_scanner_dialog.dart';
|
||||
|
||||
Reference in New Issue
Block a user