Files
App.K12.Student.Miniapp_Flu…/lib/features/conquerPackage/classExercises/widgets/pause_popup.dart
T
2026-09-28 20:12:34 +08:00

228 lines
7.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// ============================================================
/// 【PausePopup】暂停答题弹窗
/// (1:1 迁移 Vue components/PausePopup/PausePopup.vue)
///
/// - 遮罩 rgba(0,0,0,.7),点击任意位置关闭(onClose)
/// - 组件独立秒表:每次 show=true 从 0 开始计时,HH:MM:SS(不足 1 小时隐去小时)
/// - 文案:共 {totalCount} 道题,还剩 {remainingCount} 道题待完成
/// ============================================================
library;
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:new_learn/core/utils/img_url.dart';
import 'exercise_styles.dart';
class PausePopup extends StatefulWidget {
const PausePopup({
super.key,
required this.show,
this.totalCount = 20,
this.remainingCount = 0,
this.onClose,
});
final bool show;
final int totalCount;
final int remainingCount;
final VoidCallback? onClose;
@override
State<PausePopup> createState() => _PausePopupState();
}
class _PausePopupState extends State<PausePopup> {
int _seconds = 0;
Timer? _timer;
@override
void initState() {
super.initState();
_syncTimer(widget.show);
}
@override
void didUpdateWidget(covariant PausePopup oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.show != widget.show) {
_syncTimer(widget.show);
}
}
@override
void dispose() {
_stopTimer();
super.dispose();
}
void _syncTimer(bool show) {
if (show) {
_startTimer();
} else {
_stopTimer();
}
}
void _startTimer() {
_timer?.cancel();
_seconds = 0;
_timer = Timer.periodic(const Duration(seconds: 1), (_) {
if (mounted) setState(() => _seconds++);
});
}
void _stopTimer() {
_timer?.cancel();
_timer = null;
}
String _two(int v) => v < 10 ? '0$v' : '$v';
@override
Widget build(BuildContext context) {
if (!widget.show) return const SizedBox.shrink();
final isPad = isPadDevice(context);
final hours = _seconds ~/ 3600;
final showHours = hours > 0;
final minutes = (_seconds % 3600) ~/ 60;
final secs = _seconds % 60;
final unitW = isPad ? 49.w : 44.w; // 88/98rpx
final unitH = isPad ? 45.h : 40.h; // 80/90rpx
return Positioned.fill(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: widget.onClose,
child: ColoredBox(
color: const Color(0xB3000000), // rgba(0,0,0,.7)
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Transform.translate(
offset: Offset(isPad ? -35.w : 0, 0), // margin-left: -70rpx
child: Container(
width: isPad ? 315.5.w : 250.w, // 500/631rpx
height: isPad ? 299.5.h : 249.h, // 498/599rpx
padding: EdgeInsets.only(top: isPad ? 175.h : 137.5.h),
decoration: BoxDecoration(
image: DecorationImage(
image: CachedNetworkImageProvider(
ImgUrl.build(
isPad
? '/StaticResource/2026-06-03/conquer-pause-bg-Pad1780466965818.png'
: '/StaticResource/2026-04-08/conquer-pause-bg.png',
),
),
fit: BoxFit.fill,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (showHours) ...[
_timeUnit(unitW, unitH, _two(hours)),
_timeSep(),
],
_timeUnit(unitW, unitH, _two(minutes)),
_timeSep(),
_timeUnit(unitW, unitH, _two(secs)),
],
),
SizedBox(height: 15.h), // margin-t-30
Text.rich(
TextSpan(
style: TextStyle(
fontSize: 13.sp, // 26rpx
color: ExerciseColors.subtitle,
),
children: [
const TextSpan(text: '共'),
TextSpan(
text: '${widget.totalCount}',
style: const TextStyle(
color: Color(0xFF1578FF),
),
),
const TextSpan(text: '道题,还剩'),
TextSpan(
text: '${widget.remainingCount}',
style: const TextStyle(
color: Color(0xFF1578FF),
),
),
const TextSpan(text: '道题待完成'),
],
),
),
],
),
),
),
SizedBox(height: 25.h), // margin-t-50
Text(
'点击任意位置继续',
style: TextStyle(
fontSize: 14.sp, // 28rpx
color: const Color(0xFFB4C2E0),
),
),
],
),
),
),
),
);
}
Widget _timeUnit(double w, double h, String text) {
return Container(
width: w,
height: h,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color(0xFFF2F8FF),
borderRadius: BorderRadius.circular(6.r),
boxShadow: [
BoxShadow(
color: const Color(0x1A1578FF),
offset: Offset(0, 2.h),
blurRadius: 6.h,
),
],
),
child: Text(
text,
style: TextStyle(
fontSize: 20.sp, // 40rpx
fontWeight: FontWeight.w600,
color: const Color(0xFF1578FF),
),
),
);
}
Widget _timeSep() {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10.w), // margin-rl-10 + 视觉间距
child: Text(
':',
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.w600,
color: const Color(0xFF1578FF),
),
),
);
}
}