From fb529b248569c4fa16455b7a7ae59beeee8ca36f Mon Sep 17 00:00:00 2001 From: Songzex <2402265378@qq.com> Date: Wed, 13 May 2026 10:34:07 +0800 Subject: [PATCH] =?UTF-8?q?-=E6=9A=82=E6=8F=90=E4=BA=A4-bug=E6=9C=AA?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/di/injection.dart | 4 + lib/core/router/app_router.dart | 26 +- lib/core/router/route_paths.dart | 2 + .../auth/presentation/bloc/auth_cubit.dart | 21 +- .../auth/presentation/pages/login_page.dart | 37 ++- .../presentation/pages/register_page.dart | 293 +++++++++++++++++- .../home/presentation/routes/home_routes.dart | 14 +- .../presentation/main_wrapper.dart | 209 +++++++++---- .../my/presentation/pages/my_page.dart | 13 + lib/main.dart | 3 + 10 files changed, 501 insertions(+), 121 deletions(-) diff --git a/lib/core/di/injection.dart b/lib/core/di/injection.dart index f432bcc7..492a556b 100644 --- a/lib/core/di/injection.dart +++ b/lib/core/di/injection.dart @@ -16,6 +16,7 @@ import 'package:maibu_satabot_v2/features/my/presentation/bloc/my_cubit.dart'; import 'package:maibu_satabot_v2/features/my/repository/my_repository.dart'; import 'package:maibu_satabot_v2/features/my/repository/my_repository_impl.dart'; import 'package:maibu_satabot_v2/features/my/usecases/updatename_usecase.dart'; +import 'package:maibu_satabot_v2/features/main_container/presentation/cubit/tab_config_cubit.dart'; import 'package:maibu_satabot_v2/features/remote_control/data/repositories/remote_control_repository_impl.dart'; import 'package:maibu_satabot_v2/features/remote_control/domain/repositories/remote_control_repository.dart'; import 'package:maibu_satabot_v2/features/remote_control/domain/usecase/diff_steer_usecase.dart'; @@ -189,6 +190,9 @@ Future init() async { // 🔥 语言管理 Cubit (单例) sl.registerLazySingleton(() => LocaleCubit()); + // Tab 配置 Cubit (单例) + sl.registerLazySingleton(() => TabConfigCubit(sl())); + sl.registerLazySingleton(() => GetDeviceLocationUseCase(sl())); sl.registerLazySingleton(() => DevicesCubit(sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(), sl(),sl(),sl(),sl())); diff --git a/lib/core/router/app_router.dart b/lib/core/router/app_router.dart index df18c213..0c8bff72 100644 --- a/lib/core/router/app_router.dart +++ b/lib/core/router/app_router.dart @@ -6,6 +6,8 @@ import 'package:maibu_satabot_v2/features/auth/presentation/routes/auth_routes.d import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart'; import 'package:maibu_satabot_v2/features/home/presentation/routes/home_routes.dart'; import 'package:maibu_satabot_v2/features/my/presentation/routes/my_routes.dart'; +import 'package:maibu_satabot_v2/features/my/presentation/routes/settings_routes.dart'; +import 'package:maibu_satabot_v2/features/waring_center/presentation/routes/warning_center_routes.dart'; import '../../features/auth/presentation/bloc/auth_cubit.dart'; import '../../features/auth/presentation/bloc/auth_state.dart'; @@ -43,33 +45,17 @@ GoRouter createRouter(AuthCubit authCubit) { }, ), - // 注册登录注册 路由 GoRoute( - path: RoutePaths.login, - builder: (context, state) => const LoginPage(), + path: RoutePaths.home, + builder: (context, state) => const MainWrapper(), ), - // 1. 外部路由(无底部导航栏) ...AuthRoutes.routes, ...HomeRoutes.routes, ...AiRoutes.routes, ...MyRoutes.routes, - - // 2. 内部路由(带底部导航栏的容器) - StatefulShellRoute.indexedStack( - builder: (context, state, navigationShell) { - // 返回我们定义的 MainWrapper - return MainWrapper(navigationShell: navigationShell); - }, - branches: [ - // 拿一级页面 - HomeRoutes.branch, - - AiRoutes.branch, - - MyRoutes.branch, - ], - ), + ...SettingsRoutes.routes, + ...WarningCenterRoutes.routes, ], ); } diff --git a/lib/core/router/route_paths.dart b/lib/core/router/route_paths.dart index 989fcae3..981020f1 100644 --- a/lib/core/router/route_paths.dart +++ b/lib/core/router/route_paths.dart @@ -16,6 +16,8 @@ class RoutePaths { static const djMap = '/home/dj_map'; static const productDesc = '/home/productDesc'; static const usage = '/home/usage'; + static const warningCenter = '/home/warning_center'; + static const settings = '/my/settings'; static const machineDetails = '/machine_details/machine_details'; } diff --git a/lib/features/auth/presentation/bloc/auth_cubit.dart b/lib/features/auth/presentation/bloc/auth_cubit.dart index c3077d0e..ae2f3fff 100644 --- a/lib/features/auth/presentation/bloc/auth_cubit.dart +++ b/lib/features/auth/presentation/bloc/auth_cubit.dart @@ -68,25 +68,12 @@ class AuthCubit extends Cubit { /// 当 HTTP 登录/注册成功后调用 Future loginSuccess(UserEntity user) async { - // 🔥 关键修复:先立即更新状态,触发 GoRouter redirect + await storage.saveUser(user); + await tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT); + // await _authTcpDatasource.sendAuthPacket(); //包括发送认证包和获取列表和切换函数 + //tcp.startHeartbeat(interval: const Duration(seconds: 4)); //启动心跳 appCubit.setAuth(user); emit(AuthAuthenticated(user)); - - // 然后异步执行其他操作(不阻塞主流程) - _performPostLoginTasks(user); - } - - /// 登录后后台任务(不阻塞主流程) - Future _performPostLoginTasks(UserEntity user) async { - try { - await storage.saveUser(user); - await tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT); - // await _authTcpDatasource.sendAuthPacket(); - // tcp.startHeartbeat(interval: const Duration(seconds: 4)); - } catch (e) { - _logger.logWithLevel('[AUTH] 登录后任务失败: $e', level: 'ERROR'); - // 不影响已登录状态,只是记录错误 - } } /// 退出登录 (主动或被动) diff --git a/lib/features/auth/presentation/pages/login_page.dart b/lib/features/auth/presentation/pages/login_page.dart index 9c46a550..2a9316ad 100644 --- a/lib/features/auth/presentation/pages/login_page.dart +++ b/lib/features/auth/presentation/pages/login_page.dart @@ -39,9 +39,7 @@ class _LoginPageState extends State { body: BlocListener( listener: (context, state) { if (state is LoginSuccess) { - // 登录成功后,AuthCubit 状态已更新 - // GoRouter 的 redirect 会自动检测到已登录状态并跳转到首页 - // 不需要手动调用 context.go + context.go(RoutePaths.home); } else if (state is LoginFailure) { // 可以在这里弹出简洁的黑白提示框 ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('登录失败,${state.message}'))); @@ -122,6 +120,39 @@ class _LoginPageState extends State { }, ), ), + const SizedBox(height: 24), + + Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + "没有账号吗?", + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + GestureDetector( + onTap: () { + print('点击了立即注册'); + print('跳转路径: ${RoutePaths.register}'); + context.go(RoutePaths.register); + }, + child: const Text( + "立即注册", + style: TextStyle( + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + + const SizedBox(height: 20), + + + ], ), ), diff --git a/lib/features/auth/presentation/pages/register_page.dart b/lib/features/auth/presentation/pages/register_page.dart index b1f3badf..b2307b45 100644 --- a/lib/features/auth/presentation/pages/register_page.dart +++ b/lib/features/auth/presentation/pages/register_page.dart @@ -1,13 +1,300 @@ +import 'package:cc_ui_kit/cc_ui_kit.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:maibu_satabot_v2/core/router/route_paths.dart'; -class RegisterPage extends StatelessWidget { +class RegisterPage extends StatefulWidget { const RegisterPage({super.key}); + @override + State createState() => _RegisterPageState(); +} + +class _RegisterPageState extends State { + final _userCtrl = TextEditingController(); + final _pwdCtrl = TextEditingController(); + final _confirmPwdCtrl = TextEditingController(); + bool _isAgreed = false; + bool _obscurePwd = true; + bool _obscureConfirmPwd = true; + + @override + void dispose() { + _userCtrl.dispose(); + _pwdCtrl.dispose(); + _confirmPwdCtrl.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Register')), - body: Center(child: Text('Welcome Register page')), + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.black), + onPressed: () => context.go(RoutePaths.login), + ), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 30.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 40), + const Text( + "账号注册", + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 12), + const Text( + "请填写以下信息完成注册", + style: TextStyle(fontSize: 15, color: Colors.grey), + ), + const SizedBox(height: 40), + + _buildInputLabel("用户名"), + TextField( + controller: _userCtrl, + cursorColor: Colors.black, + decoration: _inputDecoration(hint: "请设置用户名"), + ), + + const SizedBox(height: 24), + + _buildInputLabel("密码"), + TextField( + controller: _pwdCtrl, + obscureText: _obscurePwd, + cursorColor: Colors.black, + decoration: _inputDecoration( + hint: "请设置密码", + suffixIcon: IconButton( + icon: Icon( + _obscurePwd + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + color: Colors.grey, + size: 20, + ), + onPressed: () => setState(() => _obscurePwd = !_obscurePwd), + ), + ), + ), + + const SizedBox(height: 24), + + _buildInputLabel("确认密码"), + TextField( + controller: _confirmPwdCtrl, + obscureText: _obscureConfirmPwd, + cursorColor: Colors.black, + decoration: _inputDecoration( + hint: "请再次输入密码", + suffixIcon: IconButton( + icon: Icon( + _obscureConfirmPwd + ? Icons.visibility_off_outlined + : Icons.visibility_outlined, + color: Colors.grey, + size: 20, + ), + onPressed: () => setState( + () => _obscureConfirmPwd = !_obscureConfirmPwd, + ), + ), + ), + ), + + const SizedBox(height: 20), + + _buildProtocolSection(), + + const SizedBox(height: 40), + + SizedBox( + width: double.infinity, + child: CCPrimaryButton( + onPressed: _isAgreed ? _handleRegister : null, + text: '注 册', + ), + ), + + const SizedBox(height: 24), + + Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + "已有账号?", + style: TextStyle(fontSize: 14, color: Colors.grey), + ), + GestureDetector( + onTap: () => context.go(RoutePaths.login), + child: const Text( + "立即登录", + style: TextStyle( + fontSize: 14, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + + const SizedBox(height: 20), + ], + ), + ), + ); + } + + void _handleRegister() { + if (_userCtrl.text.isEmpty || _pwdCtrl.text.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('请填写完整信息')), + ); + return; + } + + if (_pwdCtrl.text != _confirmPwdCtrl.text) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('两次输入的密码不一致')), + ); + return; + } + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('注册功能开发中...')), + ); + } + + Widget _buildInputLabel(String label) { + return Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Text( + label, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + ); + } + + InputDecoration _inputDecoration({required String hint, Widget? suffixIcon}) { + return InputDecoration( + hintText: hint, + hintStyle: TextStyle(color: Colors.grey.shade400, fontSize: 14), + filled: true, + fillColor: Colors.grey.shade50, + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: Colors.grey.shade200), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: Colors.black, width: 1), + ), + suffixIcon: suffixIcon, + ); + } + + Widget _buildProtocolSection() { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: 24, + width: 24, + child: Checkbox( + value: _isAgreed, + activeColor: Colors.black, + onChanged: (val) => setState(() => _isAgreed = val!), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: Wrap( + children: [ + const Text( + "我已阅读并同意 ", + style: TextStyle(fontSize: 13, color: Colors.grey), + ), + _protocolText("《用户协议》", () => _showProtocolDetail("用户协议")), + const Text(" 和 ", style: TextStyle(fontSize: 13, color: Colors.grey)), + _protocolText("《隐私政策》", () => _showProtocolDetail("隐私政策")), + ], + ), + ), + ], + ); + } + + Widget _protocolText(String text, VoidCallback onTap) { + return GestureDetector( + onTap: onTap, + child: Text( + text, + style: const TextStyle( + fontSize: 13, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ); + } + + void _showProtocolDetail(String title) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + builder: (context) => Container( + padding: const EdgeInsets.all(24), + height: MediaQuery.of(context).size.height * 0.7, + child: Column( + children: [ + Text( + title, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const Divider(height: 32), + Expanded( + child: SingleChildScrollView( + child: Text( + "此处放置您的${title}详细内容...\n" * 20, + style: const TextStyle(color: Colors.black87, height: 1.5), + ), + ), + ), + const SizedBox(height: 16), + SizedBox( + width: double.infinity, + child: CCPrimaryButton( + onPressed: () => Navigator.pop(context), + text: "我已了解", + ), + ), + ], + ), + ), ); } } diff --git a/lib/features/home/presentation/routes/home_routes.dart b/lib/features/home/presentation/routes/home_routes.dart index 8b900ac5..2624ba0f 100644 --- a/lib/features/home/presentation/routes/home_routes.dart +++ b/lib/features/home/presentation/routes/home_routes.dart @@ -15,7 +15,7 @@ import '../pages/route_plan_page.dart'; import '../pages/running_status_page.dart'; class HomeRoutes { - /// 1. 全屏功能页面(不带导航栏) + /// 全屏功能页面(不带导航栏) /// 在 createRouter 的根 routes 中使用 ...HomeRoutes.routes 引入 static List get routes => [ GoRoute( @@ -38,16 +38,4 @@ class HomeRoutes { ), ), ]; - - /// 2. 首页 Tab 分支(带导航栏) - /// 仅保留真正的首页入口 - static StatefulShellBranch get branch => StatefulShellBranch( - routes: [GoRoute( - path: RoutePaths.home, - builder: (context, state) => BlocProvider.value( - value: sl(), // 使用全局单例,持久监听 0x12 - child: const HomePage(), - ), - )], - ); } diff --git a/lib/features/main_container/presentation/main_wrapper.dart b/lib/features/main_container/presentation/main_wrapper.dart index efbe2d83..f5cfba96 100644 --- a/lib/features/main_container/presentation/main_wrapper.dart +++ b/lib/features/main_container/presentation/main_wrapper.dart @@ -1,84 +1,163 @@ import 'dart:ui'; - import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_nav_bar/google_nav_bar.dart'; +import 'package:maibu_satabot_v2/features/main_container/presentation/cubit/tab_config_cubit.dart'; +import 'package:maibu_satabot_v2/features/main_container/domain/tab_config.dart'; +import 'package:maibu_satabot_v2/features/home/presentation/pages/home_page.dart'; +import 'package:maibu_satabot_v2/features/ai/presentation/pages/ai_page.dart'; +import 'package:maibu_satabot_v2/features/waring_center/presentation/pages/warning_center_page.dart'; +import 'package:maibu_satabot_v2/features/my/presentation/pages/my_page.dart'; -class MainWrapper extends StatelessWidget { - final StatefulNavigationShell navigationShell; +class MainWrapper extends StatefulWidget { + const MainWrapper({super.key}); - const MainWrapper({super.key, required this.navigationShell}); + @override + State createState() => _MainWrapperState(); +} + +class _MainWrapperState extends State { + int _currentIndex = 0; + final PageController _pageController = PageController(); + + @override + void dispose() { + _pageController.dispose(); + super.dispose(); + } + + IconData _getIconData(String iconName) { + switch (iconName) { + case 'grid_view_rounded': + return Icons.grid_view_rounded; + case 'auto_awesome_rounded': + return Icons.auto_awesome_rounded; + case 'warning_amber_rounded': + return Icons.warning_amber_rounded; + case 'person_rounded': + return Icons.person_rounded; + default: + return Icons.home_rounded; + } + } + + Widget _buildCurrentPage(TabConfigItem tab) { + switch (tab.id) { + case 'home': + return const HomePage(); + case 'ai': + return const AiPage(); + case 'warning': + return const WarningCenterPage(); + case 'my': + return const MyPage(); + default: + return const HomePage(); + } + } @override Widget build(BuildContext context) { - return Scaffold( - extendBody: true, // 必须开启,让内容流过导航栏下方 - body: navigationShell, - bottomNavigationBar: Container( - margin: const EdgeInsets.fromLTRB(20, 0, 20, 10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(32), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.12), // 强化阴影,增加悬浮感 - blurRadius: 30, - offset: const Offset(0, 10), + return BlocBuilder( + builder: (context, state) { + if (state is! TabConfigLoaded) { + return const Scaffold(body: Center(child: CircularProgressIndicator())); + } + + final config = state.config; + final enabledItems = config.enabledItems; + + if (enabledItems.isEmpty) { + return const Scaffold( + body: Center( + child: Text('请至少启用一个 Tab'), ), - ], - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(32), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 16, sigmaY: 16), // 增加模糊半径 - child: Container( - decoration: BoxDecoration( - // 降低白色透明度到 0.4,减少“灰蒙蒙”的白雾感,让背景颜色更亮地透出来 - color: Colors.white.withOpacity(0.4), - borderRadius: BorderRadius.circular(32), - border: Border.all( - // 使用极细的深色半透明边框勾勒轮廓 - color: Colors.black.withOpacity(0.08), - width: 0.5, + ); + } + + if (_currentIndex >= enabledItems.length) { + _currentIndex = 0; + } + + return Scaffold( + extendBody: true, + body: PageView( + controller: _pageController, + physics: const NeverScrollableScrollPhysics(), + onPageChanged: (index) { + setState(() { + _currentIndex = index; + }); + }, + children: enabledItems.map((tab) => _buildCurrentPage(tab)).toList(), + ), + bottomNavigationBar: Container( + margin: const EdgeInsets.fromLTRB(20, 0, 20, 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(32), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.12), + blurRadius: 30, + offset: const Offset(0, 10), ), - ), - child: SafeArea( - top: false, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 8, - ), - child: GNav( - rippleColor: Colors.transparent, - hoverColor: Colors.transparent, - gap: 10, - // 【关键修改】选中状态:纯黑背景 + 纯白图标/文字 - activeColor: Colors.white, - tabBackgroundColor: Colors.black, - // 未选中状态:深黑色 - color: Colors.black87, - iconSize: 24, - padding: const EdgeInsets.symmetric( - horizontal: 18, - vertical: 10, + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(32), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 16, sigmaY: 16), + child: Container( + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.4), + borderRadius: BorderRadius.circular(32), + border: Border.all( + color: Colors.black.withOpacity(0.08), + width: 0.5, + ), + ), + child: SafeArea( + top: false, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 8, + ), + child: GNav( + rippleColor: Colors.transparent, + hoverColor: Colors.transparent, + gap: 10, + activeColor: Colors.white, + tabBackgroundColor: Colors.black, + color: Colors.black87, + iconSize: 24, + padding: const EdgeInsets.symmetric( + horizontal: 18, + vertical: 10, + ), + duration: const Duration(milliseconds: 300), + selectedIndex: _currentIndex, + onTabChange: (index) { + setState(() { + _currentIndex = index; + }); + _pageController.jumpToPage(index); + }, + tabs: enabledItems.map((item) { + return GButton( + icon: _getIconData(item.icon), + text: item.name, + ); + }).toList(), + ), ), - duration: const Duration(milliseconds: 300), - selectedIndex: navigationShell.currentIndex, - onTabChange: (index) { - navigationShell.goBranch(index); - }, - tabs: const [ - GButton(icon: Icons.grid_view_rounded, text: '状态'), - GButton(icon: Icons.auto_awesome_rounded, text: 'AI'), - GButton(icon: Icons.person_rounded, text: '我的'), - ], ), ), ), ), ), - ), - ), + ); + }, ); } } diff --git a/lib/features/my/presentation/pages/my_page.dart b/lib/features/my/presentation/pages/my_page.dart index 68779d42..3af60c35 100644 --- a/lib/features/my/presentation/pages/my_page.dart +++ b/lib/features/my/presentation/pages/my_page.dart @@ -96,6 +96,19 @@ class MyPage extends StatelessWidget { ), child: Column( children: [ + // 🔥 设置按钮 + ListTile( + leading: const Icon(Icons.settings, color: Colors.black), + title: Text(AppLocalizations.of(context).translate('my.settings'), style: const TextStyle(color: Colors.black)), + trailing: const Icon(Icons.arrow_forward, color: Colors.black), + onTap: () { + context.push(RoutePaths.settings); + }, + ), + + // 分割线 + Divider(height: 1, color: Colors.grey.withOpacity(0.3)), + // 功能列表 ListView.builder( shrinkWrap: true, diff --git a/lib/main.dart b/lib/main.dart index e7eae90a..45fe5bf8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,6 +11,8 @@ import 'package:maibu_satabot_v2/core/logging/i_logger_service.dart'; import 'package:maibu_satabot_v2/core/theme/AppTheme.dart'; import 'package:maibu_satabot_v2/features/auth/presentation/bloc/auth_cubit.dart'; import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart'; +import 'package:maibu_satabot_v2/features/main_container/presentation/cubit/tab_config_cubit.dart'; +import 'package:maibu_satabot_v2/features/main_container/presentation/main_wrapper.dart'; import 'core/di/injection.dart'; import 'core/localization/app_localizations.dart'; @@ -77,6 +79,7 @@ class MyApp extends StatelessWidget { ), // 🔥 语言管理 Cubit BlocProvider.value(value: localeCubit), + BlocProvider.value(value: sl()), // 其他 Cubit... ], child: BlocBuilder(