合并代码

This commit is contained in:
chenshuainan
2026-09-09 16:15:05 +08:00
parent 592e576319
commit 7acf745295
24 changed files with 1864 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/// ============================================================
/// 【CenterToast】居中轻量提示 —— 对标 uni.showToast(icon: 'none')
///
/// 一、适用场景:
/// 表单校验失败("请填写账号"/"请填写密码")、轻量成功提示等
/// 不需要用户确认、1.2s 自动消失、不阻塞交互(IgnorePointer)。
///
/// 二、与 SnackBar / ConfirmBox 的分工:
/// CenterToast → 短暂轻量提示,自动消失,中间弹出
/// SnackBar → 底部提示(信息可能较长),可手动关闭
/// ConfirmBox → 需要用户决策的确认框,双按钮
///
/// 三、用法:
/// CenterToast.show(context, '请填写账号');
/// ============================================================
class CenterToast {
CenterToast._();
static OverlayEntry? _current;
static void show(
BuildContext context,
String msg, {
Duration duration = const Duration(milliseconds: 1200),
}) {
// 连续调用时先移除上一个,避免叠加
_current?.remove();
late final OverlayEntry entry;
entry = OverlayEntry(
builder: (_) => Positioned.fill(
child: IgnorePointer(
child: Center(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 14.h),
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.75),
borderRadius: BorderRadius.circular(12.r),
),
child: Text(
msg,
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
decoration: TextDecoration.none,
),
),
),
),
),
),
);
_current = entry;
Overlay.of(context).insert(entry);
Future<void>.delayed(duration, () {
if (entry.mounted && _current == entry) {
entry.remove();
_current = null;
}
});
}
}
@@ -0,0 +1,117 @@
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 'package:new_learn/core/utils/screen_adapt_template.dart';
/// ============================================================
/// 【ResolveProblemBox】攻克任务卡(对标 Vue ResolveProblem.vue)
///
/// 用于展示"刚刚攻克了 「xxx」 的所有高难考点"类提示。
/// 由 class_update_widgets.dart 抽离,详情页也可复用。
/// 背景图 + 云朵装饰走 CDN,与 Vue 版 $img('/StaticResource/...') 同源。
/// ============================================================
class ResolveProblemBox extends StatelessWidget {
const ResolveProblemBox({
super.key,
this.title = '刚刚攻克了',
required this.desc,
});
/// 标题(默认 "刚刚攻克了")
final String title;
/// 攻克的知识点描述(如 "二次函数最值问题")
final String desc;
@override
Widget build(BuildContext context) {
final isPad = MediaQuery.sizeOf(context).width >= AppAdapt.tabletBreakpoint;
final bgUrl = ImgUrl.build(
isPad
? '/StaticResource/2026-06-02/resolve-bg2-pad1780388446390.png'
: '/StaticResource/2026-05-07/resolve-bg2.png',
);
final cloudUrl = ImgUrl.build(
isPad
? '/StaticResource/2026-06-02/cloud-pad1780388443051.png'
: '/StaticResource/2026-05-07/cloud.png',
);
final cloudHeight = isPad ? 107.h : 74.h;
return Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
image: DecorationImage(
image: CachedNetworkImageProvider(bgUrl),
fit: BoxFit.fill,
alignment: Alignment.topCenter,
),
),
// 裁剪所有子元素到圆角内(对标 Vue overflow:hidden)
clipBehavior: Clip.antiAlias,
child: Stack(
// Stack 默认不裁剪 Positioned 子元素,必须显式设置
clipBehavior: Clip.hardEdge,
children: [
// 底部云朵装饰(贴底部,z-index 1)
Positioned(
left: 0,
right: 0,
bottom: 0,
child: CachedNetworkImage(
imageUrl: cloudUrl,
height: cloudHeight,
width: double.infinity,
fit: BoxFit.fitWidth,
),
),
// 文本层(padding 在云朵之上,z-index 2)
Padding(
padding: EdgeInsets.fromLTRB(19.w, 25.h, 19.w, 11.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w900,
color: Color(0xFF1D2B47),
),
),
SizedBox(height: 3.h),
Text.rich(
TextSpan(
children: [
TextSpan(
text: '「$desc」',
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Color(0xFF1D2B47),
),
),
const TextSpan(
text: ' 的所有高难考点!',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Color(0xFF45597E),
),
),
],
),
),
],
),
),
],
),
);
}
}