fix:UI对齐demo

This commit is contained in:
jingyun
2026-06-18 18:08:29 +08:00
parent f42ad566e0
commit 2d7523f901
14 changed files with 1613 additions and 355 deletions
@@ -0,0 +1,36 @@
import '../data/profile_models.dart';
class PriceColorPalette {
const PriceColorPalette({
required this.up,
required this.down,
required this.upBackground,
required this.downBackground,
});
final int up;
final int down;
final int upBackground;
final int downBackground;
}
const _redUpGreenDown = PriceColorPalette(
up: 0xFFC0392B,
down: 0xFF2E8B6F,
upBackground: 0xFFFBEDEA,
downBackground: 0xFFE7F2EE,
);
const _greenUpRedDown = PriceColorPalette(
up: 0xFF2E8B6F,
down: 0xFFC0392B,
upBackground: 0xFFE7F2EE,
downBackground: 0xFFFBEDEA,
);
PriceColorPalette priceColorPalette(PriceColorMode mode) {
return switch (mode) {
PriceColorMode.redUpGreenDown => _redUpGreenDown,
PriceColorMode.greenUpRedDown => _greenUpRedDown,
};
}
@@ -272,9 +272,9 @@ class PuritySettingsPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final settings = ref.watch(profileSettingsControllerProvider);
final groups = [
('黄金', ['足金9999', '足金999']),
('铂金', ['PT950']),
('白银', ['999银']),
('黄金', ['足金9999', '足金999', '22K', '18K']),
('铂金', ['PT990', 'PT950']),
('白银', ['999银', '925银']),
];
return _ActionScaffold(
@@ -282,17 +282,25 @@ class PuritySettingsPage extends ConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'材料价值 = 克重 × 纯度系数 × 现货价。系数可自定义,适配不同成色。',
style: TextStyle(
fontSize: 12,
height: 1.6,
color: Color(0xFF8A8780),
),
),
const SizedBox(height: 14),
for (final group in groups) ...[
_SectionLabel(group.$1),
_CenteredSectionLabel(group.$1),
PrototypeCard(
padding: EdgeInsets.zero,
child: Column(
children: [
for (final purity in group.$2) ...[
_SettingLikeRow(
icon: Icons.tune_outlined,
_MetricRow(
title: purity,
trailing: (settings.purityPresets[purity] ?? 1)
value: (settings.purityPresets[purity] ?? 1)
.toStringAsFixed(4),
onTap: () => _toast(context, '演示:自定义「$purity」纯度系数'),
),
@@ -304,6 +312,15 @@ class PuritySettingsPage extends ConsumerWidget {
),
if (group != groups.last) const SizedBox(height: 12),
],
const SizedBox(height: 8),
const Text(
'点任一行可自定义(演示) · 系数仅影响材料价值估算',
style: TextStyle(
fontSize: 11,
height: 1.6,
color: Color(0xFFB3AFA5),
),
),
],
),
);
@@ -317,8 +334,10 @@ class RecycleDiscountPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final settings = ref.watch(profileSettingsControllerProvider);
final notifier = ref.read(profileSettingsControllerProvider.notifier);
final preview =
483812.0 * (settings.recycleDiscounts[MetalType.gold] ?? 0.97);
final gold = settings.recycleDiscounts[MetalType.gold] ?? 0.97;
final platinum = settings.recycleDiscounts[MetalType.platinum] ?? 0.93;
final silver = settings.recycleDiscounts[MetalType.silver] ?? 0.88;
final preview = 483812.0 * gold;
return _ActionScaffold(
title: '回收折扣设置',
@@ -327,51 +346,88 @@ class RecycleDiscountPage extends ConsumerWidget {
children: [
PrototypeCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'回收参考预览',
style: TextStyle(fontSize: 13, color: Color(0xFF8A8780)),
const SizedBox(height: 2),
Row(
children: [
const Text(
'回收参考预览',
style: TextStyle(fontSize: 13, color: Color(0xFF8A8780)),
),
const Spacer(),
Text(
formatCny(preview),
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
height: 1,
),
),
],
),
const SizedBox(height: 8),
Text(
formatCny(preview),
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
height: 1,
Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 16,
),
decoration: BoxDecoration(
color: const Color(0xFFF8F7F3),
borderRadius: BorderRadius.circular(14),
),
child: Column(
children: [
_DiscountSliderRow(
metal: MetalType.gold,
value: gold,
onChanged: (value) =>
notifier.setRecycleDiscount(MetalType.gold, value),
),
const SizedBox(height: 4),
const PrototypeDivider(margin: EdgeInsets.zero),
_DiscountSliderRow(
metal: MetalType.platinum,
value: platinum,
onChanged: (value) => notifier.setRecycleDiscount(
MetalType.platinum,
value,
),
),
const SizedBox(height: 4),
const PrototypeDivider(margin: EdgeInsets.zero),
_DiscountSliderRow(
metal: MetalType.silver,
value: silver,
onChanged: (value) => notifier.setRecycleDiscount(
MetalType.silver,
value,
),
),
],
),
),
const SizedBox(height: 8),
const Text(
'按当前资产总估值和黄金折扣演示,实际以持仓金属分层计算',
'回收参考价 = 材料价值 × 折扣系数,恒标「参考」。同一系数也用于「兑换试算」的回收口径',
style: TextStyle(
fontSize: 12,
height: 1.6,
color: Color(0xFF8A8780),
),
),
const SizedBox(height: 4),
const Text(
'实务中不同金属折扣不同(足金≈95%、铂金≈78%、白银更低)。',
style: TextStyle(
fontSize: 11,
height: 1.5,
height: 1.6,
color: Color(0xFFB3AFA5),
),
),
],
),
),
const SizedBox(height: 14),
PrototypeCard(
padding: EdgeInsets.zero,
child: Column(
children: [
for (final entry in settings.recycleDiscounts.entries) ...[
_DiscountSliderRow(
metal: entry.key,
value: entry.value,
onChanged: (value) =>
notifier.setRecycleDiscount(entry.key, value),
),
if (entry.key != settings.recycleDiscounts.keys.last)
const PrototypeDivider(margin: EdgeInsets.zero),
],
],
),
),
],
),
);
@@ -736,73 +792,234 @@ class _WidgetPreview extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(18),
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
decoration: BoxDecoration(
color: const Color(0xFF1A1A17),
borderRadius: BorderRadius.circular(20),
color: const Color(0xFFE8E0D0),
borderRadius: BorderRadius.circular(24),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'6月15日 周日',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Color(0xFF5C584C),
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 14),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFF7F4EE),
borderRadius: BorderRadius.circular(22),
border: Border.all(color: const Color(0xFFDAD2C2), width: 0.5),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Row(
children: [
_GoldDot(),
SizedBox(width: 7),
Text(
'金值 · 我的贵金属',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w700,
),
),
Spacer(),
Text(
'16:11',
style: TextStyle(fontSize: 11, color: Color(0xFFB3AFA5)),
),
],
),
const SizedBox(height: 14),
const Text(
'¥ 483,812',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
height: 1,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 9,
vertical: 4,
),
decoration: BoxDecoration(
color: const Color(0xFFFBEDEA),
borderRadius: BorderRadius.circular(999),
),
child: const Text(
'+¥5,821 · +1.21% 今日',
style: TextStyle(
fontSize: 12,
color: Color(0xFFC0392B),
fontWeight: FontWeight.w600,
),
),
),
const SizedBox(height: 14),
const Row(
children: [
Expanded(
child: _MiniMetal(label: '', value: '64%'),
),
SizedBox(width: 8),
Expanded(
child: _MiniMetal(label: '', value: '22%'),
),
SizedBox(width: 8),
Expanded(
child: _MiniMetal(label: '', value: '14%'),
),
],
),
],
),
),
const SizedBox(height: 16),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: const Color(0xFFF7F4EE),
borderRadius: BorderRadius.circular(22),
border: Border.all(
color: const Color(0xFFDAD2C2),
width: 0.5,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'黄金 元/克',
style: TextStyle(
fontSize: 12,
color: Color(0xFF8A8780),
),
),
const SizedBox(height: 4),
const Text(
'943.05',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
height: 1,
),
),
const SizedBox(height: 4),
const Text(
'▲ +0.50%',
style: TextStyle(
fontSize: 12,
color: Color(0xFFC0392B),
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 12),
SizedBox(
height: 32,
child: PrototypeLineChart(
values: const [
27,
31,
29,
35,
33,
37,
42,
40,
46,
44,
50,
53,
],
),
),
],
),
),
),
const SizedBox(width: 14),
const Expanded(
child: Column(
children: [
Row(
children: [
Expanded(
child: _MiniSquare(
color: Color(0xFFB5862A),
label: '金值',
),
),
SizedBox(width: 10),
Expanded(child: _MiniSquare(color: Color(0xFFCBA86A))),
],
),
SizedBox(height: 10),
Row(
children: [
Expanded(child: _MiniSquare(color: Color(0xFFB7BEC6))),
SizedBox(width: 10),
Expanded(child: _MiniSquare(color: Color(0xFFC7C2B5))),
],
),
],
),
),
],
),
],
),
);
}
}
class _MiniSquare extends StatelessWidget {
const _MiniSquare({required this.color, this.label});
final Color color;
final String? label;
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1,
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFF7F4EE),
borderRadius: BorderRadius.circular(18),
color: color,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
children: [
_GoldDot(),
SizedBox(width: 7),
Text(
'金值',
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w700),
),
],
),
const SizedBox(height: 14),
const Text(
'¥ 483,812',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
height: 1,
alignment: Alignment.center,
child: label == null
? null
: const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.paid_outlined, color: Colors.white, size: 22),
SizedBox(height: 4),
Text(
'金值',
style: TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.w700,
),
),
],
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 4),
decoration: BoxDecoration(
color: const Color(0xFFFBEDEA),
borderRadius: BorderRadius.circular(999),
),
child: const Text(
'+¥5,821 · +1.21% 今日',
style: TextStyle(
fontSize: 12,
color: Color(0xFFC0392B),
fontWeight: FontWeight.w600,
),
),
),
const SizedBox(height: 14),
const Row(
children: [
Expanded(
child: _MiniMetal(label: '', value: '64%'),
),
SizedBox(width: 8),
Expanded(
child: _MiniMetal(label: '', value: '22%'),
),
SizedBox(width: 8),
Expanded(
child: _MiniMetal(label: '', value: '14%'),
),
],
),
],
),
),
);
}
@@ -984,17 +1201,15 @@ class _SettingLikeRow extends StatelessWidget {
required this.icon,
required this.title,
required this.trailing,
this.onTap,
});
final IconData icon;
final String title;
final String trailing;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
final content = Padding(
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 13),
child: Row(
children: [
@@ -1014,15 +1229,11 @@ class _SettingLikeRow extends StatelessWidget {
fontWeight: FontWeight.w600,
),
),
if (onTap != null) ...[
const SizedBox(width: 4),
const Icon(Icons.chevron_right, size: 16, color: Color(0xFFB3AFA5)),
],
const SizedBox(width: 4),
const Icon(Icons.chevron_right, size: 16, color: Color(0xFFB3AFA5)),
],
),
);
if (onTap == null) return content;
return InkWell(onTap: onTap, child: content);
}
}
@@ -1106,18 +1317,57 @@ class _InfoParagraph extends StatelessWidget {
}
}
class _SectionLabel extends StatelessWidget {
const _SectionLabel(this.label);
class _CenteredSectionLabel extends StatelessWidget {
const _CenteredSectionLabel(this.label);
final String label;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(2, 0, 2, 7),
child: Text(
label,
style: const TextStyle(fontSize: 12, color: Color(0xFF8A8780)),
padding: const EdgeInsets.symmetric(vertical: 12),
child: Center(
child: Text(
label,
style: const TextStyle(fontSize: 12, color: Color(0xFF8A8780)),
),
),
);
}
}
class _MetricRow extends StatelessWidget {
const _MetricRow({
required this.title,
required this.value,
required this.onTap,
});
final String title;
final String value;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18),
child: Row(
children: [
Expanded(child: Text(title, style: const TextStyle(fontSize: 15))),
Text(
value,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w700,
color: Color(0xFF1F1D18),
),
),
const SizedBox(width: 6),
const Icon(Icons.chevron_right, size: 16, color: Color(0xFFB3AFA5)),
],
),
),
);
}
@@ -6,6 +6,7 @@ import 'package:url_launcher/url_launcher_string.dart';
import '../../../common/config/app_h5_urls.dart';
import '../../../common/router/app_router.dart';
import '../../../common/widgets/app_toast.dart';
import '../../../common/widgets/prototype_ui.dart';
import '../../auth/application/auth_controller.dart';
import '../../auth/data/auth_models.dart';
@@ -140,14 +141,7 @@ class ProfilePage extends ConsumerWidget {
backgroundColor: const Color(0xFFEAF2ED),
iconColor: const Color(0xFF5E8E75),
),
],
),
),
const SizedBox(height: 12),
PrototypeCard(
padding: EdgeInsets.zero,
child: Column(
children: [
const PrototypeDivider(margin: EdgeInsets.zero),
_SettingRow(
icon: Icons.grid_view_outlined,
title: '添加桌面小组件',
@@ -156,7 +150,14 @@ class ProfilePage extends ConsumerWidget {
backgroundColor: const Color(0xFFF6ECD6),
iconColor: const Color(0xFFB5862A),
),
const PrototypeDivider(margin: EdgeInsets.zero),
],
),
),
const SizedBox(height: 12),
PrototypeCard(
padding: EdgeInsets.zero,
child: Column(
children: [
_SettingRow(
icon: Icons.tune_outlined,
title: '纯度系数管理',
@@ -180,7 +181,17 @@ class ProfilePage extends ConsumerWidget {
icon: Icons.palette_outlined,
title: '涨跌颜色',
trailing: settings.priceColorMode.label,
onTap: () => _showPriceColorSheet(context, ref),
onTap: () {
final nextMode =
settings.priceColorMode ==
PriceColorMode.redUpGreenDown
? PriceColorMode.greenUpRedDown
: PriceColorMode.redUpGreenDown;
ref
.read(profileSettingsControllerProvider.notifier)
.setPriceColorMode(nextMode);
_toast(context, '已切换为「${nextMode.label}');
},
backgroundColor: const Color(0xFFE9F3F1),
iconColor: const Color(0xFF4E8B7B),
),
@@ -189,7 +200,7 @@ class ProfilePage extends ConsumerWidget {
icon: Icons.currency_yen_outlined,
title: '显示币种',
trailing: '¥ CNY',
onTap: () => _showCurrencySheet(context),
onTap: () => _toast(context, '当前仅支持 ¥ CNY'),
backgroundColor: const Color(0xFFF1EFE9),
iconColor: const Color(0xFF7F7A73),
),
@@ -293,10 +304,6 @@ class ProfilePage extends ConsumerWidget {
context.push(AppRoutes.profileWidget);
}
Future<void> _showPriceColorSheet(BuildContext context, WidgetRef ref) async {
context.push(AppRoutes.profilePriceColor);
}
Future<void> _showPuritySheet(
BuildContext context,
ProfileSettings settings,
@@ -311,15 +318,15 @@ class ProfilePage extends ConsumerWidget {
context.push(AppRoutes.profileRecycle);
}
Future<void> _showCurrencySheet(BuildContext context) async {
context.push(AppRoutes.profileCurrency);
}
void _showAbout(BuildContext context) {
context.push(AppRoutes.profileAbout);
}
}
void _toast(BuildContext context, String message) {
toastInfo(msg: message);
}
class _MenuRow extends StatelessWidget {
const _MenuRow({
required this.title,