Files
KiriMemo/lib/pages/account_page.dart
T
pluv 22715f7247 feat: manage, account and help pages
- 管理页:单元集 / 计划 / 算法三个维度,卡片带元数据
- 账户页:资料、学习数据、竖直分组的四个功能入口
- 新增设置、文档与帮助(底部可上滑助手)、反馈、关于四个页面
- 抽出 StatBlock 与 GroupedListSection 共用组件
- 关闭 Android 预测式返回,转场改为 M3 水平滑入
2026-10-24 15:21:30 +08:00

167 lines
4.5 KiB
Dart

import 'package:flutter/material.dart';
import '../models/account_profile.dart';
import '../widgets/grouped_list_section.dart';
import '../widgets/stat_block.dart';
import 'about_page.dart';
import 'docs_page.dart';
import 'feedback_page.dart';
import 'settings_page.dart';
/// 账户页:资料、学习数据、功能入口。
class AccountPage extends StatelessWidget {
const AccountPage({super.key});
static const AccountProfile _profile = AccountProfile.sample;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('账户')),
body: ListView(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 24),
children: const <Widget>[
_ProfileCard(profile: _profile),
SizedBox(height: 12),
_StatsCard(profile: _profile),
SizedBox(height: 22),
_ActionList(),
],
),
);
}
}
class _ProfileCard extends StatelessWidget {
const _ProfileCard({required this.profile});
final AccountProfile profile;
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final ColorScheme colors = theme.colorScheme;
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: colors.surfaceContainerLow,
borderRadius: BorderRadius.circular(20),
),
child: Row(
children: <Widget>[
CircleAvatar(
radius: 30,
backgroundColor: colors.primaryContainer,
child: Text(
profile.displayName.characters.first,
style: theme.textTheme.titleLarge?.copyWith(
color: colors.onPrimaryContainer,
fontWeight: FontWeight.w700,
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
profile.displayName,
style: theme.textTheme.titleMedium,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
Text(
'ID ${profile.userId} · ${profile.stage}',
style: theme.textTheme.bodySmall?.copyWith(
color: colors.onSurfaceVariant,
),
),
],
),
),
Icon(
Icons.chevron_right_rounded,
color: colors.onSurfaceVariant,
),
],
),
);
}
}
class _StatsCard extends StatelessWidget {
const _StatsCard({required this.profile});
final AccountProfile profile;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(18),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerLow,
borderRadius: BorderRadius.circular(20),
),
child: Row(
children: <Widget>[
Expanded(
child: StatBlock(
label: '累计学习',
value: '${profile.totalHours}',
unit: '小时',
),
),
Expanded(
child: StatBlock(
label: '坚持',
value: '${profile.streakDays}',
unit: '天',
),
),
],
),
);
}
}
/// 竖直排列的长按钮列表,样式参考原生 Android 设置页。
class _ActionList extends StatelessWidget {
const _ActionList();
static const List<(IconData, String)> _items = <(IconData, String)>[
(Icons.settings_outlined, '设置'),
(Icons.menu_book_outlined, '文档与帮助'),
(Icons.feedback_outlined, '反馈问题'),
(Icons.info_outline_rounded, '关于 KiriMemo'),
];
@override
Widget build(BuildContext context) {
return GroupedListSection(
tiles: <Widget>[
for (final (IconData icon, String label) in _items)
GroupedListTile(
icon: icon,
title: label,
onTap: () => _open(context, label),
),
],
);
}
void _open(BuildContext context, String label) {
final Widget page = switch (label) {
'设置' => const SettingsPage(),
'文档与帮助' => const DocsPage(),
'反馈问题' => const FeedbackPage(),
_ => const AboutPage(),
};
Navigator.of(context).push(
MaterialPageRoute<void>(builder: (BuildContext _) => page),
);
}
}