feat(ui): 登录页重设计并统一弹框主题渐变外壳
This commit is contained in:
1 parent
c027acc91f
commit
de7da64886
25 files changed
+905
-317
No files matched your search
@@ -0,0 +1,119 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../theme/app_colors.dart';
|
||||
import '../theme/app_dimens.dart';
|
||||
|
||||
/// 主题红晕渐变容器:弹框(居中)与底部弹层(半屏)共用的外壳。
|
||||
/// 纯黑弹框统一升级为「顶部红光 → 近黑」的家族渐变。
|
||||
class AppGlowPanel extends StatelessWidget {
|
||||
const AppGlowPanel({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.borderRadius = const BorderRadius.all(Radius.circular(20)),
|
||||
this.border = true,
|
||||
});
|
||||
|
||||
final Widget child;
|
||||
final BorderRadius borderRadius;
|
||||
final bool border;
|
||||
|
||||
static const _gradient = LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
AppColors.followingGlow,
|
||||
AppColors.followingGlowMid,
|
||||
Color(0xFF101012),
|
||||
],
|
||||
stops: [0, 0.22, 0.62],
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: _gradient,
|
||||
borderRadius: borderRadius,
|
||||
border: border
|
||||
? Border.all(color: AppColors.contentBorder)
|
||||
: null,
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 主题渐变确认弹框:替代 AlertDialog 的家族化外壳。
|
||||
/// 按钮沿用项目惯例:纯文字 TextButton,主操作品牌红。
|
||||
class AppGlowDialog extends StatelessWidget {
|
||||
const AppGlowDialog({
|
||||
super.key,
|
||||
this.title,
|
||||
this.content,
|
||||
this.contentChild,
|
||||
this.actions,
|
||||
this.contentTextStyle,
|
||||
});
|
||||
|
||||
final String? title;
|
||||
final String? content;
|
||||
|
||||
/// 富内容(表单/滚动区),与 [content] 二选一。
|
||||
final Widget? contentChild;
|
||||
final List<Widget>? actions;
|
||||
final TextStyle? contentTextStyle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bodyStyle = contentTextStyle ??
|
||||
TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: AppDimens.body,
|
||||
fontWeight: FontWeight.w400,
|
||||
);
|
||||
return Dialog(
|
||||
backgroundColor: AppColors.transparent,
|
||||
elevation: 0,
|
||||
child: AppGlowPanel(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(22, 22, 22, 10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (title != null) ...[
|
||||
Text(
|
||||
title!,
|
||||
style: TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontSize: AppDimens.sectionTitle,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
],
|
||||
if (content != null)
|
||||
Text(content!, style: bodyStyle)
|
||||
else
|
||||
?contentChild,
|
||||
if (actions != null && actions!.isNotEmpty) ...[
|
||||
const SizedBox(height: 18),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
for (var i = 0; i < actions!.length; i++) ...[
|
||||
if (i > 0) const SizedBox(width: 4),
|
||||
actions![i],
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import '../../l10n/app_localizations.dart';
|
||||
import '../../pages/auth/auth_view.dart';
|
||||
import '../data/services/auth_controller.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
import 'app_glow_panel.dart';
|
||||
|
||||
/// 打开登录 / 注册页(沿用现有 Navigator 风格,不引路由库)
|
||||
Future<void> openAuthPage(BuildContext context, {bool signUpMode = false}) {
|
||||
@@ -23,11 +24,11 @@ Future<bool> ensureSignedIn(BuildContext context) async {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final go = await showModalBottomSheet<bool>(
|
||||
context: context,
|
||||
backgroundColor: AppColors.card,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(18)),
|
||||
),
|
||||
builder: (sheetContext) => SafeArea(
|
||||
backgroundColor: AppColors.transparent,
|
||||
builder: (sheetContext) => AppGlowPanel(
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(18)),
|
||||
border: false,
|
||||
child: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 18, 20, 20),
|
||||
child: Column(
|
||||
@@ -71,6 +72,7 @@ Future<bool> ensureSignedIn(BuildContext context) async {
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import '../config/app_config.dart';
|
||||
import '../config/server_endpoint.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
import 'app_glow_panel.dart';
|
||||
|
||||
const String _title = '设置服务地址';
|
||||
const String _save = '保存';
|
||||
@@ -72,9 +73,9 @@ class _CatalogEndpointDialogState extends State<_CatalogEndpointDialog> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text(_title),
|
||||
content: SingleChildScrollView(
|
||||
return AppGlowDialog(
|
||||
title: _title,
|
||||
contentChild: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
Reference in new issue
Block a user