584 lines
22 KiB
Dart
584 lines
22 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:provider/provider.dart';
|
||
|
||
import '../../apis/app.dart';
|
||
import '../../components/CustomAlertDialog.dart';
|
||
import '../../components/appbar.dart';
|
||
import '../../providers/auth_provider.dart';
|
||
|
||
class InfoDetailPage extends StatefulWidget {
|
||
final Map<String, dynamic> arguments;
|
||
const InfoDetailPage({
|
||
super.key,
|
||
required this.arguments,
|
||
});
|
||
|
||
@override
|
||
State<InfoDetailPage> createState() => _InfoDetailPageState();
|
||
}
|
||
|
||
class _InfoDetailPageState extends State<InfoDetailPage> with WidgetsBindingObserver {
|
||
// final TextEditingController _commentController = TextEditingController();
|
||
bool _liked = false;
|
||
int _likesCount = 0;
|
||
bool _isFollowed = false;
|
||
bool _isOwnWork = false; // 添加标记是否为自己的作品
|
||
|
||
Map<String, dynamic>? workDetail;
|
||
bool isLoading = true; // 添加加载状态
|
||
String? error; // 添加错误状态
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
print("InfoDetail初始化参数: ${widget.arguments}");
|
||
WidgetsBinding.instance.addObserver(this);
|
||
print('Initial like status: ${widget.arguments['isLiked']}');
|
||
_liked = widget.arguments['isLiked'].toString() == "1";
|
||
print('_liked value: $_liked');
|
||
_likesCount = widget.arguments['likeCount'];
|
||
_fetchWorkDetail();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
final returnData = {
|
||
'workId': widget.arguments['workId'],
|
||
'isLiked': _liked ? "1" : "0",
|
||
'likeCount': _likesCount,
|
||
'isFollowed': _isFollowed,
|
||
'userId': workDetail?['userId'],
|
||
};
|
||
print("InfoDetail返回数据: $returnData");
|
||
|
||
if (Navigator.canPop(context)) {
|
||
Navigator.pop(context, returnData);
|
||
}
|
||
WidgetsBinding.instance.removeObserver(this);
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||
if (state == AppLifecycleState.resumed) {
|
||
// 页面重新获得焦点时刷新数据
|
||
_refreshData();
|
||
}
|
||
}
|
||
|
||
// 添加刷新方法
|
||
Future<void> _refreshData() async {
|
||
if (mounted) {
|
||
await _fetchWorkDetail();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
Future<void> _fetchWorkDetail() async {
|
||
try {
|
||
setState(() {
|
||
isLoading = true;
|
||
error = null;
|
||
});
|
||
|
||
// 获取当前登录用户的ID
|
||
final authProvider = Provider.of<AuthProvider>(context, listen: false);
|
||
final currentUserId = authProvider.userId;
|
||
print("当前登录用户ID: $currentUserId");
|
||
|
||
var result = await userApi.getMyPublishDetail(widget.arguments['workId']);
|
||
// print("更多他人发布详情页面result---------------: $result");
|
||
if (result['code'] == 200) {
|
||
setState(() {
|
||
workDetail = result['data'];
|
||
print("更多他人发布详情页面workDetail---------------: ${workDetail?['userId']}");
|
||
workDetail?['isAddLike'] = _liked ? "1" : "0";
|
||
workDetail?['receiveRockets'] = _likesCount;
|
||
_isFollowed = workDetail?['isFollow'] == "1";
|
||
// 判断是否为自己的作品,确保类型一致后再比较
|
||
print("当前用户ID类型: ${currentUserId.runtimeType}, 值: $currentUserId");
|
||
print("作品用户ID类型: ${workDetail?['userId'].runtimeType}, 值: ${workDetail?['userId']}");
|
||
_isOwnWork = currentUserId.toString() == workDetail?['userId'].toString();
|
||
print("是否为自己的作品: $_isOwnWork, 比较结果: ${currentUserId.toString() == workDetail?['userId'].toString()}");
|
||
isLoading = false;
|
||
});
|
||
} else {
|
||
setState(() {
|
||
error = result['msg'] ?? '获取数据失败';
|
||
isLoading = false;
|
||
});
|
||
}
|
||
} catch (e) {
|
||
setState(() {
|
||
error = '网络请求失败';
|
||
isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
|
||
// 当用户点击关注按钮时
|
||
Future<void> _toggleFollow() async {
|
||
if (workDetail?['userId'] == null) return;
|
||
|
||
try {
|
||
final previousState = _isFollowed;
|
||
setState(() {
|
||
_isFollowed = !_isFollowed;
|
||
workDetail!['isFollow'] = _isFollowed ? "1" : "0";
|
||
});
|
||
|
||
final result = _isFollowed
|
||
? await userApi.addFollow(workDetail!['userId'])
|
||
: await userApi.cancelFollow(workDetail!['userId']);
|
||
|
||
if (result['code'] != 200) {
|
||
setState(() {
|
||
_isFollowed = previousState;
|
||
workDetail!['isFollow'] = previousState ? "1" : "0";
|
||
});
|
||
if (!mounted) return;
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(content: Text(result['msg'] ?? '操作失败')),
|
||
);
|
||
}
|
||
} catch (e) {
|
||
setState(() {
|
||
_isFollowed = !_isFollowed;
|
||
workDetail!['isFollow'] = _isFollowed ? "1" : "0";
|
||
});
|
||
if (!mounted) return;
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('网络请求失败')),
|
||
);
|
||
}
|
||
}
|
||
|
||
|
||
// 当用户点击头像进入OtherMinePage时
|
||
void _navigateToOtherMine() async {
|
||
if (workDetail == null) return;
|
||
|
||
final result = await Navigator.pushNamed(
|
||
context,
|
||
'/otherMine',
|
||
arguments: {
|
||
...workDetail!,
|
||
'isFollow': _isFollowed ? "1" : "0", // 使用当前组件的关注状态
|
||
},
|
||
);
|
||
|
||
// 处理从OtherMinePage返回的结果
|
||
if (result != null && result is Map<String, dynamic>) {
|
||
setState(() {
|
||
_isFollowed = result['isFollowed'];
|
||
workDetail!['isFollow'] = _isFollowed ? "1" : "0";
|
||
});
|
||
}
|
||
}
|
||
|
||
// 当用户点击头像时的处理逻辑
|
||
void _handleAvatarTap() {
|
||
if (_isOwnWork) {
|
||
// 如果是自己的作品,使用pushNamed跳转到个人首页
|
||
Navigator.pushNamed(
|
||
context,
|
||
'/tabs',
|
||
arguments: {'initialIndex': 4},
|
||
);
|
||
} else {
|
||
// 如果是他人的作品,跳转到otherMine页面
|
||
_navigateToOtherMine();
|
||
}
|
||
}
|
||
|
||
// 格式化展示信息
|
||
String _formatSourceDisplay() {
|
||
if (workDetail == null || workDetail!['sourceList'] == null) {
|
||
return "暂无展示信息";
|
||
}
|
||
|
||
List<dynamic> sourceList = workDetail!['sourceList'];
|
||
if (sourceList.isEmpty) {
|
||
return "暂无展示信息";
|
||
}
|
||
|
||
// 按照城市和景区分组
|
||
Map<String, List<dynamic>> groupedSources = {};
|
||
for (var source in sourceList) {
|
||
// 创建基础位置键(城市+景区,不包含part)
|
||
String baseLocation = "${source['city']}${source['scenic']}";
|
||
if (!groupedSources.containsKey(baseLocation)) {
|
||
groupedSources[baseLocation] = [];
|
||
}
|
||
groupedSources[baseLocation]!.add(source);
|
||
}
|
||
|
||
// 格式化每个分组的显示文本
|
||
List<String> displayTexts = groupedSources.entries.map((entry) {
|
||
var sources = entry.value;
|
||
// 获取第一个源的基本信息
|
||
var firstSource = sources.first;
|
||
String baseInfo = "${firstSource['city']}${firstSource['scenic']}";
|
||
|
||
// 收集所有完整坐标(包含part)
|
||
List<String> coordinates =
|
||
sources.map<String>((s) => "${s['part']}${s['coordinate']}").toList();
|
||
|
||
// 获取剩余天数(假设剩余天数相同)
|
||
int rDays = firstSource['rDays'];
|
||
|
||
// 组合最终显示文本
|
||
return "$baseInfo${coordinates.join('、')}展示中,剩余$rDays天";
|
||
}).toList();
|
||
|
||
// 用分号连接不同景区的信息
|
||
return displayTexts.join('; ');
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
// final workItem = workDetail?.isNotEmpty == true ? workDetail![0] : null;
|
||
return Scaffold(
|
||
body: Container(
|
||
color: const Color(0xFF0C0C16),
|
||
child: Column(
|
||
children: [
|
||
Container(
|
||
padding: EdgeInsets.only(
|
||
// 添加状态栏高度的 padding
|
||
top: MediaQuery.of(context).padding.top,
|
||
),
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
IconButton(
|
||
icon: Image.asset(
|
||
'images/arraw.png',
|
||
width: 11,
|
||
height: 22,
|
||
fit: BoxFit.cover,
|
||
),
|
||
onPressed: () {
|
||
// 返回上一页
|
||
Navigator.pop(context);
|
||
},
|
||
),
|
||
// IconButton(
|
||
// icon: Image.asset(
|
||
// 'images/share.png',
|
||
// width: 19,
|
||
// height: 19,
|
||
// fit: BoxFit.cover,
|
||
// ),
|
||
// onPressed: () {
|
||
// // 分享操作
|
||
// },
|
||
// ),
|
||
]),
|
||
),
|
||
Expanded(
|
||
child: ListView(
|
||
padding: EdgeInsets.zero,
|
||
children: [
|
||
Stack(
|
||
children: [
|
||
Image.network(
|
||
workDetail?['workAddress'] ?? '',
|
||
width: MediaQuery.of(context).size.width,
|
||
height: MediaQuery.of(context).size.height * 0.55,
|
||
fit: BoxFit.cover,
|
||
errorBuilder: (context, error, stackTrace) {
|
||
return Container(
|
||
width: MediaQuery.of(context).size.width,
|
||
height: MediaQuery.of(context).size.height * 0.55,
|
||
color: Colors.grey[900],
|
||
child: const Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Icon(
|
||
Icons.broken_image,
|
||
color: Colors.white54,
|
||
size: 48,
|
||
),
|
||
SizedBox(height: 8),
|
||
Text(
|
||
'图片加载失败',
|
||
style: TextStyle(
|
||
color: Colors.white54,
|
||
fontSize: 14,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
},
|
||
),
|
||
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(
|
||
bottom: 5,
|
||
left: 16,
|
||
child: Text(
|
||
workDetail?['workName'] ?? '',
|
||
style: const TextStyle(
|
||
color: Colors.white,
|
||
fontSize: 22,
|
||
fontWeight: FontWeight.bold),
|
||
))
|
||
],
|
||
),
|
||
Container(
|
||
padding: const EdgeInsets.all(20),
|
||
// color: Colors.grey[200],
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
GestureDetector(
|
||
onTap: _handleAvatarTap,
|
||
child: Row(
|
||
children: [
|
||
Container(
|
||
width: 50,
|
||
height: 50,
|
||
decoration: BoxDecoration(
|
||
shape: BoxShape.circle,
|
||
color: const Color(0xFF2C2C2C),
|
||
image: workDetail?['avatar'] != null &&
|
||
workDetail!['avatar'].toString().isNotEmpty
|
||
? DecorationImage(
|
||
image: NetworkImage(workDetail!['avatar']),
|
||
fit: BoxFit.cover,
|
||
)
|
||
: null,
|
||
),
|
||
child: workDetail?['avatar'] == null ||
|
||
workDetail!['avatar'].toString().isEmpty
|
||
? const Center(
|
||
child: Icon(
|
||
Icons.person,
|
||
color: Colors.white54,
|
||
size: 30,
|
||
),
|
||
)
|
||
: null,
|
||
),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
workDetail?['nickName'] ?? '',
|
||
style: const TextStyle(
|
||
fontSize: 20,
|
||
color: Color.fromRGBO(255, 255, 255, 0.8),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
// 只有不是自己的作品时才显示关注按钮
|
||
if (!_isOwnWork)
|
||
TextButton(
|
||
onPressed: _toggleFollow,
|
||
style: ButtonStyle(
|
||
side: MaterialStateProperty.all(
|
||
BorderSide(
|
||
color: _isFollowed
|
||
? Colors.grey
|
||
: const Color(0xffF42845),
|
||
width: 0.67,
|
||
),
|
||
),
|
||
backgroundColor: MaterialStateProperty.all(
|
||
_isFollowed
|
||
? Colors.transparent
|
||
: const Color(0xffF42845),
|
||
),
|
||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||
minimumSize: MaterialStateProperty.all(const Size(65, 25)),
|
||
maximumSize: MaterialStateProperty.all(const Size(65, 25)),
|
||
fixedSize: MaterialStateProperty.all(const Size(65, 25)),
|
||
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||
RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(20),
|
||
),
|
||
),
|
||
),
|
||
child: Text(
|
||
_isFollowed ? '已关注' : '关注',
|
||
style: TextStyle(
|
||
color: _isFollowed ? Colors.grey : Colors.white,
|
||
fontSize: 12,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 10),
|
||
Container(
|
||
constraints: BoxConstraints(
|
||
maxHeight: MediaQuery.of(context).size.height * 0.3, // 设置最大高度
|
||
),
|
||
child: SingleChildScrollView(
|
||
child: Text(
|
||
workDetail?['detail'] ?? '',
|
||
style: const TextStyle(
|
||
fontSize: 16,
|
||
color: Color.fromRGBO(255, 255, 255, 0.8),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(
|
||
height: 10,
|
||
),
|
||
Text(
|
||
workDetail?['createTime']
|
||
?.toString()
|
||
.substring(0, 10) ??
|
||
'',
|
||
style: const TextStyle(
|
||
fontSize: 10, color: Color(0xffD6D7DC))),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
Container(
|
||
width: double.infinity,
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 16,
|
||
vertical: 10,
|
||
),
|
||
decoration: BoxDecoration(
|
||
border: Border(
|
||
top: BorderSide(color: Colors.white.withOpacity(0.3)),
|
||
),
|
||
),
|
||
child: Row(
|
||
children: [
|
||
Expanded(
|
||
child: SingleChildScrollView(
|
||
scrollDirection: Axis.horizontal,
|
||
physics: const BouncingScrollPhysics(), // 添加弹性滚动效果,提高用户体验
|
||
child: Text(
|
||
_formatSourceDisplay(),
|
||
// 移除 overflow: TextOverflow.ellipsis, 允许文本完整显示
|
||
style: const TextStyle(
|
||
color: Color(0xff78E7A4),
|
||
fontSize: 10,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
// Expanded(
|
||
// child: Text(
|
||
// _formatSourceDisplay(),
|
||
// // overflow: TextOverflow.ellipsis,
|
||
// style: const TextStyle(
|
||
// color: Color(0xff78E7A4),
|
||
// fontSize: 10,
|
||
// ),
|
||
// ),
|
||
// ),
|
||
const SizedBox(width: 8),
|
||
Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
IconButton(
|
||
constraints: const BoxConstraints(
|
||
minWidth: 36,
|
||
minHeight: 36,
|
||
),
|
||
padding: EdgeInsets.zero,
|
||
icon: Image.asset(
|
||
'images/upvote.png',
|
||
width: 21,
|
||
height: 20,
|
||
fit: BoxFit.contain,
|
||
color: _liked
|
||
? const Color(0xffEE7371)
|
||
: const Color(0xffC1C1C1),
|
||
),
|
||
onPressed: () async {
|
||
try {
|
||
var result;
|
||
if (_liked) {
|
||
// 如果已点赞,则取消点赞
|
||
result = await userApi.getCancelLikeWork(
|
||
widget.arguments['workId']);
|
||
} else {
|
||
// 如果未点赞,则添加点赞
|
||
result = await userApi
|
||
.getLikeWork(widget.arguments['workId']);
|
||
}
|
||
|
||
if (result['code'] == 200) {
|
||
setState(() {
|
||
_liked = !_liked;
|
||
_likesCount += _liked ? 1 : -1;
|
||
if (workDetail != null) {
|
||
workDetail!['isAddLike'] = _liked ? "1" : "0";
|
||
workDetail!['receiveRockets'] = _likesCount;
|
||
}
|
||
});
|
||
} else {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Text(result['msg'] ?? '操作失败')),
|
||
);
|
||
}
|
||
} catch (e) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
const SnackBar(content: Text('网络请求失败')),
|
||
);
|
||
}
|
||
},
|
||
style: ButtonStyle(
|
||
padding: MaterialStateProperty.all<EdgeInsets>(
|
||
const EdgeInsets.all(5)),
|
||
minimumSize:
|
||
MaterialStateProperty.all<Size>(const Size(0, 0)),
|
||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||
),
|
||
iconSize: 30,
|
||
),
|
||
const SizedBox(width: 4),
|
||
Text(
|
||
_likesCount.toString(),
|
||
style: TextStyle(
|
||
color: _liked ? const Color(0xffEE7371) : const Color(0xffC1C1C1),
|
||
fontSize: 14,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|