web_page.dart 14.4 KB
import 'package:appframe/bloc/web_cubit.dart';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/evn_config.dart';
import 'package:appframe/config/locator.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebPage extends StatelessWidget {
  const WebPage({super.key});

  @override
  Widget build(BuildContext buildContext) {
    final Map<String, dynamic>? extraData = GoRouterState.of(buildContext).extra as Map<String, dynamic>?;

    var sessionCode = extraData?['sessionCode'];
    var userCode = extraData?['userCode'];
    var classCode = extraData?['classCode'];
    var userType = extraData?['userType'];
    var stuId = extraData?['stuId'];

    if (sessionCode == null || sessionCode == '') {
      var sharedPreferences = getIt.get<SharedPreferences>();
      sessionCode = sharedPreferences.getString('auth_sessionCode');
      userCode = sharedPreferences.getString('auth_userCode');
      classCode = sharedPreferences.getString('auth_classCode');
      userType = sharedPreferences.getInt('auth_userType');
      stuId = sharedPreferences.getString('auth_stuId');
    }

    return BlocProvider(
      create: (context) => WebCubit(
        WebState(
          sessionCode: sessionCode,
          userCode: userCode,
          classCode: classCode,
          userType: userType,
          stuId: stuId,
        ),
      ),
      child: BlocConsumer<WebCubit, WebState>(
        builder: (ctx, state) {
          return PopScope(
            canPop: false,
            onPopInvokedWithResult: (didPop, result) {
              ctx.read<WebCubit>().handleBack();
            },
            child: Scaffold(
              appBar: _buildAppBar(ctx, state),
              endDrawer: _buildDrawer(ctx, state),
              body: Stack(
                children: [
                  state.loaded
                      ? SizedBox(
                          height: MediaQuery.of(ctx).size.height - 60, // 减去100像素留空
                          child: WebViewWidget(controller: ctx.read<WebCubit>().controller),
                        )
                      : const Center(
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              CircularProgressIndicator(),
                              SizedBox(height: 16),
                              Text('加载中...'),
                            ],
                          ),
                        ),
                  // 添加升级遮罩层
                  if (state.isUpgrading)
                    Container(
                      color: Colors.black54,
                      child: const Center(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            CircularProgressIndicator(),
                            SizedBox(height: 16),
                            Text('资源更新中...', style: TextStyle(color: Colors.white)),
                          ],
                        ),
                      ),
                    ),
                ],
              ),
              bottomNavigationBar: state.showBottomNavBar
                  ? BottomNavigationBar(
                      type: BottomNavigationBarType.fixed,
                      currentIndex: state.selectedIndex,
                      selectedItemColor: Color(0xFF7691fa),
                      unselectedItemColor: Color(0xFF969799),
                      onTap: (index) {
                        // 更新选中索引
                        ctx.read<WebCubit>().updateSelectedIndex(index);
                        // 根据 index 执行相应的操作
                      },
                      items: const [
                        BottomNavigationBarItem(
                          icon: Icon(Icons.home, size: 32),
                          label: '我的班级',
                        ),
                        BottomNavigationBarItem(
                          icon: Icon(Icons.contact_page, size: 32),
                          label: '通讯录',
                        ),
                        BottomNavigationBarItem(
                          icon: Icon(Icons.find_in_page, size: 32),
                          label: '发现',
                        ),
                        BottomNavigationBarItem(
                          icon: Icon(Icons.person, size: 32),
                          label: '我的',
                        ),
                      ],
                    )
                  : null,
            ),
          );
        },
        listener: (context, state) {
          if (state.suggestUpgrade) {
            context.read<WebCubit>().suggestUpgrade(context);
          } else if (state.orientationCmdFlag) {
            context.read<WebCubit>().getOrientation(context);
          } else if (state.windowInfoCmdFlag) {
            context.read<WebCubit>().getWindowInfo(context);
          } else if (state.chooseImageCmdFlag) {
            context.read<WebCubit>().chooseImage(context);
          } else if (state.chooseVideoCmdFlag) {
            context.read<WebCubit>().chooseVideo(context);
          }
        },
      ),
    );
  }

  AppBar _buildAppBar(BuildContext ctx, WebState state) {
    return AppBar(
      title: Text(state.title, style: TextStyle(color: Color(state.titleColor), fontSize: 18)),
      centerTitle: true,
      automaticallyImplyLeading: false,
      backgroundColor: Color(state.bgColor),
      actionsIconTheme: IconThemeData(color: Colors.white),
      leading: state.opIcon == 'back'
          ? IconButton(
              icon: const Icon(Icons.arrow_back, color: Colors.white),
              onPressed: () {
                ctx.read<WebCubit>().handleBack();
              },
            )
          : (state.opIcon == 'home'
              ? IconButton(
                  icon: const Icon(Icons.home, color: Colors.white),
                  onPressed: () {
                    ctx.read<WebCubit>().handleHome();
                  },
                )
              : null),
    );
  }

  Drawer _buildDrawer(BuildContext ctx, WebState state) {
    return Drawer(
        width: MediaQuery.of(ctx).size.width * 0.8,
        child: Column(children: [
          DrawerHeader(
            decoration: BoxDecoration(
              color: Color(0xFF7691FA),
            ),
            child: Align(
              alignment: Alignment.centerLeft,
              child: Text(
                '设置',
                style: TextStyle(
                  // color: Theme.of(ctx).colorScheme.onPrimary,
                  fontSize: 24,
                  color: Colors.white,
                ),
              ),
            ),
          ),
          Expanded(
            child: SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Card(
                    margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), // 减小垂直间距
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(6),
                    ),
                    child: Column(
                      children: [
                        ListTile(
                          leading: const Icon(Icons.lock, size: 20),
                          // 减小图标大小
                          title: const Text('账号与安全', style: TextStyle(fontSize: 14)),
                          // 设置字体大小
                          onTap: () {
                            Navigator.pop(ctx);
                            ctx.read<WebCubit>().goAccount();
                          },
                          contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                          trailing: Icon(Icons.arrow_forward_ios, size: 14),
                          // 调整内边距
                          dense: true,
                          // 使用紧凑布局
                          visualDensity: VisualDensity.compact, // 视觉密度设为紧凑
                        ),
                      ],
                    ),
                  ),
                  SizedBox(height: 8),
                  Card(
                    margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), // 减小垂直间距
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(6),
                    ),
                    child: Column(
                      children: [
                        ListTile(
                          leading: const Icon(Icons.book_outlined, size: 20),
                          // 减小图标大小
                          title: const Text('用户协议', style: TextStyle(fontSize: 14)),
                          // 设置字体大小
                          onTap: () {
                            Navigator.pop(ctx);
                          },
                          contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                          trailing: Icon(Icons.arrow_forward_ios, size: 14),
                          // 调整内边距
                          dense: true,
                          // 使用紧凑布局
                          visualDensity: VisualDensity.compact, // 视觉密度设为紧凑
                        ),
                      ],
                    ),
                  ),
                  SizedBox(height: 8),
                  Card(
                    margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 2),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(6),
                    ),
                    child: Column(
                      children: [
                        ListTile(
                          leading: const Icon(Icons.cleaning_services, size: 20),
                          title: const Text('清理缓存', style: TextStyle(fontSize: 14)),
                          onTap: () {
                            Navigator.pop(ctx);
                            _showClearCacheDialog(ctx);
                          },
                          contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                          dense: true,
                          visualDensity: VisualDensity.compact,
                        ),
                        ListTile(
                          leading: const Icon(Icons.logout, size: 20),
                          title: const Text('退出登录', style: TextStyle(fontSize: 14)),
                          onTap: () {
                            Navigator.pop(ctx);
                            ctx.read<WebCubit>().logout();
                          },
                          contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                          dense: true,
                          visualDensity: VisualDensity.compact,
                        ),
                      ],
                    ),
                  ),
                  SizedBox(height: 8),
                  Card(
                    margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 2), // 减小垂直间距
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(6),
                    ),
                    child: Column(
                      children: [
                        ListTile(
                          leading: const Icon(Icons.timeline, size: 20),
                          // 减小图标大小
                          title: const Text('切换日志模式', style: TextStyle(fontSize: 14)),
                          // 设置字体大小
                          onTap: () {
                            Navigator.pop(ctx);
                            ctx.read<WebCubit>().handleToggleDebug();
                          },
                          contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                          // trailing: Icon(Icons.arrow_forward_ios, size: 14),
                          // 调整内边距
                          dense: true,
                          // 使用紧凑布局
                          visualDensity: VisualDensity.compact, // 视觉密度设为紧凑
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
          const Divider(),
          Container(
            width: double.infinity,
            // padding: const EdgeInsets.all(16.0),
            child: Center(
              child: Column(
                children: [
                  Text(
                    EnvConfig.isDev() ? '开发版' : '正式版',
                    style: TextStyle(
                      color: Colors.grey,
                      fontSize: 14,
                    ),
                  ),
                  SizedBox(height: 4),
                  Text(
                    'Version ${Constant.appVersion}-${state.h5Version}',
                    style: TextStyle(
                      color: Colors.grey,
                      fontSize: 12,
                    ),
                  ),
                  SizedBox(height: 8),
                  Text(
                    'Copyright © 中山班小二科技有限公司',
                  ),
                  SizedBox(height: 8),
                ],
              ),
            ),
          ),
        ]));
  }

  void _showClearCacheDialog(BuildContext ctx) {
    showDialog(
      context: ctx,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('清理缓存'),
          content: Text('清理缓存后将需要重新登录,是否继续?'),
          actions: <Widget>[
            TextButton(
              child: Text('取消'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            TextButton(
              child: Text('确认'),
              onPressed: () {
                Navigator.of(context).pop();
                var webCubit = ctx.read<WebCubit>();
                webCubit.clearStorage();
                webCubit.goLogin();
              },
            ),
          ],
        );
      },
    );
  }
}