ar_tourism_flutter_unity/lib/pages/tabs/tabs.dart
2025-05-14 17:04:13 +08:00

538 lines
16 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import '../../components/CustomAlertDialog.dart';
import '../center/centerPage.dart';
import '../home/homePage.dart';
import '../mine/setting/privacy_policy.dart';
import '../mine/setting/user_manual.dart';
import '../publish/publish.dart';
import '../message/message.dart';
import '../mine/mine.dart';
import 'package:flutter/gestures.dart';
// Tabs组件抽离
class Tabs extends StatefulWidget {
final int initialIndex; //接收参数
const Tabs({super.key, this.initialIndex = 0});
@override
State<Tabs> createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
int _currentIndex = 0;
AssetEntity? selectedAsset;
int _unreadMessageCount = 0;
// 需要登录验证的页面索引
final Set<int> _authRequiredIndices = {1, 2, 3, 4}; // 除了首页(0)外都需要登录
// 添加一个key来标识CenterPage
final GlobalKey<CenterPageState> centerPageKey = GlobalKey<CenterPageState>();
Future<bool> _checkLoginStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final isLoggedIn = prefs.getBool('isLoggedIn') ?? false;
final token = prefs.getString('token');
return isLoggedIn && token != null;
}
// 添加检查实名认证状态的方法
Future<bool> _checkRealNameStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool('isRealNameAuth') ?? false;
}
// 显示实名认证提示对话框
void _showRealNameDialog() {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CustomAlertDialog(
title: '实名认证提示',
content: '为了保护您的合法权益,请先进行实名认证',
confirmText: '去实名',
cancelText: '取消',
onConfirm: () {
Navigator.of(context).pop();
Navigator.pushNamed(context, '/realName');
},
);
},
);
}
// 添加一个新方法来显示用户协议弹窗
Future<bool> _showAgreementDialog() async {
bool? result = await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CustomAlertDialog(
title: '温馨提示',
content: '',
contentWidget: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: const TextStyle(color: Colors.white54, fontSize: 14),
children: [
const TextSpan(text: '如您同意并接受'),
TextSpan(
text: '《用户协议》',
style: const TextStyle(color: Color(0xFF7cd3ba)),
recognizer: TapGestureRecognizer()
..onTap = () {
// 先关闭当前对话框
Navigator.of(context).pop(false);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const UserManualPage()),
);
},
),
const TextSpan(text: ''),
TextSpan(
text: '《隐私政策》',
style: const TextStyle(color: Color(0xFF7cd3ba)),
recognizer: TapGestureRecognizer()
..onTap = () {
// 先关闭当前对话框
Navigator.of(context).pop(false);
// 跳转到隐私政策页面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const PrivacyPolicyPage()),
);
},
),
const TextSpan(text: '全部条款后,可使用完整功能'),
],
),
),
onConfirm: () {
Navigator.of(context).pop(true); // 用户同意
},
onCancel: () {
Navigator.of(context).pop(false); // 用户不同意
},
confirmText: '同意并继续',
cancelText: '不同意',
);
},
);
return result ?? false;
}
Future<void> _handleCenterTap() async {
// 同时请求相机和相册权限
final statuses = await [
Permission.camera,
Permission.photos, // iOS相册权限
Permission.storage, // Android存储权限
].request();
// 检查所有权限是否已授予
final allGranted = statuses[Permission.camera]?.isGranted == true &&
(statuses[Permission.photos]?.isGranted == true ||
statuses[Permission.storage]?.isGranted == true);
if (!allGranted) {
if (mounted) {
showDialog(
context: context,
builder: (context) => CustomAlertDialog(
title: '需要权限授权',
content: '请允许访问相机和相册权限以继续操作',
confirmText: '去设置',
onConfirm: () => openAppSettings(),
cancelText: '取消',
),
);
}
return;
}
bool isLoggedIn = await _checkLoginStatus();
if (!isLoggedIn) {
if (mounted) {
// 先显示协议弹窗
bool agreed = await _showAgreementDialog();
if (!agreed) {
// 用户不同意,跳转到首页
setState(() {
_currentIndex = 0;
});
return;
}
// 用户同意,跳转到登录页
final result = await Navigator.pushNamed(context, '/login');
if (result == true) {
// 检查实名认证状态
bool isRealNameAuth = await _checkRealNameStatus();
if (!isRealNameAuth) {
if (mounted) {
_showRealNameDialog();
}
return;
}
// 已登录且已实名认证,直接打开相册选择器
await _openAssetPicker();
}
}
return;
}
// 已登录,检查实名认证状态
bool isRealNameAuth = await _checkRealNameStatus();
if (!isRealNameAuth) {
if (mounted) {
_showRealNameDialog();
}
return;
}
// 已登录且已实名认证,直接打开相册选择器
await _openAssetPicker();
}
// Future<void> _handleCenterTap() async {
// bool isLoggedIn = await _checkLoginStatus();
// if (!isLoggedIn) {
// if (mounted) {
// final result = await Navigator.pushNamed(context, '/login');
// if (result == true) {
// // 检查实名认证状态
// bool isRealNameAuth = await _checkRealNameStatus();
// if (!isRealNameAuth) {
// if (mounted) {
// _showRealNameDialog();
// }
// return;
// }
// // 已登录且已实名认证先设置当前索引为2CenterPage
// setState(() {
// _currentIndex = 2;
// });
// await _openAssetPicker(); // 打开相册选择器
// }
// }
// return;
// }
// // 已登录,检查实名认证状态
// bool isRealNameAuth = await _checkRealNameStatus();
// if (!isRealNameAuth) {
// if (mounted) {
// _showRealNameDialog();
// }
// return;
// }
// // 已登录且已实名认证先设置当前索引为2CenterPage
// setState(() {
// _currentIndex = 2;
// });
// await _openAssetPicker(); // 打开相册选择器
// }
// 修改现有的 _handleTabChange 方法
Future<void> _handleTabChange(int index) async {
if (_authRequiredIndices.contains(index)) {
bool isLoggedIn = await _checkLoginStatus();
if (!isLoggedIn) {
if (mounted) {
// 先显示协议弹窗
bool agreed = await _showAgreementDialog();
if (!agreed) {
// 用户不同意,保持在首页
setState(() {
_currentIndex = 0;
});
return;
}
// 用户同意,跳转到登录页
final result = await Navigator.pushNamed(context, '/login');
if (result == true && mounted) {
// 如果是发布页面index == 1需要检查实名认证
if (index == 1) {
bool isRealNameAuth = await _checkRealNameStatus();
if (!isRealNameAuth) {
_showRealNameDialog();
return;
}
}
setState(() {
_currentIndex = index;
});
}
return;
}
return;
}
// 已登录,如果是发布页面需要检查实名认证
if (index == 1) {
bool isRealNameAuth = await _checkRealNameStatus();
if (!isRealNameAuth) {
if (mounted) {
_showRealNameDialog();
}
return;
}
}
}
setState(() {
_currentIndex = index;
});
}
// 将页面列表改为getter方法动态创建页面实例
List<Widget> get _pages => [
const HomePage(),
const PublishPage(),
CenterPage(
key: centerPageKey,
selectedAsset: selectedAsset,
), // 将selectedAsset传递给CenterPage
const MessagePage(),
const MinePage(),
];
@override
void initState() {
super.initState();
_currentIndex = widget.initialIndex;
_loadUnreadMessageCount();
// 添加监听器以定期更新未读消息数
_startMessageCountTimer();
// 延迟执行以确保页面已完全加载
WidgetsBinding.instance.addPostFrameCallback((_) {
final arguments = ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>?;
// 检查是否有打开相册选择器的标记
if (arguments != null && arguments['openAssetPicker'] == true) {
// 先设置当前索引为2确保显示CenterPage再打开相册选择器
setState(() {
_currentIndex = 2;
});
_openAssetPicker(); // 自动打开相册选择器
}
// 原有的showMessage处理逻辑
if (arguments != null && arguments['showMessage'] != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
arguments['showMessage'],
style: const TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
backgroundColor: const Color(0xFF1A1A29),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).size.height - 100,
left: 20,
right: 20,
),
),
);
}
});
}
// 加载未读消息数
Future<void> _loadUnreadMessageCount() async {
final prefs = await SharedPreferences.getInstance();
if (mounted) {
setState(() {
_unreadMessageCount = prefs.getInt('unreadMessageCount') ?? 0;
});
}
}
// 定期更新未读消息数
void _startMessageCountTimer() {
Future.delayed(const Duration(seconds: 5), () {
if (mounted) {
_loadUnreadMessageCount();
_startMessageCountTimer();
}
});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: _pages[_currentIndex],
bottomNavigationBar: Container(
height: 60,
color: const Color(0xff0C0C16),
child: Stack(
children: [
// 背景图片
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
margin: const EdgeInsets.symmetric(
vertical: 5,
horizontal: 8,
),
padding: const EdgeInsets.all(5),
height: 50,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('images/bg.png'),
fit: BoxFit.fill,
),
),
),
),
// 导航栏
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildNavItem(0, "images/homePage.png", "images/homePage_active.png", "MR"),
_buildNavItem(1, "images/recommed.png", "images/recommend_active.png", "发布"),
// 中间按钮
Container(
width: 60,
height: 60,
alignment: Alignment.center,
child: GestureDetector(
onTap: _handleCenterTap,
onLongPress: _handleCenterTap,
child: Container(
width: 36,
height: 36,
decoration: const BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [Color(0xff80DAA4), Color(0xff79DDED)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
boxShadow: [
BoxShadow(
color: Color(0x40000000),
blurRadius: 4,
offset: Offset(0, 2),
),
],
),
child: const Icon(
Icons.add,
color: Colors.white,
size: 22,
),
),
),
),
_buildNavItem(3, "images/car.png", "images/car_active.png", "消息"),
_buildNavItem(4, "images/mine.png", "images/mine_active.png", "我的"),
],
),
],
),
),
);
}
Widget _buildNavItem(int index, String icon, String activeIcon, String label) {
final bool isSelected = _currentIndex == index;
return GestureDetector(
onTap: () => _handleTabChange(index),
behavior: HitTestBehavior.opaque,
child: Container(
width: 60,
height: 60,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
isSelected ? activeIcon : icon,
width: 20,
height: 20,
),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(
fontSize: 10,
color: isSelected ? const Color(0xff79DDED) : Colors.white,
),
),
],
),
),
);
}
Future<void> _openAssetPicker() async {
final List<AssetEntity>? result = await AssetPicker.pickAssets(
context,
pickerConfig: const AssetPickerConfig(
maxAssets: 1,
requestType: RequestType.image, // 限制只能选择图片
themeColor: Color(0xff7CDBC8), // 设置主题色
textDelegate: AssetPickerTextDelegate(), // 使用中文本地化
specialItemPosition: SpecialItemPosition.none, // 移除特殊项
specialItemBuilder: null,
shouldRevertGrid: false,
gridCount: 4,
pathThumbnailSize: ThumbnailSize.square(80),
),
);
if (result != null && result.isNotEmpty && mounted) {
// 先更新资源
setState(() {
selectedAsset = result.first;
});
// 选择完图片后直接切换到CenterPage
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
_currentIndex = 2;
});
// 延迟更新CenterPage的状态
Future.microtask(() {
if (centerPageKey.currentState != null) {
centerPageKey.currentState!.updateSelectedAsset(selectedAsset);
}
});
}
});
}
}
}