
资产管理是社团财务管理的重要组成部分,用于记录和管理社团的各种设备和物资。这篇文章带大家实现资产管理模块。
页面结构搭建
资产管理页面用StatelessWidget来实现:
dart
class AssetPage extends StatelessWidget {
const AssetPage({super.key});
页面不需要维护内部状态,所有数据都从Provider获取。
const构造函数可以让Flutter在重建时复用Widget实例。
导入依赖包
在文件开头导入需要的包:
dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
material.dart提供Material Design风格的组件。
provider用于状态管理,intl用于日期格式化。
还需要导入项目内的文件:
dart
import '../../providers/app_provider.dart';
app_provider包含资产数据。
使用相对路径引入,.../.../表示向上两级目录。
构建页面骨架
使用Scaffold搭建基本结构:
dart
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('资产管理')
),
Scaffold是Material Design的基础布局组件。
标题直接写"资产管理",简洁明了。
数据监听
使用Consumer监听AppProvider的数据变化:
dart
body: Consumer<AppProvider>(
builder: (context, provider, _) {
final assets = provider.assets
.where((a) => a.clubId == 'club001')
.toList();
final totalValue = assets.fold(
0.0,
(sum, a) => sum + a.value
);
Consumer会在数据变化时自动重建子组件。
fold方法计算资产总值,遍历列表累加每个资产的价值。
页面布局
使用Column纵向排列统计卡片和列表:
dart
return Column(
children: [
Column的children包含统计区域和资产列表两部分。
统计区域固定高度,列表区域占据剩余空间。
统计卡片设计
页面顶部显示资产统计信息:
dart
Container(
padding: const EdgeInsets.all(20),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF4A90E2), Color(0xFF357ABD)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
使用渐变背景让统计区域更加醒目。
LinearGradient从左上到右下渐变。
统计数据布局:
dart
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
const Text(
'资产总数',
style: TextStyle(color: Colors.white70)
),
const SizedBox(height: 4),
Text(
'${assets.length}项',
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold
)
),
],
),
左侧显示资产总数,标签用半透明白色。
数值用白色粗体大字,24像素字号。
分隔线和总值:
dart
Container(
width: 1,
height: 40,
color: Colors.white30
),
Column(
children: [
const Text(
'资产总值',
style: TextStyle(color: Colors.white70)
),
const SizedBox(height: 4),
Text(
'¥${totalValue.toStringAsFixed(0)}',
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold
)
),
],
),
],
),
),
分隔线用半透明白色,高度40像素。
资产总值用toStringAsFixed(0)格式化为整数。
资产列表区域
使用Expanded让列表占据剩余空间:
dart
Expanded(
child: assets.isEmpty
? const Center(
child: Text(
'暂无资产',
style: TextStyle(color: Colors.grey)
)
)
空状态时显示友好的提示文字。
Expanded会让子组件填充Column中的剩余空间。
使用ListView.builder构建列表:
dart
: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: assets.length,
itemBuilder: (context, index) {
final asset = assets[index];
ListView.builder是懒加载列表,性能更好。
padding设置16像素内边距。
资产卡片设计
每个资产用Card和ListTile组合展示:
dart
return Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
leading: CircleAvatar(
backgroundColor: const Color(0xFF4A90E2)
.withOpacity(0.1),
child: Icon(
_getCategoryIcon(asset.category),
color: const Color(0xFF4A90E2)
),
),
leading位置放置分类图标。
不同分类使用不同的图标。
资产基本信息
显示资产名称和分类数量:
dart
title: Text(asset.name),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${asset.category} · 数量: ${asset.quantity}'
),
Text(
'位置: ${asset.location}',
style: const TextStyle(fontSize: 12)
),
],
),
subtitle用Column显示两行信息。
第一行是分类和数量,第二行是存放位置。
价值和状态显示
trailing位置显示资产价值和状态:
dart
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'¥${asset.value.toStringAsFixed(0)}',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Color(0xFF4A90E2)
)
),
价值用蓝色粗体显示。
toStringAsFixed(0)格式化为整数。
状态标签:
dart
Container(
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 2
),
decoration: BoxDecoration(
color: asset.status == '正常'
? Colors.green.withOpacity(0.1)
: Colors.orange.withOpacity(0.1),
borderRadius: BorderRadius.circular(4),
),
child: Text(
asset.status,
style: TextStyle(
color: asset.status == '正常'
? Colors.green
: Colors.orange,
fontSize: 10
)
),
),
],
),
onTap: () => _showAssetDetail(context, asset),
),
);
},
),
),
],
);
},
),
);
}
正常状态用绿色,其他状态用橙色。
点击卡片调用_showAssetDetail显示详情。
分类图标映射
定义获取分类图标的方法:
dart
IconData _getCategoryIcon(String category) {
switch (category) {
case '电子设备':
return Icons.computer;
case '摄影器材':
return Icons.camera_alt;
case '体育器材':
return Icons.sports_basketball;
case '图书':
return Icons.book;
default:
return Icons.inventory;
}
}
不同分类使用不同的图标,让用户快速识别资产类型。
default分支使用通用的库存图标。
详情弹窗实现
使用BottomSheet显示资产详情:
dart
void _showAssetDetail(BuildContext context, asset) {
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16)
)
),
builder: (ctx) => Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
asset.name,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold
)
),
const SizedBox(height: 16),
BottomSheet从底部弹出,顶部有圆角。
mainAxisSize设为min让弹窗高度自适应内容。
详情信息列表:
dart
_buildDetailRow('分类', asset.category),
_buildDetailRow('数量', '${asset.quantity}'),
_buildDetailRow('存放位置', asset.location),
_buildDetailRow('状态', asset.status),
_buildDetailRow(
'价值',
'¥${asset.value.toStringAsFixed(2)}'
),
_buildDetailRow(
'购入日期',
DateFormat('yyyy-MM-dd').format(asset.purchaseDate)
),
const SizedBox(height: 20),
],
),
),
);
}
使用_buildDetailRow方法统一构建每一行信息。
价值显示两位小数,更加精确。
详情行组件
定义构建详情行的方法:
dart
Widget _buildDetailRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
label,
style: const TextStyle(color: Colors.grey)
),
Text(
value,
style: const TextStyle(fontWeight: FontWeight.w500)
),
],
),
);
}
}
标签用灰色,值用中等粗细的黑色。
spaceBetween让标签和值分别靠左和靠右对齐。
渐变背景的设计考虑
统计区域使用渐变背景而不是纯色背景。
可以增加视觉层次感,让这个区域更加突出。
蓝色系的渐变和整体风格保持一致。
同时吸引用户注意重要的统计信息。
资产状态的重要性
资产状态是资产管理中的重要信息。
正常状态表示资产可以正常使用。
其他状态如维修中、报废等需要特别关注。
使用不同颜色的标签让用户快速识别需要处理的资产。
小结
资产管理页面通过统计卡片和列表的形式展示社团资产信息。顶部显示资产总数和总值,列表显示每个资产的详细信息。不同分类使用不同图标,不同状态使用不同颜色标签。点击资产可以查看完整的详情信息。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net