基本完成

This commit is contained in:
zhutao
2025-08-28 16:27:56 +08:00
commit 5d7d233d2e
132 changed files with 6390 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
class AppBackend extends StatelessWidget {
final Widget child;
const AppBackend({super.key, required this.child});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xffdff8fb),
Color(0xffffffff),
Color(0xffdff8fb),
],
),
),
child: SafeArea(child: child),
);
}
}

View File

@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
class AppHeader extends StatefulWidget {
const AppHeader({super.key});
@override
State<AppHeader> createState() => _AppHeaderState();
}
class _AppHeaderState extends State<AppHeader> {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
spacing: 10,
children: [
Image.asset(
"assets/image/logo.png",
width: 44,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"FoodSafe",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
"AI Health Guardian",
style: Theme.of(context).textTheme.labelSmall,
),
],
),
],
),
],
),
);
}
}

View File

@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
class AsyncImage extends StatelessWidget {
final String url;
final double? width;
const AsyncImage({
super.key,
required this.url,
this.width,
});
@override
Widget build(BuildContext context) {
return SizedBox(
width: width,
child: Image.network(
url,
fit: BoxFit.cover,
// 加载中的样式
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) {
return child; // 加载完成,直接返回图片
}
return Container(
color: Colors.grey[200],
alignment: Alignment.center,
child: CircularProgressIndicator(strokeWidth: 2),
);
},
// 加载失败的样式
errorBuilder: (context, error, stackTrace) {
return Container(
color: Colors.grey[200],
child: const Icon(
Icons.broken_image,
size: 30,
color: Colors.grey,
),
);
},
),
);
}
}

View File

@@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
///自定义按钮
///包括loading功能
class CustomButton extends StatelessWidget {
final Widget child;
final VoidCallback? onPressed;
final bool loading;
final bool round;
final bool disabled;
const CustomButton({
super.key,
required this.child,
this.onPressed,
this.loading = false,
this.round = true,
this.disabled = false,
});
@override
Widget build(BuildContext context) {
///自定义颜色
// switch (size) {
// case ButtonSize.small:
// height = 28;
// loadingSize = 16;
// fontSize = 12;
// padding = const EdgeInsets.symmetric(horizontal: 12);
// break;
// case ButtonSize.large:
// height = 48;
// loadingSize = 24;
// fontSize = 18;
// padding = const EdgeInsets.symmetric(horizontal: 20);
// break;
// case ButtonSize.medium:
// height = 45;
// loadingSize = 15;
// fontSize = 16;
// padding = const EdgeInsets.symmetric(horizontal: 16);
// break;
// }
void handClick() {
if (!loading && !disabled) {
onPressed?.call();
}
}
return Opacity(
opacity: disabled ? 0.5 : 1,
child: ElevatedButton(
onPressed: handClick,
style: ElevatedButton.styleFrom(
shape: round
? const StadiumBorder()
: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Visibility(
visible: loading,
child: Container(
margin: EdgeInsets.only(right: 8),
child: SizedBox.square(
dimension: 15,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
),
),
),
child,
],
),
),
);
}
}

View File

@@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
import '../../../config/app_context.dart';
class Empty extends StatelessWidget {
final String? title;
final Widget? child;
const Empty({super.key, this.title, this.child});
@override
Widget build(BuildContext context) {
return SizedBox.expand(
child: Align(
alignment: const FractionalOffset(0.5, 0.2),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FractionallySizedBox(
widthFactor: 0.5,
child: Image.asset("assets/image/empty_data.png"),
),
if (title != null)
Text(
title!,
style: AppContext.textTheme.labelMedium,
),
if (child != null) child!,
],
),
),
);
}
}