Files
App.K12.Student.Miniapp_Flu…/lib/core/components/confirm_box.dart
T
崔宝新 7175bf3054 feat: 新增全局确认弹窗、多页面UI优化与网络日志开关
1.  新增全局二次确认弹窗组件confirm_box,支持自定义参数并对标小程序实现
2.  优化班级板块多处UI:
    - 修复point_rank_view中Web端字体溢出问题,使用FittedBox自适应缩放
    - 重构class_update_widgets的PostCard,新增卡片背景控制开关并替换光晕实现
    - 优化class_update_view的在线同学栏与头像组布局,支持动态计算展示数量
    - 调整my_update_detail_page的评论区结构,修复评论高亮与删除浮层定位问题
3.  为dio_client新增网络日志总开关,可按需开启请求响应打印
4.  修复多处代码格式与注释细节问题
2026-09-07 15:01:14 +08:00

185 lines
6.2 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.
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../utils/img_url.dart';
/// ============================================================
/// 【ConfirmBox】全局二次确认弹窗 —— 对标小程序 components/ConfirmBox
///
/// 一、与 Vue3 版的架构差异:
/// 小程序不支持动态插入 DOM,所以 Vue 版需要每个页面手动放置
/// `<ConfirmBox />`,并在 service.js 里按路由注册 controller。
/// Flutter 的 showDialog 可以从任意 context 直接弹出(等价于 Web
/// 动态挂载),因此这里无需注册机制,单文件即可全局使用。
///
/// 二、用法(对标 Vue 的 `await proxy.$confirm({...})`):
/// final ok = await showConfirmBox(
/// context,
/// title: '提示',
/// content: '确定要删除吗?',
/// );
/// 点"确定"返回 true;点"取消"、点遮罩、按返回键返回 false。
/// ============================================================
Future<bool> showConfirmBox(
BuildContext context, {
String title = '提示',
String content = '',
String cancelText = '取消',
String confirmText = '确定',
bool showCancel = true,
double? minWidth, // 弹窗最小宽度(逻辑像素,调用方自行 .w 换算)
}) {
return showDialog<bool>(
context: context,
barrierDismissible: true, // 点遮罩关闭 → false(对标 onPopupClose)
barrierColor: Colors.black54,
builder: (_) => ConfirmBox(
title: title,
content: content,
cancelText: cancelText,
confirmText: confirmText,
showCancel: showCancel,
minWidth: minWidth,
),
).then((result) => result ?? false);
}
class ConfirmBox extends StatelessWidget {
const ConfirmBox({
super.key,
required this.title,
required this.content,
required this.cancelText,
required this.confirmText,
required this.showCancel,
this.minWidth,
});
final String title;
final String content;
final String cancelText;
final String confirmText;
final bool showCancel;
final double? minWidth;
@override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.transparent,
child: Container(
padding: EdgeInsets.symmetric(vertical: 30.w, horizontal: 15.w), // 60rpx 30rpx
constraints:
minWidth != null ? BoxConstraints(minWidth: minWidth!) : null,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.w), // 40rpx
image: DecorationImage(
image: NetworkImage(
ImgUrl.build('/StaticResource/2026-03-31/header-bac.png')),
fit: BoxFit.fill, // background-size: 100% 100%
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (title.isNotEmpty)
Text(
title,
style: TextStyle(
fontSize: 16.sp, // 32rpx
fontWeight: FontWeight.w600,
color: const Color(0xFF1D2B47),
),
),
if (content.isNotEmpty)
Padding(
padding: EdgeInsets.only(top: 18.w), // 36rpx
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 263.w), // max-width 526rpx
child: Text(
content,
style: TextStyle(
fontSize: 14.sp, // 28rpx
color: const Color(0xFF1D2B47),
),
),
),
),
Padding(
padding: EdgeInsets.only(top: 23.w), // 46rpx
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (showCancel) ...[
_buildButton(
text: cancelText,
backgroundColor: const Color(0xFFFDFFFF),
textColor: const Color(0xFF6195F6),
onTap: () => Navigator.of(context).pop(false),
),
SizedBox(width: 10.w), // 20rpx
],
_buildButton(
text: confirmText,
gradient: const LinearGradient(
// CSS: linear-gradient(360deg, #8AD1FD -11.22%, #3C84FF 60.2%, #3D7DF5 100%)
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Color(0xFF8AD1FD),
Color(0xFF3C84FF),
Color(0xFF3D7DF5),
],
stops: [0, 0.602, 1],
),
textColor: Colors.white,
onTap: () => Navigator.of(context).pop(true),
),
],
),
),
],
),
),
);
}
/// 胶囊按钮(对标 default-button5 渐变确定键 / default-button6 白底取消键)
Widget _buildButton({
required String text,
required Color textColor,
required VoidCallback onTap,
Color? backgroundColor,
Gradient? gradient,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
height: 46.w, // 92rpx
padding: EdgeInsets.symmetric(horizontal: 20.w),
constraints: BoxConstraints(minWidth: 135.w), // min-width 270rpx
alignment: Alignment.center,
decoration: BoxDecoration(
color: backgroundColor,
gradient: gradient,
borderRadius: BorderRadius.circular(100), // border-radius: 100px
boxShadow: gradient != null
? [
// CSS: 0px 15px 11.3px rgba(61,125,245,0.08)
// (inset 内发光 Flutter 不支持,省略)
BoxShadow(
color: const Color(0x143D7DF5),
offset: Offset(0, 15.w),
blurRadius: 11.w,
),
]
: null,
),
child: Text(
text,
style: TextStyle(fontSize: 16.sp, color: textColor), // 32rpx
),
),
);
}
}