Commit 5a44fc5c by tanghuan

调整打开设置界面的方式

1 parent 1f29d37d
import 'dart:io';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/config/routes.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluwx/fluwx.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SettingState extends Equatable {
final String h5Version;
const SettingState({
this.h5Version = '',
});
SettingState copyWith({
String? h5Version,
}) {
return SettingState(
h5Version: h5Version ?? this.h5Version,
);
}
@override
List<Object?> get props => [h5Version];
}
class SettingCubit extends Cubit<SettingState> {
final SharedPreferences _prefs = getIt.get<SharedPreferences>();
final Fluwx _fluwx = getIt.get<Fluwx>();
SettingCubit() : super(const SettingState()) {
_init();
}
void _init() {
_readH5ShowVersion();
}
void _readH5ShowVersion() {
var h5Version = _prefs.getString(Constant.h5ShowVersionKey) ?? 'unknown';
emit(state.copyWith(h5Version: h5Version));
}
/// 跳转客服(微信小程序)
void goCs() {
_fluwx.open(
target: MiniProgram(
username: 'gh_0ed02e873abc',
path: '/pages/agentChat/index?showAuthDirectly=1&agentId=eiXH0MAJmjgl',
miniProgramType: WXMiniProgramType.release,
),
);
}
/// 退出登录
Future<void> logout() async {
// 删除所有auth_开头的key
_prefs.getKeys().forEach((key) {
if (key.startsWith('auth_')) {
_prefs.remove(key);
}
});
// IM 登出
// await getIt.get<ImService>().logout();
router.go('/loginMain');
}
/// 切换日志模式
Future<void> handleToggleDebug() async {
var debug = _prefs.getInt('debug') ?? 0;
debug = (debug == 0 ? 1 : 0);
_prefs.setInt('debug', debug);
// 通知 WebCubit 更新 H5 状态
WebCubitHolder.instance?.notifyDebugStatus(debug);
}
/// 清理缓存
Future<void> clearStorage() async {
// 1 清理 WebView 相关缓存
WebCubitHolder.instance?.clearWebCache();
// 2 清理非 h5_version 的缓存
_prefs.getKeys().forEach((key) async {
if (!key.startsWith('h5')) {
await _prefs.remove(key);
}
});
// 3 清理 http_dist_assets 下的非当前版本号的文件和目录
var dir = await getApplicationSupportDirectory();
var httpDir = Directory('${dir.path}/${Constant.h5DistDir}');
if (httpDir.existsSync()) {
var version = _prefs.getString(Constant.h5VersionKey) ?? Constant.h5Version;
await for (final entity in httpDir.list()) {
if (entity is Directory) {
if (!entity.path.endsWith(version)) {
await entity.delete(recursive: true);
}
} else if (entity is File) {
if (!entity.path.endsWith('$version.zip')) {
await entity.delete();
}
}
}
}
// 4 清理临时目录下的所有文件和目录
var tempDir = await getTemporaryDirectory();
if (tempDir.existsSync()) {
await for (final entity in tempDir.list()) {
if (entity is Directory) {
await entity.delete(recursive: true);
} else {
await entity.delete();
}
}
}
}
}
......@@ -67,8 +67,6 @@ class WebState extends Equatable {
final bool chooseVideoCmdFlag;
final String chooseVideoCmdMessage;
final String h5Version;
/// 用于测试监测问题
final String testMsg;
......@@ -96,7 +94,6 @@ class WebState extends Equatable {
this.chooseImageCmdMessage = '',
this.chooseVideoCmdFlag = false,
this.chooseVideoCmdMessage = '',
this.h5Version = '',
this.testMsg = '',
});
......@@ -125,7 +122,6 @@ class WebState extends Equatable {
String? chooseImageCmdMessage,
bool? chooseVideoCmdFlag,
String? chooseVideoCmdMessage,
String? h5Version,
String? testMsg,
}) {
return WebState(
......@@ -152,7 +148,6 @@ class WebState extends Equatable {
chooseImageCmdMessage: chooseImageCmdMessage ?? this.chooseImageCmdMessage,
chooseVideoCmdFlag: chooseVideoCmdFlag ?? this.chooseVideoCmdFlag,
chooseVideoCmdMessage: chooseVideoCmdMessage ?? this.chooseVideoCmdMessage,
h5Version: h5Version ?? this.h5Version,
testMsg: testMsg ?? this.testMsg,
);
}
......@@ -181,7 +176,6 @@ class WebState extends Equatable {
chooseImageCmdMessage,
chooseVideoCmdFlag,
chooseVideoCmdMessage,
h5Version,
testMsg,
];
}
......@@ -189,7 +183,6 @@ class WebState extends Equatable {
class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
late final MessageDispatcher _dispatcher;
late final WebViewController _controller;
late final Fluwx _fluwx;
HttpServer? _server;
PlayerService? _playerService;
RecorderService? _recorderService;
......@@ -259,11 +252,7 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
// 加载H5页面
_loadHtml();
// 读取 h5 版本号
_readH5ShowVersion();
// 初始化其它一些属性
_fluwx = getIt.get<Fluwx>();
_playerService = getIt.get<PlayerService>();
_playerService?.sendResponse = _sendResponse;
_recorderService = getIt.get<RecorderService>();
......@@ -271,10 +260,8 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
// 登录IM
_loginIM();
// 针对ios系统,处理侧滑返回
if (Platform.isIOS) {
WebCubitHolder.register(this);
}
// 注册 WebCubit 实例,供其它页面使用
WebCubitHolder.register(this);
}
Future<Map<String, String>> _getVersionConfig() async {
......@@ -385,11 +372,6 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
_controller.loadRequest(Uri.parse(serverUrl));
}
void _readH5ShowVersion() {
var h5Version = getIt.get<SharedPreferences>().getString(Constant.h5ShowVersionKey) ?? 'unknown';
emit(state.copyWith(h5Version: h5Version));
}
Future<void> _loginIM() async {
if (Constant.needIM) {
var imService = getIt.get<ImService>();
......@@ -476,16 +458,24 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
}
///
/// 跳转客服(微信小程序)
/// 清理 WebView 缓存
///
void goCs() {
_fluwx.open(
target: MiniProgram(
username: 'gh_0ed02e873abc',
path: '/pages/agentChat/index?showAuthDirectly=1&agentId=eiXH0MAJmjgl',
miniProgramType: WXMiniProgramType.release,
),
);
Future<void> clearWebCache() async {
_controller.clearLocalStorage();
_controller.clearCache();
}
///
/// 通知 H5 更新调试模式
///
void notifyDebugStatus(int debug) {
var resp = {
'unique': '',
'cmd': 'toggleDebug',
'data': {'debug': debug},
'errMsg': ''
};
_sendResponse(resp);
}
void goLogin() {
......@@ -525,21 +515,6 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
_sendResponse(resp);
}
Future<void> handleToggleDebug() async {
var sharedPreferences = getIt.get<SharedPreferences>();
var debug = sharedPreferences.getInt('debug') ?? 0;
debug = (debug == 0 ? 1 : 0);
sharedPreferences.setInt('debug', debug);
var resp = {
'unique': '',
'cmd': 'toggleDebug',
'data': {'debug': debug},
'errMsg': ''
};
_sendResponse(resp);
}
bool setTitleBar(String title, String color, String bgColor, String icon) {
int parsedTitleColor = _hexStringToInt(color);
int parsedBgColor = _hexStringToInt(bgColor);
......@@ -573,68 +548,6 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
router.push('/account');
}
Future<void> clearStorage() async {
// 1 清理 localStorage
_controller.clearLocalStorage();
_controller.clearCache();
// 2 清理非 h5_version 的缓存
var sharedPreferences = getIt.get<SharedPreferences>();
sharedPreferences.getKeys().forEach((key) async {
if (!key.startsWith('h5')) {
await sharedPreferences.remove(key);
}
});
// 3 清理 http_dist_assets 下的非当前版本号的文件和目录
var dir = await getApplicationSupportDirectory();
var httpDir = Directory('${dir.path}/${Constant.h5DistDir}');
if (httpDir.existsSync()) {
var version = sharedPreferences.getString(Constant.h5VersionKey) ?? Constant.h5Version;
await for (final FileSystemEntity entity in httpDir.list()) {
if (entity is Directory) {
// 删除目录
if (!entity.path.endsWith(version)) {
await entity.delete(recursive: true);
}
} else if (entity is File) {
// 删除文件
if (!entity.path.endsWith('$version.zip')) {
await entity.delete();
}
}
}
}
// 4 清理临时目录下的所有文件和目录
var tempDir = await getTemporaryDirectory();
if (tempDir.existsSync()) {
await for (final FileSystemEntity entity in tempDir.list()) {
if (entity is Directory) {
await entity.delete(recursive: true);
} else {
await entity.delete();
}
}
}
}
Future<void> logout() async {
// 删除所有auth_开头的key
var sharedPreferences = getIt.get<SharedPreferences>();
sharedPreferences.getKeys().forEach((key) {
if (key.startsWith('auth_')) {
sharedPreferences.remove(key);
}
});
// IM 登出
// await getIt.get<ImService>().logout();
goLogin();
}
void updateSelectedIndex(int index) {
emit(state.copyWith(selectedIndex: index));
}
......@@ -1221,9 +1134,7 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
await _playerService?.close();
await _recorderService?.close();
if (Platform.isIOS) {
WebCubitHolder.unregister();
}
WebCubitHolder.unregister();
// 移除观察者
WidgetsBinding.instance.removeObserver(this);
......
......@@ -13,6 +13,7 @@ import 'package:appframe/ui/pages/setting/account_logoff_page.dart';
import 'package:appframe/ui/pages/setting/account_page.dart';
import 'package:appframe/ui/pages/setting/account_phone_page.dart';
import 'package:appframe/ui/pages/setting/account_user_page.dart';
import 'package:appframe/ui/pages/setting/setting_page.dart';
import 'package:appframe/ui/pages/web_page.dart';
import 'package:appframe/ui/widgets/ios_edge_swipe_detector.dart';
import 'package:flutter/material.dart';
......@@ -25,7 +26,7 @@ final GoRouter router = GoRouter(
GoRoute(
path: '/web',
builder: (BuildContext context, GoRouterState state) {
return WebPage();
return const WebPage();
},
),
GoRoute(
......@@ -100,6 +101,12 @@ final GoRouter router = GoRouter(
return const ReloadPage();
},
),
GoRoute(
path: '/setting',
builder: (BuildContext context, GoRouterState state) {
return const SettingPage();
},
),
],
);
......@@ -158,7 +165,7 @@ class AppRouteObserver extends NavigatorObserver {
}
///
/// 只针对iOS使用
/// 用于全局访问 WebCubit 实例
///
class WebCubitHolder {
static WebCubit? instance;
......
import 'package:appframe/bloc/setting/setting_cubit.dart';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/env_config.dart';
import 'package:appframe/config/routes.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SettingPage extends StatelessWidget {
const SettingPage({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SettingCubit(),
child: BlocBuilder<SettingCubit, SettingState>(
builder: (context, state) {
final settingCubit = context.read<SettingCubit>();
return Scaffold(
appBar: AppBar(
title: const Text('设置', style: TextStyle(color: Colors.white, fontSize: 18)),
centerTitle: true,
backgroundColor: const Color(0xFF7691FA),
iconTheme: const IconThemeData(color: Colors.white),
),
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 16),
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: () {
router.push('/account');
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: const Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
],
),
),
const 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: () {
router.push(
'/link',
extra: {'url': 'https://bxr.banxiaoer.net/apps/versions.html', 'title': '版本记录'},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: const Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
const Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.book_outlined, size: 20),
title: const Text('用户协议', style: TextStyle(fontSize: 14)),
onTap: () {
router.push(
'/link',
extra: {
'url': 'https://bxr.banxiaoer.net/apps/useragreement.html',
'title': '用户协议'
},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: const Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
const Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.book_outlined, size: 20),
title: const Text('隐私设置', style: TextStyle(fontSize: 14)),
onTap: () {
router.push(
'/link',
extra: {
'url': 'https://bxr.banxiaoer.net/apps/privacysettings.html',
'title': '隐私设置'
},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: const Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
const Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.book_outlined, size: 20),
title: const Text('关于', style: TextStyle(fontSize: 14)),
onTap: () {
router.push(
'/link',
extra: {'url': 'https://bxr.banxiaoer.net/apps/produce.html', 'title': '关于'},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: const Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
],
),
),
const 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.headset_mic, size: 20),
title: const Text('在线客服', style: TextStyle(fontSize: 14)),
onTap: () {
settingCubit.goCs();
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: const Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
],
),
),
const 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: () {
_showClearCacheDialog(context, settingCubit);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
dense: true,
visualDensity: VisualDensity.compact,
),
const Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.logout, size: 20),
title: const Text('退出登录', style: TextStyle(fontSize: 14)),
onTap: () {
settingCubit.logout();
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
dense: true,
visualDensity: VisualDensity.compact,
),
],
),
),
const SizedBox(height: 8),
EnvConfig.isDev()
? 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: () {
settingCubit.handleToggleDebug();
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
dense: true,
visualDensity: VisualDensity.compact,
),
],
),
)
: const SizedBox(),
],
),
),
),
const Divider(),
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
child: Center(
child: Column(
children: [
if (EnvConfig.isDev()) ...[
const Text(
'开发版',
style: TextStyle(
color: Colors.grey,
fontSize: 14,
),
),
const SizedBox(height: 4),
],
const Text(
'V1.0',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
const SizedBox(height: 8),
const Text(
'粤ICP备2025475184号-15A',
style: TextStyle(color: Colors.grey, fontSize: 12),
),
const SizedBox(height: 8),
const Text(
'Copyright © 中山班小二科技有限公司',
style: TextStyle(color: Colors.grey, fontSize: 12),
),
const SizedBox(height: 8),
Text(
'${Constant.appVersion}-${state.h5Version}',
style: const TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
const SizedBox(height: 10),
],
),
),
),
],
),
);
},
),
);
}
void _showClearCacheDialog(BuildContext context, SettingCubit settingCubit) {
showDialog(
context: context,
builder: (BuildContext ctx) {
return AlertDialog(
title: const Text('清理缓存'),
content: const Text('清理缓存后将需要重新登录,是否继续?'),
actions: <Widget>[
TextButton(
child: const Text('取消'),
onPressed: () {
Navigator.of(ctx).pop();
},
),
TextButton(
child: const Text('确认'),
onPressed: () {
Navigator.of(ctx).pop();
settingCubit.clearStorage();
settingCubit.logout();
},
),
],
);
},
);
}
}
import 'dart:io';
import 'package:appframe/bloc/web_cubit.dart';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/env_config.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/config/routes.dart';
......@@ -12,9 +11,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebPage extends StatelessWidget {
WebPage({super.key});
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
const WebPage({super.key});
@override
Widget build(BuildContext buildContext) {
......@@ -56,9 +53,7 @@ class WebPage extends StatelessWidget {
child: BlocConsumer<WebCubit, WebState>(
builder: (ctx, state) {
final scaffold = Scaffold(
key: _scaffoldKey,
appBar: _buildAppBar(ctx, state),
endDrawer: _buildDrawer(ctx, state),
body: Stack(
children: [
state.loaded
......@@ -183,291 +178,14 @@ class WebPage extends StatelessWidget {
},
)
: null),
);
}
Drawer _buildDrawer(BuildContext ctx, WebState state) {
final screenSize = MediaQuery.of(ctx).size;
return Drawer(
width: screenSize.width > 600 ? 400 : screenSize.width * 0.8, // Pad 上给一个固定最大宽度
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: 4),
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);
router.push(
'/link',
extra: {'url': 'https://bxr.banxiaoer.net/apps/versions.html', 'title': '版本记录'},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.book_outlined, size: 20),
title: const Text('用户协议', style: TextStyle(fontSize: 14)),
onTap: () {
Navigator.pop(ctx);
router.push(
'/link',
extra: {'url': 'https://bxr.banxiaoer.net/apps/useragreement.html', 'title': '用户协议'},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.book_outlined, size: 20),
title: const Text('隐私设置', style: TextStyle(fontSize: 14)),
onTap: () {
Navigator.pop(ctx);
router.push(
'/link',
extra: {'url': 'https://bxr.banxiaoer.net/apps/privacysettings.html', 'title': '隐私设置'},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
trailing: Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact,
),
Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.book_outlined, size: 20),
title: const Text('关于', style: TextStyle(fontSize: 14)),
onTap: () {
Navigator.pop(ctx);
router.push(
'/link',
extra: {'url': 'https://bxr.banxiaoer.net/apps/produce.html', 'title': '关于'},
);
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
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.headset_mic, size: 20),
title: const Text('在线客服', style: TextStyle(fontSize: 14)),
onTap: () {
Navigator.pop(ctx);
ctx.read<WebCubit>().goCs();
},
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
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: 4),
dense: true,
visualDensity: VisualDensity.compact,
),
Divider(height: 1, thickness: 0.5, indent: 16, endIndent: 16),
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: 4),
dense: true,
visualDensity: VisualDensity.compact,
),
],
),
),
SizedBox(height: 8),
EnvConfig.isDev()
? 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: 4),
// trailing: Icon(Icons.arrow_forward_ios, size: 14),
dense: true,
visualDensity: VisualDensity.compact, // 视觉密度设为紧凑
),
],
),
)
: SizedBox(),
],
),
),
),
const Divider(),
Container(
width: double.infinity,
padding: const EdgeInsets.all(1),
child: Center(
child: Column(
children: [
if (EnvConfig.isDev()) ...[
Text(
'开发版',
style: TextStyle(
color: Colors.grey,
fontSize: 14,
),
),
SizedBox(height: 4),
],
Text(
'V1.0',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
SizedBox(height: 8),
Text(
'粤ICP备2025475184号-15A',
),
SizedBox(height: 8),
Text(
'Copyright © 中山班小二科技有限公司',
),
SizedBox(height: 8),
Text(
'${Constant.appVersion}-${state.h5Version}',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
SizedBox(height: 10),
],
),
),
),
]));
}
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();
},
),
],
);
},
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
router.push('/setting');
},
),
],
);
}
}
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!