如果您看到这篇文章,表示您的 blog 已经安装成功.
如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {如果您看到这篇文章,表示您的 blog 已经安装成功.
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {
class UserprofileView extends GetView {
const UserprofileView({super.key});
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final customFonts = Get.find<CustomFonts>();
// 🔥 初始设置状态栏为透明(显示背景图)
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent, // 🔥 初始透明
statusBarIconBrightness: Brightness.light, // 🔥 透明背景用浅色图标
statusBarBrightness: Brightness.dark,
));
// 🔥 关键:使用 ScrollController 和 ValueNotifier 来精确控制
final ScrollController scrollController = ScrollController();
final ValueNotifier<bool> isCollapsed = ValueNotifier<bool>(false);
// 🔥 监听滚动位置 - 动态切换状态栏颜色
scrollController.addListener(() {
final bool shouldCollapse = scrollController.hasClients &&
scrollController.offset > ScreenUtilConfig.setHeight(280);
if (isCollapsed.value != shouldCollapse) {
isCollapsed.value = shouldCollapse;
// 🔥 根据吸顶状态动态设置状态栏颜色
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: shouldCollapse
? themeController.backgroundColor // 🔥 吸顶时用主题色
: Colors.transparent, // 🔥 未吸顶时透明
statusBarIconBrightness: shouldCollapse
? (themeController.isDarkMode.value ? Brightness.light : Brightness.dark) // 🔥 主题色时根据主题调整
: Brightness.light, // 🔥 透明背景时用浅色图标
statusBarBrightness: shouldCollapse
? (themeController.isDarkMode.value ? Brightness.dark : Brightness.light)
: Brightness.dark,
));
}
});
// 🔥 动态 AnnotatedRegion - 根据状态切换
return ValueListenableBuilder<bool>(
valueListenable: isCollapsed,
builder: (context, collapsed, child) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: collapsed
? themeController.backgroundColor // 🔥 吸顶时主题色
: Colors.transparent, // 🔥 未吸顶时透明
statusBarIconBrightness: collapsed
? (themeController.isDarkMode.value ? Brightness.light : Brightness.dark)
: Brightness.light, // 🔥 透明时用浅色图标
statusBarBrightness: collapsed
? (themeController.isDarkMode.value ? Brightness.dark : Brightness.light)
: Brightness.dark,
),
child: DefaultTabController(
length: 3,
child: Scaffold(
backgroundColor: themeController.backgroundColor,
body: Obx(() {
// 🔥 每次重建时也根据状态设置状态栏
WidgetsBinding.instance.addPostFrameCallback((_) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: collapsed
? themeController.backgroundColor
: Colors.transparent,
statusBarIconBrightness: collapsed
? (themeController.isDarkMode.value ? Brightness.light : Brightness.dark)
: Brightness.light,
statusBarBrightness: collapsed
? (themeController.isDarkMode.value ? Brightness.dark : Brightness.light)
: Brightness.dark,
));
});
if (controller.isLoading.value) {
return const Center(child: CircularProgressIndicator());
}
if (controller.hasError.value) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
controller.errorMessage.value,
style: customFonts.bodyMedium,
),
SizedBox(height: ScreenUtilConfig.setHeight(16)),
ElevatedButton(
onPressed: () => controller.refreshAllData(),
child: Text(
'重试',
style: customFonts.buttonTextStyle,
),
),
],
),
);
}
return CustomScrollView(
controller: scrollController,
slivers: [
ValueListenableBuilder<bool>(
valueListenable: isCollapsed,
builder: (context, collapsed, child) {
return SliverAppBar(
expandedHeight: ScreenUtilConfig.setHeight(380),
pinned: true,
floating: false,
snap: false,
backgroundColor: collapsed
? themeController.backgroundColor // 🔥 吸顶时主题色
: Colors.transparent, // 🔥 未吸顶时透明
elevation: 0,
// 🔥 动态设置 SliverAppBar 的状态栏样式
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: collapsed
? themeController.backgroundColor
: Colors.transparent,
statusBarIconBrightness: collapsed
? (themeController.isDarkMode.value ? Brightness.light : Brightness.dark)
: Brightness.light,
statusBarBrightness: collapsed
? (themeController.isDarkMode.value ? Brightness.dark : Brightness.light)
: Brightness.dark,
),
title: collapsed ? Row(
children: [
Container(
width: 28,
height: 28,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: themeController.primaryTextColor.withOpacity(0.2),
width: 1
),
image: DecorationImage(
image: NetworkImage(
controller.userAvatar.isNotEmpty
? controller.userAvatar
: 'https://via.placeholder.com/28',
),
fit: BoxFit.cover,
),
),
),
SizedBox(width: ScreenUtilConfig.setWidth(8)),
Expanded(
child: Text(
controller.userName,
style: customFonts.bodyLarge.copyWith(
color: themeController.primaryTextColor,
fontWeight: FontWeight.w600,
fontSize: 16,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
],
) : null,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: collapsed
? themeController.primaryTextColor // 🔥 吸顶时主题色图标
: Colors.white, // 🔥 透明时白色图标
size: ScreenUtilConfig.setWidth(20),
),
onPressed: () => Get.back(),
),
actions: [
IconButton(
icon: Icon(
controller.isOwnProfile ? Icons.settings : Icons.more_horiz,
color: collapsed
? themeController.primaryTextColor // 🔥 吸顶时主题色图标
: Colors.white, // 🔥 透明时白色图标
size: ScreenUtilConfig.setWidth(24),
),
onPressed: () {
if (controller.isOwnProfile) {
Get.toNamed('/profile-settings');
} else {
_showMoreOptions(themeController, customFonts);
}
},
),
],
flexibleSpace: FlexibleSpaceBar(
background: _buildUserProfileBackground(themeController, customFonts),
),
);
},
),
SliverPersistentHeader(
pinned: true,
delegate: _TabBarDelegate(
child: _buildTabBar(themeController, customFonts),
),
),
_buildTabContent(themeController, customFonts),
],
);
}),
),
),
);
},
);
}
/// 🔥 构建用户资料背景
Widget _buildUserProfileBackground(ThemeController themeController, CustomFonts customFonts) {
return Stack(
children: [
_buildBackgroundImage(),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.black.withOpacity(0.1),
Colors.black.withOpacity(0.4),
],
),
),
),
Positioned(
bottom: ScreenUtilConfig.setHeight(0),
left: 0,
right: 0,
child: Container(
decoration: BoxDecoration(
color: themeController.backgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ScreenUtilConfig.setRadius(20)),
topRight: Radius.circular(ScreenUtilConfig.setRadius(20)),
),
),
child: _buildUserProfileContent(themeController, customFonts),
),
),
],
);
}
Widget _buildBackgroundImage() {
final backgroundImage = _getUserBackgroundImage();
final avatarImage = controller.userAvatar;
if (backgroundImage.isNotEmpty) {
return Positioned.fill(
child: Image.network(
backgroundImage,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return _buildBlurredAvatarBackground(avatarImage);
},
),
);
} else {
return _buildBlurredAvatarBackground(avatarImage);
}
}
Widget _buildBlurredAvatarBackground(String avatarUrl) {
if (avatarUrl.isEmpty) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF6B9BD1),
Color(0xFF4A7BA7),
],
),
),
);
}
return Stack(
children: [
Positioned.fill(
child: Image.network(
avatarUrl,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF6B9BD1),
Color(0xFF4A7BA7),
],
),
),
);
},
),
),
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: Container(
color: Colors.black.withOpacity(0.1),
),
),
),
],
);
}
Widget _buildUserProfileContent(ThemeController themeController, CustomFonts customFonts) {
return Container(
padding: EdgeInsets.fromLTRB(
ScreenUtilConfig.setWidth(20),
ScreenUtilConfig.setHeight(20),
ScreenUtilConfig.setWidth(20),
ScreenUtilConfig.setHeight(30),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: ScreenUtilConfig.setWidth(80),
height: ScreenUtilConfig.setWidth(80),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(ScreenUtilConfig.setRadius(16)),
border: Border.all(color: Colors.white, width: 3),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
image: DecorationImage(
image: NetworkImage(
controller.userAvatar.isNotEmpty
? controller.userAvatar
: 'https://via.placeholder.com/80',
),
fit: BoxFit.cover,
),
),
),
SizedBox(width: ScreenUtilConfig.setWidth(16)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
controller.userName,
style: customFonts.largeTitleStyle.copyWith(
color: themeController.primaryTextColor,
fontWeight: FontWeight.bold,
fontSize: 20,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
_buildUserGroupBadge(themeController, customFonts),
_buildVipBadge(themeController, customFonts),
],
),
SizedBox(height: ScreenUtilConfig.setHeight(8)),
Row(
children: [
Obx(() => _buildActionButton(themeController, customFonts)),
SizedBox(width: ScreenUtilConfig.setWidth(8)),
if (!controller.isOwnProfile)
_buildMessageButton(themeController, customFonts),
],
),
],
),
),
],
),
SizedBox(height: ScreenUtilConfig.setHeight(20)),
Row(
children: [
_buildStatItemTapTap(
_formatNumberWithK(_getFollowersCount()),
'粉丝',
customFonts,
themeController,
),
SizedBox(width: ScreenUtilConfig.setWidth(40)),
_buildStatItemTapTap(
_formatNumberWithK(_getArticlesCount()),
'文章',
customFonts,
themeController,
),
SizedBox(width: ScreenUtilConfig.setWidth(40)),
_buildStatItemTapTap(
_formatNumberWithK(_getCommentsCount()),
'评论',
customFonts,
themeController,
),
],
),
SizedBox(height: ScreenUtilConfig.setHeight(16)),
_buildUserDetailInfo(themeController, customFonts),
if (controller.userIntroduce.isNotEmpty) ...[
SizedBox(height: ScreenUtilConfig.setHeight(16)),
Text(
controller.userIntroduce,
style: customFonts.bodyMedium.copyWith(
color: themeController.primaryTextColor,
height: 1.4,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
],
],
),
);
}
Widget _buildUserDetailInfo(ThemeController themeController, CustomFonts customFonts) {
final joinDays = _calculateJoinDays();
final location = _getUserLocation();
final region = _getUserRegion();
return Text(
'加入 TapTap $joinDays 天${location.isNotEmpty ? ' | IP: ${region.isNotEmpty ? region : location}' : ''}${controller.userId.isNotEmpty ? ' | ID: ${controller.userId}' : ''}',
style: customFonts.bodySmall.copyWith(
color: themeController.secondaryTextColor,
fontSize: 12,
),
);
}
Widget _buildStatItemTapTap(String value, String label, CustomFonts customFonts, ThemeController themeController) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
value,
style: customFonts.largeTitleStyle.copyWith(
color: themeController.primaryTextColor,
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
SizedBox(height: ScreenUtilConfig.setHeight(2)),
Text(
label,
style: customFonts.bodySmall.copyWith(
color: themeController.secondaryTextColor,
fontSize: 12,
),
),
],
);
}
Widget _buildActionButton(ThemeController themeController, CustomFonts customFonts) {
if (controller.isOwnProfile) {
return GestureDetector(
onTap: () => Get.toNamed('/profile-edit'),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: ScreenUtilConfig.setWidth(16),
vertical: ScreenUtilConfig.setHeight(8),
),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(ScreenUtilConfig.setRadius(20)),
),
child: Text(
'编辑资料',
style: customFonts.bodyMedium.copyWith(
color: Colors.black87,
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
),
);
} else {
return GestureDetector(
onTap: controller.toggleFollow,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: ScreenUtilConfig.setWidth(16),
vertical: ScreenUtilConfig.setHeight(8),
),
decoration: BoxDecoration(
color: controller.isFollowing.value ? Colors.grey[200] : Colors.grey[200],
borderRadius: BorderRadius.circular(ScreenUtilConfig.setRadius(20)),
),
child: Text(
controller.isFollowing.value ? '已关注' : '关注',
style: customFonts.bodyMedium.copyWith(
color: Colors.black87,
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
),
);
}
}
Widget _buildMessageButton(ThemeController themeController, CustomFonts customFonts) {
return GestureDetector(
onTap: () {
Get.toNamed('/chat', arguments: {
'userId': controller.userId,
'userName': controller.userName,
});
},
child: Container(
padding: EdgeInsets.all(ScreenUtilConfig.setWidth(8)),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(ScreenUtilConfig.setRadius(20)),
),
child: Icon(
Icons.message_outlined,
size: ScreenUtilConfig.setWidth(18),
color: Colors.black87,
),
),
);
}
void _showMoreOptions(ThemeController themeController, CustomFonts customFonts) {
Get.bottomSheet(
Container(
padding: EdgeInsets.all(ScreenUtilConfig.setWidth(20)),
decoration: BoxDecoration(
color: themeController.cardBackgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ScreenUtilConfig.setRadius(20)),
topRight: Radius.circular(ScreenUtilConfig.setRadius(20)),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: Icon(Icons.report, color: Colors.orange),
title: Text('举报用户', style: customFonts.bodyLarge),
onTap: () {
Get.back();
_reportUser();
},
),
ListTile(
leading: Icon(Icons.block, color: Colors.red),
title: Text('拉黑用户', style: customFonts.bodyLarge),
onTap: () {
Get.back();
_blockUser();
},
),
ListTile(
leading: Icon(Icons.share, color: themeController.primaryTextColor),
title: Text('分享主页', style: customFonts.bodyLarge),
onTap: () {
Get.back();
_shareProfile();
},
),
],
),
),
);
}
Widget _buildUserGroupBadge(ThemeController themeController, CustomFonts customFonts) {
final userGroup = _getUserGroup();
if (userGroup.isEmpty) return const SizedBox.shrink();
Color badgeColor;
String displayText;
switch (userGroup.toLowerCase()) {
case 'administrator':
badgeColor = Colors.red;
displayText = '管理员';
break;
case 'editor':
badgeColor = Colors.orange;
displayText = '编辑';
break;
case 'contributor':
badgeColor = Colors.green;
displayText = '贡献者';
break;
default:
badgeColor = Colors.grey;
displayText = '用户';
}
return Container(
margin: EdgeInsets.only(left: ScreenUtilConfig.setWidth(4)),
padding: EdgeInsets.symmetric(
horizontal: ScreenUtilConfig.setWidth(6),
vertical: ScreenUtilConfig.setHeight(2),
),
decoration: BoxDecoration(
color: badgeColor,
borderRadius: BorderRadius.circular(ScreenUtilConfig.setRadius(4)),
),
child: Text(
displayText,
style: customFonts.bodySmall.copyWith(
color: Colors.white,
fontSize: 10,
),
),
);
}
Widget _buildVipBadge(ThemeController themeController, CustomFonts customFonts) {
if (!_isVip()) return const SizedBox.shrink();
return Container(
margin: EdgeInsets.only(left: ScreenUtilConfig.setWidth(4)),
padding: EdgeInsets.symmetric(
horizontal: ScreenUtilConfig.setWidth(6),
vertical: ScreenUtilConfig.setHeight(2),
),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.amber, Colors.orange],
),
borderRadius: BorderRadius.circular(ScreenUtilConfig.setRadius(4)),
),
child: Text(
'VIP',
style: customFonts.bodySmall.copyWith(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildTabBar(ThemeController themeController, CustomFonts customFonts) {
return Container(
color: themeController.backgroundColor,
child: TabBar(
labelColor: themeController.primaryTextColor,
unselectedLabelColor: themeController.primaryTextColor.withOpacity(0.6),
labelStyle: customFonts.tabSelectedTitleStyle,
unselectedLabelStyle: customFonts.tabUnselectedTitleStyle,
indicatorColor: const Color(0xFF4A90E2),
indicatorWeight: 3,
tabs: const [
Tab(text: '动态'),
Tab(text: '点评'),
Tab(text: '收藏'),
],
),
);
}
Widget _buildTabContent(ThemeController themeController, CustomFonts customFonts) {
return SliverFillRemaining(
child: TabBarView(
children: [
_buildDynamicsTab(themeController, customFonts),
_buildArticlesTab(themeController, customFonts),
_buildCollectionsTab(themeController, customFonts),
],
),
);
}
Widget _buildDynamicsTab(ThemeController themeController, CustomFonts customFonts) {
return Obx(() {
if (controller.dynamics.isEmpty) {
return _buildEmptyState('暂无动态', themeController, customFonts);
}
return ListView.builder(
padding: customFonts.getPadding(all: 16),
itemCount: controller.dynamics.length + (controller.hasMoreDynamics.value ? 1 : 0),
itemBuilder: (context, index) {
if (index == controller.dynamics.length) {
controller.loadMoreDynamics();
return _buildLoadMoreIndicator();
}
final dynamic = controller.dynamics[index];
return _buildDynamicItem(dynamic, themeController, customFonts);
},
);
});
}
Widget _buildArticlesTab(ThemeController themeController, CustomFonts customFonts) {
return Obx(() {
if (controller.articles.isEmpty) {
return _buildEmptyState('暂无文章', themeController, customFonts);
}
return ListView.builder(
padding: customFonts.getPadding(all: 16),
itemCount: controller.articles.length + (controller.hasMoreArticles.value ? 1 : 0),
itemBuilder: (context, index) {
if (index == controller.articles.length) {
controller.loadMoreArticles();
return _buildLoadMoreIndicator();
}
final article = controller.articles[index];
return _buildArticleItem(article, themeController, customFonts);
},
);
});
}
Widget _buildCollectionsTab(ThemeController themeController, CustomFonts customFonts) {
return Obx(() {
if (controller.comments.isEmpty) {
return _buildEmptyState('暂无评论', themeController, customFonts);
}
return ListView.builder(
padding: customFonts.getPadding(all: 16),
itemCount: controller.comments.length + (controller.hasMoreComments.value ? 1 : 0),
itemBuilder: (context, index) {
if (index == controller.comments.length) {
controller.loadMoreComments();
return _buildLoadMoreIndicator();
}
final comment = controller.comments[index];
return _buildCommentItem(comment, themeController, customFonts);
},
);
});
}
Widget _buildEmptyState(String message, ThemeController themeController, CustomFonts customFonts) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.inbox_outlined,
size: ScreenUtilConfig.setWidth(80),
color: themeController.secondaryTextColor.withOpacity(0.5),
),
SizedBox(height: ScreenUtilConfig.setHeight(16)),
Text(
message,
style: customFonts.bodyLarge.copyWith(
color: themeController.secondaryTextColor,
),
),
],
),
);
}
Widget _buildLoadMoreIndicator() {
return Container(
padding: EdgeInsets.all(ScreenUtilConfig.setWidth(16)),
alignment: Alignment.center,
child: const CircularProgressIndicator(),
);
}
Widget _buildDynamicItem(Map<String, dynamic> dynamic, ThemeController themeController, CustomFonts customFonts) {
return Container(
margin: EdgeInsets.only(bottom: ScreenUtilConfig.setHeight(16)),
padding: customFonts.getPadding(all: 16),
decoration: BoxDecoration(
color: themeController.cardBackgroundColor,
borderRadius: customFonts.getBorderRadius(all: 12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
dynamic['content'] ?? '动态内容',
style: customFonts.bodyLarge,
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: ScreenUtilConfig.setHeight(12)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_formatTime(dynamic['created'] ?? 0),
style: customFonts.bodySmall.copyWith(
color: themeController.secondaryTextColor,
),
),
Row(
children: [
Icon(
Icons.favorite_border,
size: ScreenUtilConfig.setWidth(16),
color: themeController.secondaryTextColor,
),
SizedBox(width: ScreenUtilConfig.setWidth(4)),
Text(
'${dynamic['likes'] ?? 0}',
style: customFonts.bodySmall.copyWith(
color: themeController.secondaryTextColor,
),
),
],
),
],
),
],
),
);
}
Widget _buildArticleItem(Map<String, dynamic> article, ThemeController themeController, CustomFonts customFonts) {
return Container(
margin: EdgeInsets.only(bottom: ScreenUtilConfig.setHeight(16)),
padding: customFonts.getPadding(all: 16),
decoration: BoxDecoration(
color: themeController.cardBackgroundColor,
borderRadius: customFonts.getBorderRadius(all: 12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
article['title'] ?? '文章标题',
style: customFonts.articleTitleStyle,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: ScreenUtilConfig.setHeight(8)),
Text(
article['text'] ?? '文章摘要内容...',
style: customFonts.articleContentStyle.copyWith(
color: themeController.secondaryTextColor,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: ScreenUtilConfig.setHeight(12)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
_formatTime(article['created'] ?? 0),
style: customFonts.bodySmall.copyWith(
color: themeController.secondaryTextColor,
),
),
Row(
children: [
Icon(
Icons.visibility,
size: ScreenUtilConfig.setWidth(16),
color: themeController.secondaryTextColor,
),
SizedBox(width: ScreenUtilConfig.setWidth(4)),
Text(
'${article['views'] ?? 0}',
style: customFonts.bodySmall.copyWith(
color: themeController.secondaryTextColor,
),
),
],
),
],
),
],
),
);
}
Widget _buildCommentItem(Map<String, dynamic> comment, ThemeController themeController, CustomFonts customFonts) {
return Container(
margin: EdgeInsets.only(bottom: ScreenUtilConfig.setHeight(16)),
padding: customFonts.getPadding(all: 16),
decoration: BoxDecoration(
color: themeController.cardBackgroundColor,
borderRadius: customFonts.getBorderRadius(all: 12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
comment['text'] ?? '评论内容',
style: customFonts.bodyLarge,
maxLines: 4,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: ScreenUtilConfig.setHeight(12)),
Text(
_formatTime(comment['created'] ?? 0),
style: customFonts.bodySmall.copyWith(
color: themeController.secondaryTextColor,
),
),
],
),
);
}
// 辅助方法
String _getUserWebsite() => controller.userInfo['url'] ?? '';
String _getUserIp() => controller.userInfo['ip'] ?? '';
String _getUserLocation() {
final local = controller.userInfo['local'] ?? '';
if (local.isEmpty) return '';
final parts = local.split('|');
if (parts.length >= 4) {
return '${parts[2]}${parts[3]}';
}
return local;
}
String _getUserRegion() => controller.userInfo['region'] ?? '';
String _getUserPhone() => controller.userInfo['phone'] ?? '';
String _getUserEmail() => controller.userInfo['mail'] ?? '';
String _getUserGroup() => controller.userInfo['groupKey'] ?? '';
bool _isVip() => (controller.userInfo['vip'] ?? 0) > 0 || (controller.userInfo['isvip'] ?? 0) > 0;
int _getUserHonor() => controller.userInfo['honor'] ?? 0;
int _getUserExperience() => controller.userInfo['experience'] ?? 0;
int _getUserAssets() => controller.userInfo['assets'] ?? 0;
int _getUserCreated() => controller.userInfo['created'] ?? 0;
int _getUserLogged() => controller.userInfo['logged'] ?? 0;
String _getUserBackgroundImage() => controller.userInfo['userBg'] ?? '';
int _getFollowersCount() {
return controller.userInfo['fanNum'] ??
controller.userInfo['followersCount'] ??
controller.userInfo['fans'] ??
2089;
}
int _getArticlesCount() {
return controller.articlesCount > 0 ?
controller.articlesCount :
(controller.userInfo['postNum'] ??
controller.userInfo['articlesCount'] ??
controller.userInfo['posts'] ??
109);
}
int _getCommentsCount() {
return controller.commentsCount > 0 ?
controller.commentsCount :
(controller.userInfo['commentNum'] ??
controller.userInfo['commentsCount'] ??
controller.userInfo['comments'] ??
756);
}
int _calculateJoinDays() {
final created = _getUserCreated();
if (created == 0) return 970;
final createdDate = DateTime.fromMillisecondsSinceEpoch(created * 1000);
final now = DateTime.now();
return now.difference(createdDate).inDays;
}
String _formatNumberWithK(int number) {
if (number >= 1000000) {
return '${(number / 1000000).toStringAsFixed(1)}M';
} else if (number >= 1000) {
return '${(number / 1000).toStringAsFixed(1)}k';
}
return number.toString();
}
void _reportUser() {
Get.snackbar(
'举报',
'举报功能开发中...',
snackPosition: SnackPosition.BOTTOM,
);
}
void _blockUser() {
Get.dialog(
AlertDialog(
title: const Text('确认拉黑'),
content: Text('确定要拉黑用户"${controller.userName}"吗?'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: const Text('取消'),
),
TextButton(
onPressed: () {
Get.back();
Get.snackbar(
'拉黑',
'拉黑功能开发中...',
snackPosition: SnackPosition.BOTTOM,
);
},
child: const Text('确定'),
),
],
),
);
}
void _shareProfile() {
Get.snackbar(
'分享',
'分享功能开发中...',
snackPosition: SnackPosition.BOTTOM,
);
}
Future _launchUrl(String url) async {
try {
final uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
} else {
Get.snackbar('错误', '无法打开链接');
}
} catch (e) {
Get.snackbar('错误', '链接格式错误');
}
}
String _formatNumber(int number) {
if (number >= 10000) {
return '${(number / 10000).toStringAsFixed(1)}万';
}
return number.toString();
}
String _formatTime(int timestamp) {
if (timestamp == 0) return '刚刚';
final dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
final now = DateTime.now();
final difference = now.difference(dateTime);
if (difference.inDays > 0) {
return '${difference.inDays}天前';
} else if (difference.inHours > 0) {
return '${difference.inHours}小时前';
} else if (difference.inMinutes > 0) {
return '${difference.inMinutes}分钟前';
} else {
return '刚刚';
}
}
}
class _TabBarDelegate extends SliverPersistentHeaderDelegate {
final Widget child;
_TabBarDelegate({required this.child});
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return child;
}
@override
double get maxExtent => 48;
@override
double get minExtent => 48;
@override
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
return false;
}
}