rui_admin 0.0.5
rui_admin: ^0.0.5 copied to clipboard
A flutter UI, for crossing platform APP, supporting mobile and windows, macos, web. 主要特点:admin布局,左侧菜单栏可展开收起,在宽度太小时自动切换为drawer。
RUI Admin #
English Version | 中文版
[LOGO]
RUI Admin 是一个基于 Flutter 的现代化后台管理系统模板,提供了一套完整的布局和组件系统。
功能预览 #
响应式布局 #
[响应式布局] [响应式布局]
移动端自适应,左侧菜单变更为drawer。 #
[用户界面] [用户界面]
主题切换 #
[主题切换]
- 支持浅色/深色主题
- 主题色
主要功能 #
1. 布局系统 #
- 跨平台支持:
- 移动端:支持 iOS 和 Android 平台,提供原生体验
- 桌面端:支持 Windows 和 macOS 平台,提供桌面级应用体验
- Web 端:支持现代浏览器,提供响应式网页体验
- 响应式布局:
- 自适应不同屏幕尺寸,自动调整布局结构
- 在窄屏设备上自动切换为抽屉式导航
- 支持自定义断点配置,灵活控制布局切换
- 左侧菜单栏:
- 可展开收起的多级菜单系统,支持无限层级
- 支持自定义 Logo 和底部组件,满足品牌定制需求
- 菜单项支持图标、标题、徽标和点击事件
- 支持菜单项权限控制,实现动态菜单
- 支持菜单折叠功能,优化空间利用
2. 主题系统 #
- 主题切换:
- 支持浅色/深色主题一键切换
- 支持跟随系统主题自动切换
- 支持自定义主题色配置
- 主题定制:
- 支持自定义主题色、文字颜色、背景色等
- 支持自定义组件样式,如按钮、输入框等
- 支持自定义字体、间距、圆角等样式
- 主题持久化:
- 自动保存主题设置到本地存储
- 支持主题配置的导入导出
- 支持多主题配置管理
3. 导航系统 #
- 路由管理:
- 支持命名路由,简化页面跳转
- 支持路由参数传递和获取
- 支持路由守卫,实现权限控制
- 页面状态:
- 支持页面状态保持,避免重复加载
- 支持页面数据缓存,提升用户体验
- 支持页面生命周期管理
- 页面动画:
- 支持自定义页面切换动画
- 支持多种过渡效果选择
- 支持动画时长和曲线配置
- 返回处理:
- 支持自定义返回行为
- 支持返回确认提示
- 支持返回栈管理
4. 用户界面组件 #
- 登录状态面板:
- 显示用户头像、名称、角色等信息
- 支持在线状态显示
- 支持快捷操作菜单
- 用户信息展示:
- 支持用户基本信息展示
- 支持用户设置管理
- 支持消息通知中心
- 菜单按钮组件:
- 支持图标和文字组合
- 支持徽标显示
- 支持禁用状态
- 自定义输入框:
- 支持多种输入类型
- 支持验证和错误提示
- 支持自定义样式
- 加载动画:
- 支持多种加载动画样式
- 支持自定义加载文案
- 支持加载超时处理
5. 全局功能 #
- 应用初始化:
- 支持异步初始化流程
- 支持初始化进度显示
- 支持初始化失败处理
- 消息提示:
- 支持全局 SnackBar 消息
- 支持多种消息类型(成功、警告、错误)
- 支持消息队列管理
- 状态管理:
- 支持主题状态管理
- 支持会话状态管理
- 支持用户状态管理
- 存储管理:
- 支持本地数据持久化
- 支持数据加密存储
- 支持数据同步机制
6. 全局函数列表 #
// 显示全局消息提示
RuiApp.rootScaffoldMessengerKey.currentState?.showSnackBar(
SnackBar(
content: Text('消息内容'),
duration: Duration(seconds: 2),
),
);
// 加载主题
RuiStorageManager.load().then((ThemeModel tm) {
// 处理主题数据
});
// 加载会话
RuiStorageManager.loadSession().then((SessionModel sm) {
// 处理会话数据
});
// 应用初始化
RuiApp(
appInit: () async {
// 执行初始化操作
return true; // 返回初始化结果
},
);
示例代码 #
1. 基础应用结构 #
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserProvider()),
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return RuiApp(
title: "RUI APP",
home: MainFrame(),
appInit: () async {
// 执行初始化操作
return true;
},
);
}
}
2. 主框架结构 #
class MainFrame extends StatefulWidget {
const MainFrame({super.key});
@override
State<MainFrame> createState() => _MainFrameState();
}
class _MainFrameState extends State<MainFrame> {
@override
Widget build(BuildContext context) {
return RuiScaffold(
initialRoute: '/home',
routes: {
'/home': (context) => const MyHomePage(title: 'Flutter Demo Home Page'),
'/login': (context) => const LoginPage(),
'/about': (context) => const AboutPage(),
'/contact': (context) => const ContactPage(),
},
body: const MyHomePage(title: "Home"),
headerMainPanel: const Text("Demo of Rui"),
headerToolsPanel: _buildHeaderToolbar(),
appName: 'RUI',
headerUserPanel: _buildHeaderUserPanel(),
logo: Icons.apple,
leftMenuButtons: genLeftMenuItems(),
leftFooterWidget: _buildLeftFooterPanel(),
footerPanel: _buildFooter(),
rightMenuButtons: _buildRightMenuButtons(),
rightPanel: _buildRightPanel(),
);
}
}
3. 菜单项配置 #
List<RuiMenuItem> genLeftMenuItems() {
return [
RuiMenuItem(
id: "home",
icon: Icons.home,
title: 'Home',
subItems: [],
onPressed: () {
RuiScaffold.navigatorKey.currentState?.pushReplacementNamed('/home');
},
),
RuiMenuItem(
id: "settings",
icon: Icons.settings,
title: 'settings',
subItems: [],
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('设置功能即将推出'),
duration: Duration(seconds: 2),
),
);
},
),
// ... 其他菜单项
];
}
使用说明 #
- 克隆项目到本地
- 安装依赖:
flutter pub add rui_admin - 参考 example 目录下代码
- 运行项目:
flutter run
注意事项 #
- 确保 Flutter SDK 版本兼容
- 首次运行需要等待依赖安装完成
- 主题切换后会自动保存设置
- 页面状态保持需要正确配置路由
Getting started / 开始使用 #
flutter pub add rui_admin
Usage / 使用方法 #
For examples, please refer to the /example folder.
示例代码请参考 /example 文件夹。
main.dart:
import 'package:example/main_frame.dart';
import 'package:example/providers/user_provider.dart';
import 'package:flutter/material.dart';
import 'package:rui_admin/components/rui_app.dart';
import 'package:provider/provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserProvider()),
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Future<bool> _initializeApp() async {
// 模拟一些初始化操作
await Future.delayed(const Duration(seconds: 2));
//延迟弹出,等主界面显示后。
Future.delayed(const Duration(milliseconds: 500), () {
RuiApp.rootScaffoldMessengerKey.currentState?.showSnackBar(
const SnackBar(
content: Text('应用初始化成功'),
duration: Duration(seconds: 2),
),
);
});
return true;
}
@override
Widget build(BuildContext context) {
return RuiApp(
title: "RUI APP",
home: const MainFrame(),
//异步 app初始化操作
appInit: _initializeApp,
);
}
}
main_frame.dart:
import 'package:example/pages/home.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rui_admin/components/menu/rui_menu_item.dart';
import 'package:rui_admin/components/panels/user/rui_login_status_panel.dart';
import 'package:rui_admin/components/panels/rui_footer.dart';
import 'package:rui_admin/components/rui_scaffold.dart';
import 'package:rui_admin/pages/about_page.dart';
import 'package:rui_admin/pages/contact_page.dart';
import 'package:rui_admin/pages/login_page.dart';
class MainFrame extends StatefulWidget {
const MainFrame({super.key});
@override
State<MainFrame> createState() => _MainFrameState();
}
class _MainFrameState extends State<MainFrame> {
@override
Widget build(BuildContext context) {
return RuiScaffold(
initialRoute: '/home',
routes: {
'/home': (context) => const MyHomePage(title: 'Flutter Demo Home Page'),
'/login': (context) => const LoginPage(),
'/about': (context) => const AboutPage(),
'/contact': (context) => const ContactPage(),
},
body: const MyHomePage(title: "Home"),
headerMainPanel: const Text("Demo of Rui"),
headerToolsPanel: _buildHeaderToolbar(),
appName: 'RUI',
headerUserPanel: _buildHeaderUserPanel(),
logo: Icons.apple,
leftMenuButtons: genLeftMenuItems(),
leftFooterWidget: _buildLeftFooterPanel(),
footerPanel: _buildFooter(),
rightMenuButtons: _buildRightMenuButtons(),
rightPanel: _buildRightPanel(),
);
}
Widget _buildHeaderToolbar() {
return Row(
children: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.check),
),
],
);
}
Widget _buildHeaderUserPanel() {
return Row(
children: [
RuiLoginStatusPanel(
userName: "张三",
userPhone: "18000000000",
userImage:
"https://th.bing.com/th?id=OSK.f7f4e9af4e9ca9ea2585e5df12ff1c5f&w=80&h=80&c=7&o=6&dpr=2&pid=SANGAM",
userEmail: "test@qwe.com",
),
],
);
}
Widget _buildFooter() {
return const RuiFooter();
}
Widget _buildLeftFooterPanel() {
return const Icon(Icons.abc);
}
List<RuiMenuItem> genLeftMenuItems() {
return [
RuiMenuItem(
id: "home",
icon: Icons.home,
title: 'Home',
subItems: [],
onPressed: () {
//need to user RuiScaffold.navigatorKey to jump
RuiScaffold.navigatorKey.currentState?.pushNamed('/home');
},
),
RuiMenuItem(
id: "settings",
icon: Icons.settings,
title: 'settings',
subItems: [],
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('设置功能即将推出'),
action: SnackBarAction(
label: '知道了',
onPressed: () {
// 点击操作
},
),
duration: const Duration(seconds: 2),
),
);
},
),
RuiMenuItem(
id: "About",
icon: Icons.info,
title: 'About',
subItems: [
RuiMenuItem(
id: "AboutUs",
icon: Icons.person,
title: 'About Us',
subItems: [],
onPressed: () {
//need to user RuiScaffold.navigatorKey to jump
RuiScaffold.navigatorKey.currentState?.pushNamed('/about');
},
),
RuiMenuItem(
id: "ContactUs",
icon: Icons.email,
title: 'Contact Us',
onPressed: () {
//need to user RuiScaffold.navigatorKey to jump
RuiScaffold.navigatorKey.currentState?.pushNamed('/contact');
},
),
],
),
RuiMenuItem(
id: "Logout",
icon: Icons.logout,
title: 'Logout',
onPressed: () {
RuiScaffold.pushNamed('/login');
},
),
];
}
List<MenuItemButton> _buildRightMenuButtons() {
return [
MenuItemButton(
shortcut: const SingleActivator(LogicalKeyboardKey.keyO, control: true),
onPressed: () {
if (kDebugMode) {
print("======打开==========");
}
},
child: const Text('打开'),
),
MenuItemButton(
shortcut: const SingleActivator(LogicalKeyboardKey.keyE, meta: true),
onPressed: () {
if (kDebugMode) {
print("======print==========");
}
},
child: const Text('print'),
),
MenuItemButton(
onPressed: () {
if (kDebugMode) {
print("======exit==========");
}
},
child: const Text('Exit'),
),
];
}
Widget _buildRightPanel() {
return const Text("Right Panel");
}
}
MyHomePage.dart:
import 'package:example/providers/user_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:rui_admin/components/rui_scaffold.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text(
"${Provider.of<UserProvider>(context).count}",
style: Theme.of(context).textTheme.headlineMedium,
),
ElevatedButton(
onPressed: () {
//need to user RuiScaffold.navigatorKey to jump
RuiScaffold.navigatorKey.currentState?.pushNamed('/login');
},
child: const Text("Goto login"),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed:
Provider.of<UserProvider>(context, listen: false).increaseCount,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}