flutter_for_openharmony小区门禁管理app实战+家庭成员管理实现
本文介绍了小区门禁系统中家庭成员管理页面的设计与实现。该页面采用列表展示+权限管理的模式,通过状态管理维护成员信息,包含统计卡片、成员列表和空状态提示三大核心组件。统计卡片采用紫色渐变设计,实时显示成员总数、活跃数和待审核数;成员列表支持下拉刷新和加载状态;空状态提供直观引导。页面实现了添加、编辑、删除成员等基础功能,同时考虑权限管理和操作便捷性,为小区门禁系统提供了安全可控的家庭成员管理解决方案
·

家庭成员管理是小区门禁系统中的重要功能,它为主用户提供了管理家庭成员信息和权限的便捷方式,同时确保了家庭访问的安全性。
在实际项目中,家庭成员管理需要解决几个关键问题:
- 如何清晰展示家庭成员列表和状态
- 如何支持成员的添加、编辑和删除操作
- 如何管理不同成员的访问权限
- 如何处理成员关系的验证和确认
这篇讲家庭成员管理页面的实现,重点是如何让家庭成员管理变得简单直观且安全可控。
对应源码
lib/pages/profile/family_members_page.dart
家庭成员管理页面的设计思路是:列表展示 + 权限管理 + 操作便捷。
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'add_family_member_page.dart';
class FamilyMembersPage extends StatefulWidget {
const FamilyMembersPage({Key? key}) : super(key: key);
State<FamilyMembersPage> createState() => _FamilyMembersPageState();
}
class _FamilyMembersPageState extends State<FamilyMembersPage> {
List<Map<String, dynamic>> _familyMembers = [];
bool _isLoading = false;
void initState() {
super.initState();
_loadFamilyMembers();
}
基础结构说明:
- 家庭成员管理页面需要维护成员列表状态,所以用
StatefulWidget。 - 导入
add_family_member_page.dart支持添加新成员。 _familyMembers存储所有家庭成员信息。_isLoading控制加载状态,提供良好的用户体验。
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('家庭成员'),
centerTitle: true,
actions: [
IconButton(
icon: const Icon(Icons.add),
onPressed: () => _addFamilyMember(),
),
],
),
body: RefreshIndicator(
onRefresh: _refreshMembers,
child: Column(
children: [
// 统计信息
Container(
width: double.infinity,
padding: EdgeInsets.all(16.w),
margin: EdgeInsets.all(16.w),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF9C27B0), Color(0xFF7B1FA2)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12.r),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem('成员总数', '${_familyMembers.length}'),
_buildStatItem('活跃成员', '${_getActiveMembersCount()}'),
_buildStatItem('待审核', '${_getPendingMembersCount()}'),
],
),
),
统计信息设计:
- 顶部紫色渐变统计卡片,视觉突出。
- 显示成员总数、活跃成员数、待审核数。
- 使用
_buildStatItem统一统计项样式。 - 统计信息实时更新,反映当前成员状态。
// 成员列表
Expanded(
child: _isLoading
? const Center(child: CircularProgressIndicator())
: _familyMembers.isEmpty
? _buildEmptyState()
: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16.w),
itemCount: _familyMembers.length,
itemBuilder: (context, index) {
return _buildMemberItem(_familyMembers[index], index);
},
),
),
],
),
),
);
}
页面布局设计:
- 使用
RefreshIndicator支持下拉刷新。 - 统计信息固定在顶部,成员列表占据主要空间。
- 空状态提示用户添加第一个家庭成员。
- 加载状态显示进度器,用户体验友好。
Widget _buildStatItem(String label, String value) {
return Column(
children: [
Text(
value,
style: TextStyle(
color: Colors.white,
fontSize: 20.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 4.h),
Text(
label,
style: TextStyle(
color: Colors.white70,
fontSize: 12.sp,
),
),
],
);
}
统计项组件:
- 统一的统计项样式,数值大而醒目。
- 标签使用较小字体和半透明白色。
- 垂直布局,数值在上,标签在下。
- 三个统计项均匀分布,视觉平衡。
Widget _buildEmptyState() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.family_restroom,
size: 80.sp,
color: Colors.grey[300],
),
SizedBox(height: 16.h),
Text(
'暂无家庭成员',
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey[600],
fontWeight: FontWeight.w500,
),
),
SizedBox(height: 8.h),
Text(
'点击右上角添加第一个家庭成员',
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey[500],
),
),
SizedBox(height: 24.h),
ElevatedButton.icon(
onPressed: _addFamilyMember,
icon: const Icon(Icons.add),
label: const Text('添加成员'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.purple,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 12.h),
),
),
],
),
);
}
空状态设计:
- 大图标和文字说明当前状态。
- 提供明确的操作指引。
- 添加按钮使用紫色主题色,与统计卡片呼应。
- 布局居中,视觉上更平衡。
Widget _buildMemberItem(Map<String, dynamic> member, int index) {
final isActive = member['status'] == 'active';
final isPending = member['status'] == 'pending';
return Container(
margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: isPending ? Colors.orange[300]! : Colors.grey[200]!,
width: isPending ? 2.w : 1.w,
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
blurRadius: 4.r,
offset: Offset(0, 2.h),
),
],
),
child: Column(
children: [
Row(
children: [
// 头像
Container(
width: 50.w,
height: 50.w,
decoration: BoxDecoration(
color: isActive ? Colors.purple[100] : Colors.grey[200],
shape: BoxShape.circle,
),
child: member['avatar'] != null && member['avatar'].isNotEmpty
? ClipOval(
child: Image.network(
member['avatar'],
width: 50.w,
height: 50.w,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return _buildDefaultAvatar();
},
),
)
: _buildDefaultAvatar(),
),
],
),
成员条目设计:
- 待审核成员用橙色边框突出显示。
- 头像使用圆形设计,支持网络图片加载。
- 显示成员姓名、关系、电话和权限信息。
- 状态标签用不同颜色区分:活跃、待审核、停用。
SizedBox(height: 12.h),
// 权限详情
Container(
width: double.infinity,
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: Colors.grey[50],
borderRadius: BorderRadius.circular(8.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'访问权限',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Colors.grey[700],
),
),
SizedBox(height: 8.h),
Wrap(
spacing: 8.w,
runSpacing: 4.h,
children: _buildPermissionChips(member['permissions']),
),
],
),
),
],
),
);
}
权限详情展示:
- 灰色背景区域显示权限详情。
- 使用
Wrap布局展示权限标签。 - 权限标签使用不同颜色区分类型。
- 信息层次清晰,便于快速了解权限。
Widget _buildDefaultAvatar() {
return Icon(
Icons.person,
size: 25.sp,
color: Colors.grey[400],
);
}
List<Widget> _buildPermissionChips(List<String> permissions) {
return permissions.map((permission) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
decoration: BoxDecoration(
color: _getPermissionColor(permission),
borderRadius: BorderRadius.circular(12.r),
),
child: Text(
_getPermissionLabel(permission),
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
),
),
);
}).toList();
}
权限标签组件:
_buildDefaultAvatar提供默认头像。_buildPermissionChips生成权限标签列表。- 每个权限标签使用不同颜色区分。
- 标签尺寸小巧,信息密度适中。
Future<void> _loadFamilyMembers() async {
setState(() {
_isLoading = true;
});
// 模拟加载家庭成员数据
await Future.delayed(const Duration(seconds: 1));
final mockMembers = [
{
'id': '1',
'name': '李四',
'relation': '配偶',
'phone': '13900139000',
'avatar': '',
'status': 'active',
'permissions': ['main_gate', 'parking', 'gym'],
'joinDate': '2023-06-15',
},
{
'id': '2',
'name': '张小明',
'relation': '子女',
'phone': '13700137000',
'avatar': '',
'status': 'active',
'permissions': ['main_gate', 'gym'],
'joinDate': '2023-08-20',
},
{
'id': '3',
'name': '王阿姨',
'relation': '保姆',
'phone': '13600136000',
'avatar': '',
'status': 'pending',
'permissions': ['main_gate'],
'joinDate': '2024-01-10',
},
];
setState(() {
_familyMembers = mockMembers;
_isLoading = false;
});
}
数据加载逻辑:
- 模拟异步加载家庭成员数据。
- 包含完整的成员信息:姓名、关系、电话、权限等。
- 不同状态的成员:活跃、待审核。
- 加载完成后更新UI状态。
Future<void> _refreshMembers() async {
await _loadFamilyMembers();
}
int _getActiveMembersCount() {
return _familyMembers.where((member) => member['status'] == 'active').length;
}
int _getPendingMembersCount() {
return _familyMembers.where((member) => member['status'] == 'pending').length;
}
Color _getStatusColor(String status) {
switch (status) {
case 'active':
return Colors.green;
case 'pending':
return Colors.orange;
case 'inactive':
return Colors.grey;
default:
return Colors.grey;
}
}
String _getStatusText(String status) {
switch (status) {
case 'active':
return '正常';
case 'pending':
return '待审核';
case 'inactive':
return '停用';
default:
return '未知';
}
}
状态处理方法:
_getActiveMembersCount和_getPendingMembersCount计算统计数量。_getStatusColor和_getStatusText获取状态的颜色和文本。- 使用 switch 语句确保状态处理的完整性。
String _getPermissionText(List<String> permissions) {
return permissions.map((p) => _getPermissionLabel(p)).join('、');
}
String _getPermissionLabel(String permission) {
switch (permission) {
case 'main_gate':
return '主门';
case 'parking':
return '停车场';
case 'gym':
return '健身房';
case 'pool':
return '游泳池';
default:
return '未知';
}
}
Color _getPermissionColor(String permission) {
switch (permission) {
case 'main_gate':
return Colors.blue;
case 'parking':
return Colors.green;
case 'gym':
return Colors.purple;
case 'pool':
return Colors.cyan;
default:
return Colors.grey;
}
}
权限处理方法:
_getPermissionText将权限列表转换为可读文本。_getPermissionLabel获取权限的中文标签。_getPermissionColor为不同权限分配不同颜色。- 支持多种权限类型:主门、停车场、健身房、游泳池。
void _addFamilyMember() {
Get.to(() => const AddFamilyMemberPage())?.then((result) {
if (result != null) {
_loadFamilyMembers();
}
});
}
void _handleMemberAction(String action, Map<String, dynamic> member) async {
switch (action) {
case 'edit':
_editMember(member);
break;
case 'permissions':
_managePermissions(member);
break;
case 'approve':
await _approveMember(member);
break;
case 'reject':
await _rejectMember(member);
break;
case 'delete':
await _deleteMember(member);
break;
}
}
操作处理逻辑:
_addFamilyMember跳转到添加成员页面。_handleMemberAction根据操作类型调用相应处理方法。- 支持编辑、权限管理、审核、拒绝、删除等操作。
- 添加成员成功后刷新列表。
void _editMember(Map<String, dynamic> member) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('编辑功能开发中...')),
);
}
void _managePermissions(Map<String, dynamic> member) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('权限管理功能开发中...')),
);
}
Future<void> _approveMember(Map<String, dynamic> member) async {
final index = _familyMembers.indexWhere((m) => m['id'] == member['id']);
if (index != -1) {
setState(() {
_familyMembers[index]['status'] = 'active';
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('成员审核通过'),
backgroundColor: Colors.green,
),
);
}
}
Future<void> _rejectMember(Map<String, dynamic> member) async {
final index = _familyMembers.indexWhere((m) => m['id'] == member['id']);
if (index != -1) {
setState(() {
_familyMembers.removeAt(index);
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('已拒绝成员申请'),
backgroundColor: Colors.orange,
),
);
}
}
具体操作实现:
_approveMember审核通过成员,更新状态为活跃。_rejectMember拒绝成员申请,从列表中移除。- 编辑和权限管理功能预留接口。
- 所有操作都有相应的用户反馈。
Future<void> _deleteMember(Map<String, dynamic> member) async {
final confirmed = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('确认删除'),
content: Text('确定要删除成员"${member['name']}"吗?\n删除后无法恢复。'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('取消'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('删除'),
),
],
),
);
if (confirmed == true) {
final index = _familyMembers.indexWhere((m) => m['id'] == member['id']);
if (index != -1) {
setState(() {
_familyMembers.removeAt(index);
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('成员已删除'),
backgroundColor: Colors.red,
),
);
}
}
}
}
删除操作实现:
- 删除操作需要用户二次确认,防止误删。
- 确认后从列表中移除对应成员。
- 删除成功后显示红色提示信息。
- 操作完成后自动刷新统计信息。
用户体验设计
家庭成员管理页面的用户体验重点:
- 状态可视化:用颜色和标签区分成员状态
- 权限清晰:权限信息展示直观易懂
- 操作便捷:常用操作集中在右键菜单
- 反馈及时:每个操作都有明确的反馈
这些设计让家庭成员管理变得简单直观。
权限管理策略
权限管理的安全考虑:
- 分级权限:不同成员有不同的访问权限
- 权限可视化:权限标签清晰展示
- 权限审核:新成员需要审核才能获得权限
- 权限追溯:权限变更记录日志
这些措施确保权限管理的安全性。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐

所有评论(0)