? boxShadow;
+
+ const GlassCard({
+ super.key,
+ required this.child,
+ this.padding,
+ this.margin,
+ this.borderRadius = 16,
+ this.width,
+ this.height,
+ this.borderColor,
+ this.boxShadow,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ width: width,
+ height: height,
+ margin: margin,
+ padding: padding ?? const EdgeInsets.all(14),
+ decoration: BoxDecoration(
+ color: AppColors.cardBg,
+ borderRadius: BorderRadius.circular(borderRadius),
+ border: Border.all(color: borderColor ?? Colors.white.withOpacity(0.8)),
+ boxShadow: boxShadow ?? [
+ BoxShadow(
+ color: AppColors.brand.withOpacity(0.06),
+ blurRadius: 32,
+ offset: const Offset(0, 8),
+ ),
+ ],
+ ),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(borderRadius),
+ child: BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
+ child: child,
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/frontend/lib/widgets/number_pad.dart b/frontend/lib/widgets/number_pad.dart
new file mode 100644
index 0000000..4bc2c14
--- /dev/null
+++ b/frontend/lib/widgets/number_pad.dart
@@ -0,0 +1,48 @@
+import 'package:flutter/material.dart';
+import '../theme/colors.dart';
+
+class NumberPad extends StatelessWidget {
+ final void Function(String key) onKeyTap;
+ final String? Function()? onDelete;
+
+ const NumberPad({super.key, required this.onKeyTap, this.onDelete});
+
+ @override
+ Widget build(BuildContext context) {
+ final keys = ['1','2','3','4','5','6','7','8','9','.', '0', 'delete'];
+ return Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 20),
+ child: GridView.count(
+ crossAxisCount: 4,
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ mainAxisSpacing: 8,
+ crossAxisSpacing: 8,
+ childAspectRatio: 1.5,
+ children: keys.map((key) {
+ final isDelete = key == 'delete';
+ return GestureDetector(
+ onTap: () => onKeyTap(key),
+ child: Container(
+ height: 48,
+ decoration: BoxDecoration(
+ color: isDelete ? AppColors.brand.withOpacity(0.08) : Colors.white.withOpacity(0.7),
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Center(
+ child: Text(
+ isDelete ? '⌫' : key,
+ style: TextStyle(
+ fontSize: isDelete ? 20 : 22,
+ fontWeight: isDelete ? FontWeight.w400 : FontWeight.w500,
+ color: isDelete ? AppColors.brand : const Color(0xFF1C1C1E),
+ ),
+ ),
+ ),
+ ),
+ );
+ }).toList(),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/frontend/lib/widgets/stat_card.dart b/frontend/lib/widgets/stat_card.dart
new file mode 100644
index 0000000..1f3c1b0
--- /dev/null
+++ b/frontend/lib/widgets/stat_card.dart
@@ -0,0 +1,52 @@
+import 'dart:ui';
+import 'package:flutter/material.dart';
+
+class StatCard extends StatelessWidget {
+ final String label;
+ final String value;
+ final Color color;
+ final double? fontSize;
+
+ const StatCard({
+ super.key,
+ required this.label,
+ required this.value,
+ required this.color,
+ this.fontSize,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
+ decoration: BoxDecoration(
+ color: const Color(0xA6FFFFFF),
+ borderRadius: BorderRadius.circular(16),
+ border: Border.all(color: Colors.white.withOpacity(0.8)),
+ boxShadow: const [
+ BoxShadow(color: Color(0x0DFF6B35), blurRadius: 32, offset: Offset(0, 8)),
+ ],
+ ),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(16),
+ child: BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
+ child: Column(
+ children: [
+ Text(label, style: const TextStyle(fontSize: 11, color: Color(0xFF8E8E93), fontWeight: FontWeight.w500)),
+ const SizedBox(height: 4),
+ Text(
+ value,
+ style: TextStyle(
+ fontSize: fontSize ?? (value.length > 10 ? 13 : 15),
+ fontWeight: FontWeight.w700,
+ color: color,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml
new file mode 100644
index 0000000..3a77dd4
--- /dev/null
+++ b/frontend/pubspec.yaml
@@ -0,0 +1,28 @@
+name: family_accounting
+description: Family Accounting App
+publish_to: 'none'
+version: 1.0.0+1
+
+environment:
+ sdk: '>=3.2.0 <4.0.0'
+
+dependencies:
+ flutter:
+ sdk: flutter
+ flutter_riverpod: ^2.5.0
+ riverpod_annotation: ^2.3.0
+ dio: ^5.4.0
+ flutter_secure_storage: ^9.0.0
+ go_router: ^14.0.0
+ fl_chart: ^0.68.0
+ intl: ^0.19.0
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^4.0.0
+ build_runner: ^2.4.0
+ riverpod_generator: ^2.4.0
+
+flutter:
+ uses-material-design: true
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..0205389
--- /dev/null
+++ b/index.html
@@ -0,0 +1,3113 @@
+
+
+
+
+
+家庭记账 · 液态玻璃设计
+
+
+
+
+
+
+家庭记账 · 液态玻璃设计
+简约白 · 时尚橙 · iOS 26 Liquid Glass
+
+iOS 26 · Liquid Glass Concept
+
+
+
+