Flutter双角色App相似页面编码策略咨询
Flutter 多角色模块架构方案建议
针对团队领导(Teamleader)和员工(Staff)模块的视图、控制器、服务分层设计,推荐采用组件拆分复用+分层继承/组合的方案,平衡代码复用性和可维护性,以下是各层具体实现思路:
视图层:公共组件抽离 + 条件渲染/按需拆分页面
- 公共组件抽离:把两个角色页面中相同/相似的Widget(如顶部导航栏、员工列表卡片、状态加载组件)单独封装成独立组件,放在
common_widgets目录下,比如CommonAppBar、EmployeeCard、LoadStateWidget,两个页面直接引用即可,避免重复代码。 - 差异化处理:
- 如果只是少量Widget差异(比如领导页面多一个添加员工按钮),用单页面
HomeView结合条件渲染即可,通过传入角色枚举判断是否显示差异化组件,代码示例:enum UserRole { staff, teamLeader } class HomeView extends StatelessWidget { final UserRole role; const HomeView({super.key, required this.role}); @override Widget build(BuildContext context) { return Scaffold( appBar: const CommonAppBar(title: '首页'), body: Column( children: [ const CommonStatsPanel(), Expanded(child: EmployeeList(role: role)), // 仅团队领导显示添加按钮 if (role == UserRole.teamLeader) FloatingActionButton( onPressed: () => Navigator.push(context, AddEmployeeRoute()), child: const Icon(Icons.add), ), ], ), ); } } - 如果两个角色的页面布局逻辑差异极大(比如领导页面有复杂的权限管理面板,员工页面只有个人任务列表),则拆分
StaffHomeView和TeamLeaderHomeView,但内部依然复用公共组件,避免从零搭建。
- 如果只是少量Widget差异(比如领导页面多一个添加员工按钮),用单页面
控制器/业务逻辑层:基类封装公共逻辑 + 子类扩展差异化功能
采用基类继承或组合模式,避免重复编写相同的业务逻辑:
- 基类封装公共逻辑:创建
BaseHomeController,处理两个角色都需要的逻辑,比如员工列表加载、状态管理(加载/错误/成功):enum LoadState { idle, loading, success, error } class BaseHomeController extends GetxController { final EmployeeApiService _apiService = EmployeeApiService(); final RxList<Employee> employees = RxList.empty(); final Rx<LoadState> loadState = Rx(LoadState.idle); @override void onInit() { super.onInit(); _fetchEmployees(); } Future<void> _fetchEmployees() async { loadState.value = LoadState.loading; try { employees.value = await _apiService.getEmployeeList(); loadState.value = LoadState.success; } catch (e) { loadState.value = LoadState.error; } } } - 子类扩展差异化逻辑:
StaffHomeController继承基类,添加员工专属逻辑,比如获取个人任务:class StaffHomeController extends BaseHomeController { final RxList<Task> myTasks = RxList.empty(); Future<void> fetchMyTasks() async { // 调用员工专属接口获取个人任务 } }TeamLeaderHomeController继承基类,添加领导专属逻辑,比如添加员工、修改员工权限:class TeamLeaderHomeController extends BaseHomeController { final TeamLeaderApiService _leaderApiService = TeamLeaderApiService(); Future<void> addEmployee(Employee employee) async { await _leaderApiService.addEmployee(employee); _fetchEmployees(); // 添加后刷新列表 } }
服务层:公共服务复用 + 差异化服务拆分
- 公共服务:创建
EmployeeApiService封装所有角色都能访问的接口,比如获取员工列表、员工详情:class EmployeeApiService { Future<List<Employee>> getEmployeeList() async { final response = await http.get(Uri.parse('/api/employees')); // 解析响应并返回员工列表 } } - 差异化服务:
TeamLeaderApiService继承或组合EmployeeApiService,添加领导专属接口,比如添加员工、调整员工权限:class TeamLeaderApiService extends EmployeeApiService { Future<void> addEmployee(Employee employee) async { await http.post( Uri.parse('/api/employees/add'), body: jsonEncode(employee.toJson()), headers: {'Content-Type': 'application/json'}, ); } }StaffApiService仅保留员工能访问的接口,比如获取个人任务、提交工作报告,避免越权调用。
方案对比
- 完全独立视图:优点是角色逻辑完全隔离,不会互相干扰;缺点是重复代码多,后期修改公共部分需要同步更新两个页面,维护成本高。
- 单页面硬适配:优点是代码复用率高;缺点是如果差异大,页面会充斥大量条件判断,逻辑混乱,可读性差,难以维护。
- 组件拆分+分层继承/组合:兼顾复用性和可维护性,公共部分统一管理,差异化逻辑各自实现,后期迭代修改更高效,是最推荐的方案。
内容的提问来源于stack exchange,提问作者Furkan Türkmen
相关产品推荐
相关产品推荐

