feat(apps): establish shared mobile design system

This commit is contained in:
2026-08-10 23:31:44 +08:00
parent 7242048abf
commit a2383fc8a1
34 changed files with 2007 additions and 751 deletions

View File

@@ -12,6 +12,7 @@ class RecordListPage extends StatefulWidget {
this.description,
this.floatingActionButton,
this.onRecordTap,
this.embedded = false,
super.key,
});
@@ -21,6 +22,7 @@ class RecordListPage extends StatefulWidget {
final RecordListViewModel viewModel;
final Widget? floatingActionButton;
final ValueChanged<ClientRecord>? onRecordTap;
final bool embedded;
@override
State<RecordListPage> createState() => _RecordListPageState();
@@ -40,10 +42,8 @@ class _RecordListPageState extends State<RecordListPage> {
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: Text(widget.title)),
floatingActionButton: widget.floatingActionButton,
body: ListenableBuilder(
Widget build(BuildContext context) {
final content = ListenableBuilder(
listenable: widget.viewModel,
builder: (context, _) {
final state = widget.viewModel;
@@ -62,24 +62,52 @@ class _RecordListPageState extends State<RecordListPage> {
child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(),
slivers: [
SliverToBoxAdapter(
child: PageIntro(
eyebrow: widget.eyebrow,
title: widget.title,
description: widget.description,
if (!widget.embedded)
SliverToBoxAdapter(
child: PageIntro(
eyebrow: widget.eyebrow,
title: widget.title,
description: widget.description,
),
)
else
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 12),
child: Text(
widget.description ?? widget.title,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
),
),
if (state.records.isEmpty)
const SliverFillRemaining(
hasScrollBody: false,
child: EmptyState(title: '暂无记录', description: '服务端还没有可展示的数据'),
)
else
SliverList.builder(
itemCount: state.records.length,
itemBuilder: (context, index) => RecordCard(
record: state.records[index],
onTap: widget.onRecordTap == null ? null : () => widget.onRecordTap!(state.records[index]),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 20),
sliver: SliverToBoxAdapter(
child: SurfaceSection(
padding: EdgeInsets.zero,
child: Column(
children: [
for (var index = 0; index < state.records.length; index++) ...[
RecordCard(
record: state.records[index],
onTap: widget.onRecordTap == null
? null
: () => widget.onRecordTap!(state.records[index]),
),
if (index < state.records.length - 1)
const Divider(indent: 16, endIndent: 16),
],
],
),
),
),
),
const SliverPadding(padding: EdgeInsets.only(bottom: 24)),
@@ -87,6 +115,12 @@ class _RecordListPageState extends State<RecordListPage> {
),
);
},
),
);
);
if (widget.embedded) return content;
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
floatingActionButton: widget.floatingActionButton,
body: content,
);
}
}