745 lines
29 KiB
Dart
745 lines
29 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:share_plus/share_plus.dart';
|
||
import 'package:shared_preferences/shared_preferences.dart';
|
||
|
||
import '../../apis/app.dart';
|
||
import '../../components/emptyState.dart';
|
||
import '../../components/workGrid.dart';
|
||
import 'authInfo.dart';
|
||
|
||
// 添加 WorkItem 类定义
|
||
class WorkItem {
|
||
final String imageUrl;
|
||
final String title;
|
||
final String count;
|
||
final int workId;
|
||
final bool showUpvote;
|
||
final String isAddLike; // 添加点赞状态字段
|
||
|
||
const WorkItem({
|
||
required this.imageUrl,
|
||
required this.title,
|
||
this.count = '0',
|
||
required this.workId,
|
||
this.showUpvote = true,
|
||
this.isAddLike = '0',
|
||
});
|
||
|
||
factory WorkItem.fromJson(Map<String, dynamic> json) {
|
||
return WorkItem(
|
||
imageUrl: json['workAddress']?.toString() ?? '',
|
||
title: json['workName']?.toString() ?? '',
|
||
count: json['receiveRockets']?.toString() ?? '0',
|
||
workId: json['workId'] ?? 0,
|
||
isAddLike: json['isAddLike']?.toString() ?? '0',
|
||
);
|
||
}
|
||
}
|
||
|
||
class MinePage extends StatefulWidget {
|
||
const MinePage({super.key});
|
||
|
||
@override
|
||
State<MinePage> createState() => _MinePageState();
|
||
}
|
||
|
||
class _MinePageState extends State<MinePage> {
|
||
late List<WorkItem> publishedWorks = [];
|
||
String storedPhone = '';
|
||
bool isLoading = true;
|
||
String? error;
|
||
|
||
Map<String, dynamic> userInfo = {
|
||
'avatar': null,
|
||
'nickName': '',
|
||
'signature': '',
|
||
};
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_loadUserData();
|
||
}
|
||
|
||
Future<void> _loadUserData() async {
|
||
try {
|
||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
storedPhone = prefs.getString('phone') ?? '';
|
||
|
||
final result = await userApi.getSetting(storedPhone);
|
||
if (result['code'] == 200) {
|
||
if (mounted) {
|
||
setState(() {
|
||
userInfo = result;
|
||
isLoading = false;
|
||
});
|
||
getPublishedWorks();
|
||
}
|
||
}
|
||
} catch (e) {
|
||
if (mounted) {
|
||
setState(() {
|
||
error = '获取用户数据失败';
|
||
isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
// 分享内容
|
||
void shareContent() {
|
||
final box = context.findRenderObject() as RenderBox;
|
||
String contentToShare = '这是我想分享的内容';
|
||
Share.share(
|
||
contentToShare,
|
||
subject: "分享主题",
|
||
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size,
|
||
);
|
||
}
|
||
|
||
// 获取我的发布作品
|
||
Future<void> getPublishedWorks() async {
|
||
try {
|
||
setState(() {
|
||
isLoading = true;
|
||
error = null;
|
||
});
|
||
|
||
final result = await userApi.getMyPublish();
|
||
if (result['code'] == 200) {
|
||
final List<dynamic> data = result['data'] ?? [];
|
||
|
||
// 直接使用服务器返回的点赞状态,而不是依赖本地存储
|
||
setState(() {
|
||
publishedWorks = data.map((item) {
|
||
return WorkItem(
|
||
workId: item['workId'] ?? '',
|
||
imageUrl: item['workAddress'] ?? '',
|
||
title: item['workName'] ?? '',
|
||
count: (item['receiveRockets'] ?? 0).toString(),
|
||
isAddLike: item['isAddLike']?.toString() ?? '0',
|
||
);
|
||
}).toList();
|
||
});
|
||
|
||
// 同步更新SharedPreferences中的点赞状态
|
||
_syncLikedWorksToPrefs();
|
||
} else {
|
||
setState(() {
|
||
error = result['msg'] ?? '未知错误';
|
||
});
|
||
}
|
||
} catch (e) {
|
||
setState(() {
|
||
error = '获取数据失败';
|
||
});
|
||
} finally {
|
||
setState(() {
|
||
isLoading = false;
|
||
});
|
||
}
|
||
}
|
||
|
||
// 同步点赞状态到本地存储
|
||
Future<void> _syncLikedWorksToPrefs() async {
|
||
try {
|
||
final prefs = await SharedPreferences.getInstance();
|
||
final likedWorkIds = publishedWorks
|
||
.where((work) => work.isAddLike == '1')
|
||
.map((work) => work.workId.toString())
|
||
.toList();
|
||
|
||
await prefs.setStringList('likedWorks', likedWorkIds);
|
||
} catch (e) {
|
||
print('同步点赞状态失败: $e');
|
||
}
|
||
}
|
||
|
||
String _truncateText(String text, int maxLength, int maxLines) {
|
||
if (text.isEmpty) return text;
|
||
|
||
final List<String> lines = [];
|
||
int startIndex = 0;
|
||
int currentLine = 0;
|
||
|
||
while (startIndex < text.length && currentLine < maxLines) {
|
||
int endIndex = startIndex + maxLength;
|
||
if (endIndex >= text.length) {
|
||
lines.add(text.substring(startIndex));
|
||
break;
|
||
}
|
||
lines.add(
|
||
'${text.substring(startIndex, endIndex)}${currentLine < maxLines - 1 ? '' : '...'}');
|
||
startIndex = endIndex;
|
||
currentLine++;
|
||
}
|
||
|
||
return lines.join('\n');
|
||
}
|
||
|
||
Future<void> handleLike(int index) async {
|
||
final workId = publishedWorks[index].workId;
|
||
final isLiked = publishedWorks[index].isAddLike == '1';
|
||
|
||
try {
|
||
final response = isLiked
|
||
? await userApi.getCancelLikeWork(workId)
|
||
: await userApi.getLikeWork(workId);
|
||
|
||
if (response['code'] == 200) {
|
||
// 更新当前页面状态
|
||
setState(() {
|
||
final updatedItems = List<WorkItem>.from(publishedWorks);
|
||
updatedItems[index] = WorkItem(
|
||
workId: publishedWorks[index].workId,
|
||
imageUrl: publishedWorks[index].imageUrl,
|
||
title: publishedWorks[index].title,
|
||
count: isLiked
|
||
? (int.parse(publishedWorks[index].count) - 1).toString()
|
||
: (int.parse(publishedWorks[index].count) + 1).toString(),
|
||
isAddLike: isLiked ? '0' : '1',
|
||
);
|
||
publishedWorks = updatedItems;
|
||
});
|
||
|
||
// 更新SharedPreferences中的点赞状态
|
||
await _syncLikedWorksToPrefs();
|
||
} else {
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Text(response['msg'] ?? '操作失败'),
|
||
backgroundColor: Colors.red,
|
||
),
|
||
);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Text('操作失败: $e'),
|
||
backgroundColor: Colors.red,
|
||
),
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
Widget _buildStatItem(
|
||
BuildContext context,
|
||
String label,
|
||
String count,
|
||
VoidCallback onTap,
|
||
) {
|
||
return GestureDetector(
|
||
onTap: onTap,
|
||
child: Column(
|
||
children: [
|
||
Text(
|
||
count,
|
||
style: const TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
const SizedBox(height: 4),
|
||
Text(
|
||
label,
|
||
style: const TextStyle(
|
||
fontSize: 12,
|
||
color: Color(0xffc1c1c1),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
// if (isLoading) {
|
||
// return const Scaffold(
|
||
// body: Center(
|
||
// child: CircularProgressIndicator(),
|
||
// ),
|
||
// );
|
||
// }
|
||
|
||
// 如果未登录,返回空页面(防止闪现)
|
||
// if (!isLoggedIn) {
|
||
// return const SizedBox.shrink();
|
||
// }
|
||
|
||
return Scaffold(
|
||
body: Container(
|
||
width: double.infinity,
|
||
color: const Color(0xff0C0C16),
|
||
child: Stack(
|
||
children: [
|
||
Positioned(
|
||
top: 0,
|
||
left: 0,
|
||
child: GestureDetector(
|
||
onTap: () {
|
||
Navigator.pushNamed(
|
||
context,
|
||
"/change",
|
||
arguments: userInfo['background'],
|
||
);
|
||
},
|
||
child: Container(
|
||
width: MediaQuery.of(context).size.width,
|
||
height: 230,
|
||
decoration: BoxDecoration(
|
||
image: DecorationImage(
|
||
image: NetworkImage(
|
||
userInfo['background'] ?? 'images/detail_bg.png',
|
||
),
|
||
fit: BoxFit.fill,
|
||
),
|
||
),
|
||
child: Column(
|
||
children: [
|
||
Container(
|
||
padding: const EdgeInsets.only(top: 45, right: 10),
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.end,
|
||
children: [
|
||
// IconButton(
|
||
// padding: EdgeInsets.zero,
|
||
// constraints: const BoxConstraints(),
|
||
// icon: Image.asset(
|
||
// 'images/share.png',
|
||
// width: 19,
|
||
// height: 19,
|
||
// fit: BoxFit.cover,
|
||
// ),
|
||
// onPressed: shareContent,
|
||
// ),
|
||
SizedBox(
|
||
height: 20,
|
||
)
|
||
],
|
||
),
|
||
),
|
||
Container(
|
||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||
child: Column(
|
||
children: [
|
||
Row(
|
||
children: [
|
||
GestureDetector(
|
||
onTap: () {
|
||
Navigator.pushNamed(
|
||
context,
|
||
'/myInfo',
|
||
arguments: userInfo,
|
||
);
|
||
},
|
||
child: CircleAvatar(
|
||
radius: 42,
|
||
backgroundImage:
|
||
(userInfo['avatar'] == null ||
|
||
userInfo['avatar']
|
||
.toString()
|
||
.isEmpty)
|
||
? const AssetImage(
|
||
'images/default_avatar.png')
|
||
: NetworkImage(userInfo['avatar'])
|
||
as ImageProvider,
|
||
),
|
||
),
|
||
const SizedBox(width: 16.0),
|
||
Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Text(
|
||
_truncateText(
|
||
userInfo['nickName'], 8, 3),
|
||
style: const TextStyle(
|
||
fontSize: 20,
|
||
color: Color(0xffffffff),
|
||
decoration: TextDecoration.none,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
maxLines: 2,
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
const SizedBox(width: 10),
|
||
TextButton(
|
||
onPressed: userInfo[
|
||
'authenticationStatus'] ==
|
||
'1'
|
||
? () {
|
||
// 跳转到认证信息页面
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(
|
||
builder: (context) =>
|
||
AuthInfoPage(),
|
||
),
|
||
);
|
||
}
|
||
: () {
|
||
Navigator.pushNamed(
|
||
context,
|
||
"/realName",
|
||
);
|
||
},
|
||
style: ButtonStyle(
|
||
backgroundColor:
|
||
MaterialStateProperty.all(
|
||
userInfo['authenticationStatus'] ==
|
||
'1'
|
||
? const Color(0xff70DEED)
|
||
: const Color(0xff4E4E4E),
|
||
),
|
||
padding: MaterialStateProperty.all(
|
||
const EdgeInsets.symmetric(
|
||
vertical: 2,
|
||
horizontal: 8,
|
||
),
|
||
),
|
||
minimumSize:
|
||
MaterialStateProperty.all(
|
||
const Size(40, 10),
|
||
),
|
||
tapTargetSize: MaterialTapTargetSize
|
||
.shrinkWrap,
|
||
shape: MaterialStateProperty.all(
|
||
RoundedRectangleBorder(
|
||
borderRadius:
|
||
BorderRadius.circular(4),
|
||
),
|
||
),
|
||
),
|
||
child: Text(
|
||
userInfo['authenticationStatus'] ==
|
||
'1'
|
||
? '已认证'
|
||
: '实名认证',
|
||
style: const TextStyle(
|
||
color: Colors.black,
|
||
fontSize: 12,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 10),
|
||
Text(
|
||
_truncateText(
|
||
userInfo['signature'] ?? '暂无个性签名',
|
||
15,
|
||
3),
|
||
style: const TextStyle(
|
||
color: Color(0xffE9E9E9),
|
||
fontSize: 12,
|
||
decoration: TextDecoration.none,
|
||
),
|
||
maxLines: 3,
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
Positioned(
|
||
top: 170,
|
||
left: 0,
|
||
right: 0,
|
||
child: Container(
|
||
height: 60,
|
||
decoration: BoxDecoration(
|
||
gradient: LinearGradient(
|
||
begin: Alignment.topCenter,
|
||
end: Alignment.bottomCenter,
|
||
colors: [
|
||
Colors.black.withOpacity(0),
|
||
Colors.black.withOpacity(1),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
Positioned(
|
||
top: 145,
|
||
left: 0,
|
||
right: 0,
|
||
child: Container(
|
||
padding: const EdgeInsets.only(
|
||
top: 20, left: 115), // 修改左边距为16,与用户名对齐
|
||
child: Row(
|
||
children: [
|
||
// 改为普通Row,使用SizedBox控制间距
|
||
_buildStatItem(context, '关注', "${userInfo['following']}",
|
||
() {
|
||
Navigator.pushNamed(
|
||
context,
|
||
'/like',
|
||
arguments: {"initialTabIndex": 0},
|
||
);
|
||
}),
|
||
const SizedBox(width: 25), // 添加25px的间距
|
||
_buildStatItem(context, '欢迎度', "${userInfo['followed']}",
|
||
() {
|
||
Navigator.pushNamed(
|
||
context,
|
||
'/like',
|
||
arguments: {"initialTabIndex": 1},
|
||
);
|
||
}),
|
||
const SizedBox(width: 25), // 添加25px的间距
|
||
_buildStatItem(context, '喜爱', "${userInfo['popularity']}",
|
||
() {
|
||
Navigator.pushNamed(context, '/recevieLike');
|
||
}),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
Positioned(
|
||
left: 0,
|
||
top: 230,
|
||
bottom: 0,
|
||
child: Container(
|
||
width: MediaQuery.of(context).size.width,
|
||
// decoration: const BoxDecoration(
|
||
// image: DecorationImage(
|
||
// image: AssetImage('images/mine_bg.png'),
|
||
// fit: BoxFit.fill,
|
||
// ),
|
||
// ),
|
||
color: const Color(0xff0C0C16),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// 固定不滚动的部分
|
||
Container(
|
||
color: const Color(0xff0C0C16), // 确保上部分背景色一致
|
||
child: Column(
|
||
children: [
|
||
const SizedBox(height: 10),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||
children: [
|
||
GestureDetector(
|
||
onTap: () {
|
||
Navigator.pushNamed(context, '/history');
|
||
},
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
'images/history.png',
|
||
width: 30,
|
||
height: 30,
|
||
),
|
||
const SizedBox(height: 4),
|
||
const Text(
|
||
'历史订单',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
GestureDetector(
|
||
onTap: () {
|
||
Navigator.pushNamed(context, '/works');
|
||
},
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
'images/works.png',
|
||
width: 30,
|
||
height: 30,
|
||
),
|
||
const SizedBox(height: 4),
|
||
const Text(
|
||
'作品集',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
GestureDetector(
|
||
onTap: () {
|
||
Navigator.pushNamed(context, '/help');
|
||
},
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
'images/help.png',
|
||
width: 30,
|
||
height: 30,
|
||
),
|
||
const SizedBox(height: 4),
|
||
const Text(
|
||
'帮助中心',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
GestureDetector(
|
||
onTap: () {
|
||
var userInfoWithPhone = {
|
||
...userInfo,
|
||
'phone': storedPhone
|
||
};
|
||
Navigator.pushNamed(
|
||
context,
|
||
'/setting',
|
||
arguments: userInfoWithPhone,
|
||
);
|
||
},
|
||
child: Column(
|
||
children: [
|
||
Image.asset(
|
||
'images/setting.png',
|
||
width: 30,
|
||
height: 30,
|
||
),
|
||
const SizedBox(height: 4),
|
||
const Text(
|
||
'设置中心',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 10),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
const Padding(
|
||
padding: EdgeInsets.only(left: 20),
|
||
child: Text(
|
||
"我的发布",
|
||
style: TextStyle(
|
||
color: Color(0xffffffff),
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
),
|
||
Padding(
|
||
padding: const EdgeInsets.only(right: 20),
|
||
child: GestureDetector(
|
||
onTap: () {
|
||
Navigator.pushNamed(context, '/drafts');
|
||
},
|
||
child: const Column(
|
||
children: [
|
||
Image(
|
||
image: AssetImage(
|
||
'images/save_drafts.png'),
|
||
width: 23,
|
||
height: 23,
|
||
),
|
||
SizedBox(height: 4),
|
||
Text(
|
||
'草稿箱',
|
||
style: TextStyle(
|
||
fontSize: 10,
|
||
color: Color(0xffc1c1c1),
|
||
),
|
||
)
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
),
|
||
// 可滚动的网格部分
|
||
Expanded(
|
||
child: Container(
|
||
color: const Color(0xff0C0C16), // 确保网格部分背景色一致
|
||
child: RefreshIndicator(
|
||
onRefresh: getPublishedWorks,
|
||
child: publishedWorks.isEmpty
|
||
? const EmptyState(
|
||
message: '暂无发布内容',
|
||
usePureBackground: true, // 指定使用纯色背景
|
||
)
|
||
: SingleChildScrollView(
|
||
physics:
|
||
const AlwaysScrollableScrollPhysics(),
|
||
child: WorkGridView(
|
||
items: publishedWorks,
|
||
onTap: (index) async {
|
||
final result = await Navigator.pushNamed(
|
||
context,
|
||
'/worksDetail',
|
||
arguments: {
|
||
'id': publishedWorks[index].workId,
|
||
'type': 'publish',
|
||
},
|
||
);
|
||
|
||
if (result != null &&
|
||
result is Map<String, dynamic>) {
|
||
setState(() {
|
||
final updatedItems =
|
||
List<WorkItem>.from(
|
||
publishedWorks);
|
||
updatedItems[index] = WorkItem(
|
||
workId:
|
||
publishedWorks[index].workId,
|
||
imageUrl:
|
||
publishedWorks[index].imageUrl,
|
||
title: publishedWorks[index].title,
|
||
count: result['receiveRockets']
|
||
.toString(),
|
||
isAddLike:
|
||
result['isAddLike'].toString(),
|
||
);
|
||
publishedWorks = updatedItems;
|
||
});
|
||
}
|
||
},
|
||
onLikeTap: handleLike,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|