From a201fdb91c5e063c04b03c852c2de6c66a3d2bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=B8=9C=E4=BA=91?= Date: Wed, 29 Mar 2023 14:47:31 +0800 Subject: [PATCH] =?UTF-8?q?refactor(router):=20=E6=94=B9=E5=8F=98=E4=BA=86?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 从路由配置文件改为了路由表 --- lib/common/access_control_filter.dart | 107 ------------------ lib/common/global.dart | 38 +++---- lib/main.dart | 153 +++++++++++++------------- lib/router/router.dart | 5 - lib/router/router_table.dart | 40 +++++++ test/widget_test.dart | 2 +- 6 files changed, 133 insertions(+), 212 deletions(-) delete mode 100644 lib/common/access_control_filter.dart delete mode 100644 lib/router/router.dart create mode 100644 lib/router/router_table.dart diff --git a/lib/common/access_control_filter.dart b/lib/common/access_control_filter.dart deleted file mode 100644 index 0606289..0000000 --- a/lib/common/access_control_filter.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:flutter/material.dart'; -import 'global.dart'; -import 'package:bistro/mine/login.dart'; - -typedef ACFCallback = Future Function(Map userInfo); - -/// -/// 登录状态检查 -/// -class AccessControlFilter extends StatefulWidget { - /// 头部 - final AppBar? appBar; - - /// 标题 - final String? title; - - /// 内容组件 - final Widget child; - - /// 未登录的显示 - final Widget? didNotLoginWidget; - - const AccessControlFilter({ - required Key key, - this.appBar, - this.title, - required this.child, - this.didNotLoginWidget, - }) : super(key: key); - - @override - AccessControlFilterState createState() => AccessControlFilterState(); -} - -class AccessControlFilterState extends State { - /// 登录状态 - final bool _isLogin = false; - - @override - void initState() { - super.initState(); - - _updateUserState(); - } - - @override - void didUpdateWidget(AccessControlFilter oldWidget) { - super.didUpdateWidget(oldWidget); - _updateUserState(); - } - - /// 更新用户信息 - void _updateUserState({data}) { -// final Map userInfo = data != null ? data : UserInfo().userInfo; -// final bool isLogin = userInfo != null && userInfo.length != 0; -// setState(() { -// _isLogin = isLogin; -// }); - } - - /// 未登录的显示 - Widget? _didNotLoginWidget() { - // 如果传入的未登录情况下显示的组件,则采用传入的 - if (widget.didNotLoginWidget != null) return widget.didNotLoginWidget; - - // 缺省的未登录情况下的显示 - return Center( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).colorScheme.background, - textStyle: TextStyle( - color: Theme.of(context).colorScheme.primary - ) - ), - child: const Text('请先登录'), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) { - return Login( - successCallback: (Map data) { - _updateUserState(data: data); - printWhenDebug('登录成功'); - }, - key: widget.key ?? const Key('acf'), - ); - }, - ), - ); - }, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: widget.appBar ?? - AppBar( - centerTitle: true, - title: Text(widget.title ?? ""), - ), - body: _isLogin ? widget.child : _didNotLoginWidget(), - ); - } -} diff --git a/lib/common/global.dart b/lib/common/global.dart index 573998e..692cf0e 100644 --- a/lib/common/global.dart +++ b/lib/common/global.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; -import 'package:dio_http_cache/dio_http_cache.dart'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -19,9 +19,9 @@ const _themes = [ /// 当调试模式打开时打印 /// void printWhenDebug(Object object) { - if (kDebugMode) { - print(object); - } + if (kDebugMode) { + print(object); + } } /// @@ -36,12 +36,12 @@ class Global { static SharedPreferences? _prefs; static Dio? dio; static Map profile = {}; + /// /// 当前环境 /// static const Env env = Env.dev; - /// /// 根域名 /// @@ -57,11 +57,11 @@ class Global { static String baseUrl = baseUrlList[env]; // 网络缓存对象 - static DioCacheManager netCache = DioCacheManager( - CacheConfig( - baseUrl: baseUrl, - ), - ); + // static DioCacheManager netCache = DioCacheManager( + // CacheConfig( + // baseUrl: baseUrl, + // ), + // ); // 可选的主题列表 static List get themes => _themes; @@ -70,27 +70,19 @@ class Global { static bool get isRelease => const bool.fromEnvironment("dart.vm.product"); //初始化全局信息,会在APP启动时执行 - static Future init() async { + static Future init(context) async { dio = Dio(); - // 添加拦截器 - dio?.interceptors.add(netCache.interceptor); // 初始化用户信息 _prefs = await SharedPreferences.getInstance(); var profile = _prefs?.getString("user_info"); if (profile != null) { try { - if (kDebugMode) { - print('开始读取用户信息...'); - } + printWhenDebug('开始读取用户信息...'); profile = jsonDecode(profile); - if (kDebugMode) { - print('用户信息读取成功'); - } + printWhenDebug('用户信息读取成功'); } catch (e) { - if (kDebugMode) { - print(e); - } + printWhenDebug(e); } } } @@ -103,7 +95,7 @@ class Global { } /// 读取持久化Profile信息 - static Future getProfile() { + static Map getProfile() { return jsonDecode(_prefs?.getString("user_info") ?? '{}'); } } diff --git a/lib/main.dart b/lib/main.dart index 045db3c..51a2794 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,28 +1,47 @@ import 'package:bistro/common/global.dart'; +import 'package:bistro/router/router_table.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; - import 'package:flutter_native_splash/flutter_native_splash.dart'; +import 'package:flutter_web_plugins/url_strategy.dart'; // import 'package:flutter_localizations/flutter_localizations.dart'; import 'app.dart'; import 'life.dart'; import 'mine.dart'; import 'news.dart'; -import 'router/router.dart'; void main() { + // 保证核心已启动 WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); + FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); + + // SystemChrome.setEnabledSystemUIMode( SystemUiMode.edgeToEdge, overlays: [SystemUiOverlay.bottom, SystemUiOverlay.top], ); - FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); - runApp(const Bistro()); + + // 只允许竖屏 + SystemChrome.setPreferredOrientations( + [ + DeviceOrientation.portraitUp, // 竖屏 Portrait 模式 + DeviceOrientation.portraitDown, + // DeviceOrientation.landscapeLeft, // 横屏 Landscape 模式 + // DeviceOrientation.landscapeRight, + ], + ); + + // web 使用 path(history)路由 + usePathUrlStrategy(); + + runApp(Bistro()); } class Bistro extends StatelessWidget { - const Bistro({Key? key}) : super(key: key); + final GlobalKey navigationKey = GlobalKey(); + + Bistro({Key? key}) : super(key: key); // This widget is the root of your application. @override @@ -33,37 +52,32 @@ class Bistro extends StatelessWidget { fontFamily: "SongTiHeavy", primaryColor: const Color(0xFFD56937), primaryColorDark: const Color(0xFFD56937), - scaffoldBackgroundColor: const Color(0xFF939D99), - appBarTheme: const AppBarTheme(color: Color(0xff384444)), + // appBarTheme: const AppBarTheme(color: Color(0xff384444)), navigationBarTheme: const NavigationBarThemeData( - surfaceTintColor: Color(0xffd56937), - backgroundColor:Color(0xff2a2a22), - indicatorColor: Color(0x00000000), - labelTextStyle: MaterialStatePropertyAll(TextStyle( - color: Color(0xffd56937), - )), + indicatorColor: Color(0xFFD56937), + labelTextStyle: MaterialStatePropertyAll( + TextStyle( + // color: Color(0xffd56937), + ), + ), ), colorScheme: const ColorScheme.dark( primary: Color(0xFFD56937), secondary: Color(0xFFC8C2B4), - background: Color(0xff384444), + tertiary: Color(0xff384444), + background: Color(0xff2a2a22), ), useMaterial3: true, ), + themeMode: ThemeMode.system, home: const BistroFrame( title: '小酒馆', ), - // 国际化 - // localizationsDelegates: [ - // GlobalMaterialLocalizations.delegate, - // GlobalWidgetsLocalizations.delegate, - // ], - // supportedLocales: const [ - // Locale('zh', 'CN'), - // ], - // locale: const Locale('zh'), // 路由 - routes: router, + // routes: RouterTable.routeTables, + navigatorKey: navigationKey, + onGenerateRoute: RouterTable.onGenerateRoute, + initialRoute: RouterTable.homePath, ); } } @@ -79,31 +93,29 @@ class BistroFrame extends StatefulWidget { class BistroFrameState extends State { late Widget _body; - int _index = 3; + late int _index = 2; + final List loginRequired = [3]; static const List> _iconList = [ { "title": "满席", "icon": Icons.storefront_outlined, - "display": true, + "selectedIcon": Icons.storefront_rounded, }, { "title": "道听", "icon": Icons.forum_outlined, - "display": true, - }, - { - "display": false, + "selectedIcon": Icons.forum_rounded, }, { "title": "途说", "icon": Icons.supervisor_account_outlined, - "display": true, + "selectedIcon": Icons.supervisor_account_rounded, }, { "title": "在下", "icon": Icons.person_outline, - "display": true, + "selectedIcon": Icons.person_rounded, }, ]; @@ -113,6 +125,7 @@ class BistroFrameState extends State { super.initState(); initialization(); + Global.init(context); } void initData() { @@ -121,7 +134,6 @@ class BistroFrameState extends State { children: const [ App(), News(), - News(), Life(), Mine(), ], @@ -140,8 +152,8 @@ class BistroFrameState extends State { // print('ready in 2...'); // } // await Future.delayed(const Duration(seconds: 1)); - await Future.delayed(const Duration(seconds: 1)); - printWhenDebug('go!'); + // await Future.delayed(const Duration(seconds: 1)); + // printWhenDebug('go!'); FlutterNativeSplash.remove(); } @@ -149,25 +161,20 @@ class BistroFrameState extends State { Widget build(BuildContext context) { initData(); - List bottomNavigationBarData = []; - for (var i = 0; i < 5; i++) { - Widget itemWidget = bottomAppBarItem(index: i); + List bottomNavigationBarData = []; + for (var i = 0; i < 4; i++) { + NavigationDestination itemWidget = bottomAppBarItem(index: i); bottomNavigationBarData.add(itemWidget); } return Scaffold( - body: _body, - bottomNavigationBar: NavigationBar( - selectedIndex: _index, - destinations: bottomNavigationBarData, - // backgroundColor: Theme.of(context).colorScheme.primary, - onDestinationSelected: (index) => { - setState(() { - _index = index; - }) - }, - labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected, + appBar: AppBar( + title: Text(_iconList[_index]['title']), + systemOverlayStyle: const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, //设置为透明 + ), ), + body: _body, floatingActionButton: FloatingActionButton( enableFeedback: true, backgroundColor: Theme.of(context).colorScheme.background, @@ -177,40 +184,34 @@ class BistroFrameState extends State { color: Theme.of(context).primaryColor, ), ), - floatingActionButtonLocation: - FloatingActionButtonLocation.miniCenterDocked, + bottomNavigationBar: NavigationBar( + selectedIndex: _index, + destinations: bottomNavigationBarData, + onDestinationSelected: (int index) { + setState(() { + _index = index; + }); + + loginRequired.forEach((index) { + if (_index == index) { + Navigator.of(context).pushNamed(RouterTable.loginPath); + } + }); + }, + ), ); } - Widget bottomAppBarItem({ + NavigationDestination bottomAppBarItem({ required int index, // 序列 }) { Map item = _iconList[index]; - //设置默认未选中的状态 - // TextStyle style = TextStyle( - // fontSize: size, - // color: color, - // ); - - bool isShow = item["display"]; - - Widget child; - if (!isShow) { - child = Container(); - } else { - child = NavigationDestination( - icon: Icon( - item['icon'], - color: Theme.of(context).colorScheme.secondary, - ), - label: item["title"], - selectedIcon: Icon( - item['icon'], - color: Theme.of(context).primaryColor, - ), - ); - } + NavigationDestination child = NavigationDestination( + icon: Icon(item['icon']), + label: item["title"], + selectedIcon: Icon(item['selectedIcon']), + ); return child; } diff --git a/lib/router/router.dart b/lib/router/router.dart deleted file mode 100644 index 82529a1..0000000 --- a/lib/router/router.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:bistro/app.dart'; - -var router = { - '/app': (context) => const App(), //应用页 -}; diff --git a/lib/router/router_table.dart b/lib/router/router_table.dart new file mode 100644 index 0000000..ce9ce1a --- /dev/null +++ b/lib/router/router_table.dart @@ -0,0 +1,40 @@ +import 'package:bistro/login.dart'; +import 'package:flutter/material.dart'; + +import '../life.dart'; + +class RouterTable { + // static String splashPath = 'splash'; + static String loginPath = 'login'; + static String homePath = '/'; + + // static String notFoundPath = '404'; + + static Map routeTables = { + //404页面 + // notFoundPath: (context) => NotFound(), + //启动页 + // splashPath: (context) => Splash(), + //登录 + loginPath: (context) => const Login(), + //首页 + homePath: (context) => const Life(), + }; + + ///路由拦截 + static Route onGenerateRoute(RouteSettings settings) { + return MaterialPageRoute( + settings: settings, + builder: (context) { + String name = settings.name!; + // if (routeTables[name] == null) { + // name = notFoundPath; + // } + + Widget widget = routeTables[name]!(context); + + return widget; + }, + ); + } +} diff --git a/test/widget_test.dart b/test/widget_test.dart index 661c3bd..f155722 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:bistro/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const Bistro()); + await tester.pumpWidget(Bistro()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget);