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

460 lines
14 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 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../apis/app.dart';
import '../../components/appbar.dart';
import '../../components/cached_image.dart';
import '../../providers/auth_provider.dart';
class MorePage extends StatefulWidget {
const MorePage({super.key});
@override
State<MorePage> createState() => _MorePageState();
}
// WidgetsBindingObserver mixin 来监听页面生命周期。
class _MorePageState extends State<MorePage> with WidgetsBindingObserver {
// Map来存储每个item的固定高度
final Map<String, double> _itemHeights = {};
List _waterFallList = [];
List<dynamic> _workList = [];
int countNum = 0;
int _currentPage = 1;
String? _userId;
bool _liked = false;
int _likesCount = 0;
bool _isLoading = false;
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
var randomNum = Random();
for (var i = 0; i < 20; i++) {
_waterFallList.add(230 + 28 * randomNum.nextDouble());
}
print(_waterFallList);
WidgetsBinding.instance.addObserver(this);
_fetchWorks();
// 滚动监听
_scrollController.addListener(_onScroll);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_fetchWorks();
}
}
//页面重新获得焦点时刷新数据
Future<void> _onPageResume() async {
if (mounted) {
await _fetchWorks();
}
}
void _onScroll() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_loadMore();
}
}
Future<void> _loadMore() async {
// 检查是否正在加载和是否还有更多数据
if (!_isLoading && _workList.length < countNum) {
await _fetchWorks(page: _currentPage + 1);
}
}
Future<void> _fetchWorks({int page = 1}) async {
if (_isLoading) return;
setState(() {
_isLoading = true;
});
try {
// 使用 AuthProvider 获取登录状态
final authProvider = Provider.of<AuthProvider>(context, listen: false);
// 先加载token确保登录状态是最新的
await authProvider.loadTokenFromPrefs();
final bool isLoggedIn = authProvider.isLoggedIn;
final works = await userApi.getMoreWork(
page: page,
pageSize: 10,
requiresToken: isLoggedIn,
);
if (works['code'] == 200) {
if (mounted) {
// 获取作品列表后,遍历获取每个作者的关注状态
final List newWorkList = List.from(works['rows']);
print("newWorkList----------,${newWorkList}");
if (isLoggedIn) {
for (var work in newWorkList) {
try {
final userResponse = await userApi.getOtherPublish(work['userId'].toString());
if (userResponse['code'] == 200) {
work['isFollow'] = userResponse['data']['isFollow'];
// print("##############################userResponse['data'],${userResponse['data']}");
}
} catch (e) {
print('获取用户${work['userId']}的关注状态失败: $e');
}
}
}
setState(() {
if (page == 1) {
_workList = newWorkList;
} else {
_workList.addAll(newWorkList);
}
countNum = works['total'];
_currentPage = page;
});
// 确保最新点赞状态同步到本地存储
if (isLoggedIn) {
_syncLikedWorksToPrefs();
}
}
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('加载失败,请稍后重试')),
);
}
} finally {
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
}
// 同步点赞状态到本地存储
Future<void> _syncLikedWorksToPrefs() async {
try {
final prefs = await SharedPreferences.getInstance();
final likedWorkIds = _workList
.where((work) => work['isAddLike']?.toString() == '1')
.map((work) => work['workId'].toString())
.toList();
await prefs.setStringList('likedWorks', likedWorkIds);
} catch (e) {
print('同步点赞状态失败: $e');
}
}
Future<void> _navigateToDetail(Map<String, dynamic> work) async {
if (!mounted) return;
final authProvider = Provider.of<AuthProvider>(context, listen: false);
if (!authProvider.isLoggedIn) {
await Navigator.pushNamed(context, '/login');
return;
}
final result = await Navigator.pushNamed(
context,
"/infoDetail",
arguments: {
'workId': work['workId'],
'isLiked': work['isAddLike'],
'likeCount': work['receiveRockets'],
},
);
if (result != null && result is Map<String, dynamic>) {
setState(() {
final index = _workList.indexWhere((item) => item['workId'] == work['workId']);
if (index != -1) {
_workList[index]['isAddLike'] = result['isLiked'];
_workList[index]['receiveRockets'] = result['likeCount'];
}
});
}
}
Future<void> _handleAvatarTap(Map<String, dynamic> work) async {
final authProvider = Provider.of<AuthProvider>(context, listen: false);
final currentUserId = authProvider.userId;
if (currentUserId.toString() == work['userId'].toString()) {
Navigator.pushNamed(
context,
'/tabs',
arguments: {'initialIndex': 4},
);
} else {
final result = await Navigator.pushNamed(
context,
'/otherMine',
arguments: {
...work, // 展开所有现有属性
'userId': work['userId'],
'nickName': work['nickName'] ?? '未知用户',
'avatar': work['avatar'] ?? '',
'isFollow': work['isFollow'] ?? '0',
'workAddress': work['workAddress'] ?? '',
'workName': work['workName'] ?? '',
'receiveRockets': work['receiveRockets'] ?? 0,
'isAddLike': work['isAddLike'] ?? '0',
},
);
if (result != null && result is Map<String, dynamic>) {
setState(() {
// 更新列表中对应项的关注状态
final index = _workList.indexWhere(
(item) => item['userId'] == result['userId']);
if (index != -1) {
_workList[index]['isFollow'] = result['isFollowed'] ? "1" : "0";
}
});
}
}
}
Future<void> _handleLikeInMore(Map<String, dynamic> work) async {
if (!mounted) return;
try {
final response = work['isAddLike'].toString() == "1"
? await userApi.getCancelLikeWork(work['workId'])
: await userApi.getLikeWork(work['workId']);
if (!mounted) return;
if (response['code'] == 200) {
setState(() {
work['isAddLike'] = work['isAddLike'].toString() == "1" ? "0" : "1";
work['receiveRockets'] = work['isAddLike'].toString() == "1"
? work['receiveRockets'] + 1
: work['receiveRockets'] - 1;
});
// 更新SharedPreferences中的点赞状态
await _syncLikedWorksToPrefs();
} else {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(response['msg'] ?? '操作失败'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('网络错误,请稍后重试'),
backgroundColor: Colors.red,
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: const CustomAppBar(title: ''),
backgroundColor: Colors.black,
body: RefreshIndicator(
onRefresh: () => _fetchWorks(page: 1),
child: Padding(
padding: const EdgeInsets.all(10),
child: ListView(
controller: _scrollController,
children: [
MasonryGridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 2,
itemCount: _workList.length,
itemBuilder: (BuildContext context, int index) {
return picCard(_workList[index]);
},
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
if (_workList.isNotEmpty)
Container(
padding: const EdgeInsets.symmetric(vertical: 16),
alignment: Alignment.center,
child: _workList.length < countNum
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2.0,
color: Colors.white,
),
)
: const Text(
'已经到底啦',
style: TextStyle(
color: Colors.grey,
fontSize: 14,
),
),
),
],
),
),
),
);
}
Widget picCard(Map<String, dynamic> work) {
// 使用workId作为key来获取或生成固定高度
final double itemHeight = _itemHeights.putIfAbsent(
work['workId'].toString(),
() => 230 + Random().nextDouble() * 28,
);
String isLiked = work['isAddLike'].toString();
return GestureDetector(
onTap: () => _navigateToDetail(work),
child: Container(
height: itemHeight,
child: Stack(
children: [
CachedImage(
imageUrl: work['workAddress'],
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
borderRadius: BorderRadius.circular(10),
),
Positioned(
left: 5,
top: 5,
child: GestureDetector(
onTap: () => _handleAvatarTap(work),
child: Row(
children: [
Container(
width: 24,
height: 24,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: const Color(0xFF2C2C2C),
),
child: ClipOval(
child: work['avatar'] != null && work['avatar'].toString().isNotEmpty
? CachedImage(
imageUrl: work['avatar'],
width: 24,
height: 24,
fit: BoxFit.cover,
)
: const Center(
child: Icon(
Icons.person,
color: Colors.white54,
size: 12,
),
),
),
),
const SizedBox(width: 5),
Text(
work['nickName'],
style: const TextStyle(color: Colors.white, fontSize: 12),
),
],
),
),
),
// 渐变背景
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 80,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black.withOpacity(0.8),
],
),
),
),
),
// 作品信息和点赞按钮
Positioned(
left: 5,
bottom: 8,
right: 5,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
work['workName'],
style:
const TextStyle(color: Colors.white, fontSize: 14),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
Row(
children: [
GestureDetector(
onTap: () => _handleLikeInMore(work),
child: Image.asset(
'images/upvote.png',
width: 18,
height: 18,
fit: BoxFit.contain,
color: work['isAddLike'].toString() == "1"
? const Color(0xffEE7371)
: const Color(0xffC1C1C1),
),
),
const SizedBox(width: 5),
Text(
work['receiveRockets'].toString(),
style: TextStyle(
color: work['isAddLike'].toString() == "1"
? const Color(0xffEE7371)
: Colors.white,
),
),
],
),
],
),
),
],
),
));
}
}