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

169 lines
5.6 KiB
Dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:new_learn/core/api/auth/api.dart';
import 'package:new_learn/core/providers/user_provider.dart';
import 'package:new_learn/core/utils/img_url.dart';
import 'package:new_learn/features/conquerPackage/classExercises/widgets/exercise_styles.dart';
/// ============================================================
/// 【GuideModal】攻克报告后功能引导遮罩
/// 1:1 对标 Vue components/GuideModal/GuideModal.vue
///
/// 行为:点击任意位置 → ChangeShowGuide → 刷新用户信息 → 关闭
/// ============================================================
class GuideModal extends ConsumerStatefulWidget {
const GuideModal({
super.key,
required this.show,
required this.onClose,
});
final bool show;
final VoidCallback onClose;
@override
ConsumerState<GuideModal> createState() => _GuideModalState();
}
class _GuideModalState extends ConsumerState<GuideModal> {
bool _closing = false;
Future<void> _handleClose() async {
if (_closing) return;
_closing = true;
try {
await UserApi.changeShowGuide();
// 强制刷新全局用户信息(失败也不阻塞关闭,refresh 内部已兜底)
await ref.read(currentUserProvider.notifier).refresh();
} catch (_) {
// 对标 Vue:接口失败仅打印,不影响关闭
} finally {
widget.onClose();
}
}
@override
Widget build(BuildContext context) {
if (!widget.show) return const SizedBox.shrink();
final pad = isPadDevice(context);
final buttonWidth = pad ? 255.w : 165.w;
return Positioned.fill(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _handleClose,
child: Stack(
children: [
const Positioned.fill(
child: ColoredBox(color: Color(0x8C000000)), // rgba(0,0,0,.55)
),
// 「点击任意位置退出」居中白字
Positioned.fill(
child: Center(
child: Text(
'点击任意位置退出',
style: TextStyle(
color: Colors.white,
fontSize: 16.sp,
fontWeight: FontWeight.w400,
height: 1.375,
),
),
),
),
// 引导图 bottom 292rpx
Positioned(
left: 0,
right: 0,
bottom: 146.h,
height: 139.h,
child: CachedNetworkImage(
imageUrl: ImgUrl.build(
'/StaticResource/2026-06-09/guide_pg1781012082368.png',
),
fit: BoxFit.contain,
),
),
// 箭头 bottom 206rpx / left 180rpx
Positioned(
left: 90.w,
bottom: 103.h,
width: 12.w,
height: 50.h,
child: CachedNetworkImage(
imageUrl: ImgUrl.build(
'/StaticResource/2026-06-09/guide_arrow1781012131243.png',
),
fit: BoxFit.contain,
),
),
// 假按钮组 bottom 80rpx
Positioned(
left: 0,
right: 0,
bottom: 40.h,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: buttonWidth,
height: 49.h,
margin: EdgeInsets.only(right: 17.w),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50.r),
border: Border.all(
color: const Color(0xFF66A6FF),
width: 1.w,
),
),
child: Text(
'全部解析',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: const Color(0xFF66A6FF),
),
),
),
Container(
width: buttonWidth,
height: 49.h,
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF3373FF), Color(0xFF3D7DF5)],
),
borderRadius: BorderRadius.circular(50.r),
boxShadow: const [
BoxShadow(
color: Color(0x4D3D7DF5),
offset: Offset(0, 7.5),
blurRadius: 15,
),
],
),
child: Text(
'错题解析',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
],
),
),
],
),
),
);
}
}