fix_个人中心&博主主页

This commit is contained in:
abu 2025-10-13 22:52:47 +08:00
parent 314aeddf23
commit 67ed131eeb
3 changed files with 250 additions and 201 deletions

View File

@ -543,16 +543,6 @@ class _IndexPageState extends State<IndexPage> with TickerProviderStateMixin {
SliverToBoxAdapter( SliverToBoxAdapter(
child: Obx( child: Obx(
() { () {
// if (isInitLoading.value) {
// return Column(
// children: [
// RefreshProgressIndicator(
// backgroundColor: Colors.white,
// color: Color(0xFFFF5000),
// ),
// ],
// );
// }
if (dataList.isEmpty) { if (dataList.isEmpty) {
return EmptyTip(); return EmptyTip();
} }

View File

@ -28,7 +28,7 @@ import '../../utils/common.dart';
class PageParams { class PageParams {
int page; int page;
int pageSize; int pageSize;
bool isLoading; RxBool isLoading;
RxBool hasMore; RxBool hasMore;
int total; int total;
bool isInitLoading; bool isInitLoading;
@ -36,16 +36,21 @@ class PageParams {
PageParams({ PageParams({
this.page = 1, this.page = 1,
this.pageSize = 10, this.pageSize = 10,
this.isLoading = false, bool isLoading = false,
bool hasMore = true, bool hasMore = true,
this.total = 0, this.total = 0,
this.isInitLoading = true, this.isInitLoading = true,
}) : hasMore = hasMore.obs; }) : hasMore = hasMore.obs,
isLoading = isLoading.obs;
@override
String toString() {
return 'PageParams(page: $page, pageSize: $pageSize, isLoading: ${isLoading.value}, hasMore: ${hasMore.value})';
}
void init() { void init() {
page = 1; page = 1;
pageSize = 10; pageSize = 10;
isLoading = false; isLoading.value = false;
hasMore.value = true; hasMore.value = true;
total = 0; total = 0;
isInitLoading = true; isInitLoading = true;
@ -98,16 +103,16 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
super.initState(); super.initState();
imUserInfoController = Get.find<ImUserInfoController>(); imUserInfoController = Get.find<ImUserInfoController>();
initControllers(); initControllers();
//
scrollListener = () { scrollListener = () {
final pos = scrollController.position; final pos = scrollController.position;
final isNearBottom = pos.pixels >= pos.maxScrollExtent - 100; final isNearBottom = pos.pixels >= pos.maxScrollExtent - 100;
if (!isNearBottom) return; if (!isNearBottom) return;
if (currentTabIndex.value == 0 && !itemsParams.isLoading && itemsParams.hasMore.value) { if (currentTabIndex.value == 0 && !itemsParams.isLoading.value && itemsParams.hasMore.value) {
loadData(0); loadData(0);
} else if (currentTabIndex.value == 1 && !favoriteParams.isLoading && favoriteParams.hasMore.value) { } else if (currentTabIndex.value == 1 && !favoriteParams.isLoading.value && favoriteParams.hasMore.value) {
loadData(1); loadData(1);
} }
}; };
@ -124,8 +129,6 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
} }
}; };
tabController.addListener(tabListener); tabController.addListener(tabListener);
// loadData(0);
} }
@override @override
@ -165,10 +168,10 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
Future<void> loadData([int? tabIndex]) async { Future<void> loadData([int? tabIndex]) async {
final index = tabIndex ?? currentTabIndex.value; final index = tabIndex ?? currentTabIndex.value;
if (index == 0) { if (index == 0) {
if (itemsParams.isLoading || !itemsParams.hasMore.value) return; if (itemsParams.isLoading.value || !itemsParams.hasMore.value) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
itemsParams.isLoading = true; itemsParams.isLoading.value = true;
// itemsParams.isInitLoading = true; });
final res = await Http.post(VideoApi.myPublicList, data: { final res = await Http.post(VideoApi.myPublicList, data: {
"userId": imUserInfoController.userID.value, "userId": imUserInfoController.userID.value,
@ -179,25 +182,22 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
final obj = res['data']; final obj = res['data'];
final total = obj['total']; final total = obj['total'];
final row = obj['records'] ?? []; final row = obj['records'] ?? [];
logger.i(res['data']);
// //
logger.e(items.length); logger.e(items.length);
// //
items.addAll(row); items.addAll(row);
logger.e(obj); itemsParams.page++;
if (items.length >= total) { if (items.length >= total) {
itemsParams.hasMore.value = false; itemsParams.hasMore.value = false;
} }
// itemsParams.isLoading.value = false;
itemsParams.page++;
//
itemsParams.isLoading = false;
itemsParams.isInitLoading = false; itemsParams.isInitLoading = false;
} else if (index == 1) { } else if (index == 1) {
if (favoriteParams.isLoading || !favoriteParams.hasMore.value) return; if (favoriteParams.isLoading.value || !favoriteParams.hasMore.value) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
favoriteParams.isLoading = true; favoriteParams.isLoading.value = true;
// favoriteParams.isInitLoading = true; });
final res = await Http.post(VideoApi.myLikedList, data: { final res = await Http.post(VideoApi.myLikedList, data: {
"userId": imUserInfoController.userID.value, "userId": imUserInfoController.userID.value,
@ -209,14 +209,14 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
final total = obj['total']; final total = obj['total'];
final row = obj['records'] ?? []; final row = obj['records'] ?? [];
favoriteItems.addAll(row); favoriteItems.addAll(row);
favoriteParams.page++;
if (favoriteItems.length >= total) { if (favoriteItems.length >= total) {
favoriteParams.hasMore.value = false; favoriteParams.hasMore.value = false;
} }
favoriteParams.isLoading.value = false;
favoriteParams.page++;
favoriteParams.isLoading = false;
favoriteParams.isInitLoading = false; favoriteParams.isInitLoading = false;
logger.e(favoriteParams.toString());
} }
} }
@ -583,46 +583,65 @@ class MyPageState extends State<MyPage> with SingleTickerProviderStateMixin {
if (listToShow.isEmpty) { if (listToShow.isEmpty) {
return emptyTip('暂无相关数据'); return emptyTip('暂无相关数据');
} }
return CustomScrollView( return NotificationListener<ScrollNotification>(
// physics: !isPinned.value ? NeverScrollableScrollPhysics() : AlwaysScrollableScrollPhysics(), onNotification: (notification) {
// physics: AlwaysScrollableScrollPhysics(), if (notification is ScrollUpdateNotification) {
key: PageStorageKey('myindex_$tabIndex'), final metrics = notification.metrics;
slivers: [ final isNearBottom = metrics.pixels == metrics.maxScrollExtent;
SliverPadding(
padding: EdgeInsets.all(10.0), if (isNearBottom && !params.isLoading.value && params.hasMore.value) {
sliver: SliverGrid( loadData(tabIndex);
delegate: SliverChildBuilderDelegate( }
(context, index) { }
return Container( return false;
decoration: BoxDecoration( },
color: Colors.blue[100 * ((index % 8) + 1)], child: CustomScrollView(
borderRadius: BorderRadius.circular(10.0), key: PageStorageKey('myindex_$tabIndex'),
), slivers: [
alignment: Alignment.center, SliverPadding(
child: _buildVdCard(listToShow[index], tabIndex), padding: EdgeInsets.all(10.0),
); sliver: SliverGrid(
}, delegate: SliverChildBuilderDelegate(
childCount: listToShow.length, (context, index) {
), return Container(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( decoration: BoxDecoration(
crossAxisCount: 3, color: Colors.blue[100 * ((index % 8) + 1)],
crossAxisSpacing: 10.0, borderRadius: BorderRadius.circular(10.0),
mainAxisSpacing: 10.0, ),
childAspectRatio: 0.6, alignment: Alignment.center,
), child: _buildVdCard(listToShow[index], tabIndex),
), );
), },
SliverToBoxAdapter( childCount: listToShow.length,
child: Padding( ),
padding: const EdgeInsets.symmetric(vertical: 20.0), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
child: Center( crossAxisCount: 3,
child: Obx( crossAxisSpacing: 10.0,
() => params.hasMore.value ? CircularProgressIndicator() : Text('没有更多数据了'), mainAxisSpacing: 10.0,
childAspectRatio: 0.6,
), ),
), ),
), ),
), SliverToBoxAdapter(
], child: Padding(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: Center(
child: Obx(
() {
if (params.isLoading.value) {
return SafeArea(top: false, child: CircularProgressIndicator());
} else if (!params.hasMore.value) {
return SafeArea(top: false, child: Text('没有更多数据了'));
} else {
return SizedBox(height: 20);
}
},
),
),
),
),
],
),
); );
} }

View File

@ -23,15 +23,20 @@ import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
class PageParams { class PageParams {
int page; int page;
int pageSize; int pageSize;
bool isLoading; RxBool isLoading;
bool hasMore; RxBool hasMore;
PageParams({ PageParams({
this.page = 1, this.page = 1,
this.pageSize = 10, this.pageSize = 12,
this.isLoading = false, bool isLoading = false,
this.hasMore = true, bool hasMore = true,
}); }) : hasMore = hasMore.obs,
isLoading = isLoading.obs;
@override
String toString() {
return 'PageParams(page: $page, pageSize: $pageSize, isLoading: ${isLoading.value}, hasMore: ${hasMore.value})';
}
} }
class Vloger extends StatefulWidget { class Vloger extends StatefulWidget {
@ -67,7 +72,7 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
)); ));
RxBool get shouldFixHeader => (currentTabIndex.value == 0 && items.isEmpty) || (currentTabIndex.value == 1 && favoriteItems.isEmpty) ? true.obs : false.obs; RxBool get shouldFixHeader => (currentTabIndex.value == 0 && items.isEmpty) || (currentTabIndex.value == 1 && favoriteItems.isEmpty) ? true.obs : false.obs;
RxInt totalCount = 0.obs;
List tabList = [ List tabList = [
{'name': "作品"}, {'name': "作品"},
]; ];
@ -85,24 +90,21 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
void initState() { void initState() {
super.initState(); super.initState();
args = Get.arguments ?? {}; args = Get.arguments ?? {};
print('argsssssssssssssssssssssss$args'); logger.e(args);
itemsParams = PageParams(); itemsParams = PageParams();
favoriteParams = PageParams(); favoriteParams = PageParams();
selfInfo(); selfInfo();
flowInfo(); flowInfo();
checkFollowType(); checkFollowType();
initControllers(); initControllers();
//
scrollListener = () { scrollListener = () {
final pos = scrollController.position; final pos = scrollController.position;
final isNearBottom = pos.pixels >= pos.maxScrollExtent - 100; final isNearBottom = pos.pixels >= pos.maxScrollExtent - 100;
if (!isNearBottom) return; if (!isNearBottom) return;
if (currentTabIndex.value == 0 && !itemsParams.isLoading && itemsParams.hasMore) { if (currentTabIndex.value == 0 && !itemsParams.isLoading.value && itemsParams.hasMore.value) {
loadData(0); loadData(0);
} else if (currentTabIndex.value == 1 && !favoriteParams.isLoading && favoriteParams.hasMore) {
loadData(1);
} }
}; };
scrollController.addListener(scrollListener); scrollController.addListener(scrollListener);
@ -133,18 +135,27 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
void getUserLikesCount() async { void getUserLikesCount() async {
try { try {
final resData = await Http.get('${CommonApi.accountInfo}?memberId=${args['memberId']}'); final resData = await Http.get('${CommonApi.accountInfo}?memberId=${args['memberId']}');
print('aaaaaaaaaaaaaaaaaaa$resData'); logger.e('$resData');
if (resData != null && resData['code'] == 200) { if (resData != null && resData['code'] == 200) {
vlogLikeCount = resData['data']['vlogLikeCount'] ?? 0; vlogLikeCount = resData['data']['vlogLikeCount'] ?? 0;
} }
} catch (e) {} } catch (e) {
logger.e(e);
}
} }
void loadData([int? tabIndex]) async { void loadData([int? tabIndex]) async {
final index = tabIndex ?? currentTabIndex.value; final index = tabIndex ?? currentTabIndex.value;
if (index == 0) { if (index == 0) {
if (itemsParams.isLoading || !itemsParams.hasMore) return; if (itemsParams.isLoading.value || !itemsParams.hasMore.value) return;
itemsParams.isLoading = true; WidgetsBinding.instance.addPostFrameCallback((_) {
itemsParams.isLoading.value = true;
});
// await Future.delayed(Duration(seconds: 5), () {
// logger.e('5秒后执行完毕');
// });
final res = await Http.post(VideoApi.getVideoListByMemberId, data: { final res = await Http.post(VideoApi.getVideoListByMemberId, data: {
"memberId": args['memberId'], "memberId": args['memberId'],
"current": itemsParams.page, "current": itemsParams.page,
@ -153,19 +164,20 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
final obj = res['data']; final obj = res['data'];
final total = obj['total']; final total = obj['total'];
final row = obj['records'] ?? []; final row = obj['records'] ?? [];
logger.i(res['data']); // logger.i(res['data']);
totalCount.value = total;
// //
logger.e(items.length); logger.e(items.length);
// //
items.addAll(row); items.addAll(row);
logger.e(obj);
if (items.length >= total) {
itemsParams.hasMore = false;
}
//
itemsParams.page++; itemsParams.page++;
//
itemsParams.isLoading = false; if (items.length >= total) {
itemsParams.hasMore.value = false;
}
itemsParams.isLoading.value = false;
logger.e(itemsParams.toString());
} }
} }
@ -418,14 +430,20 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
controller: tabController, controller: tabController,
tabs: tabList.map((item) { tabs: tabList.map((item) {
return Tab( return Tab(
child: Badge.count( child: Obx(
backgroundColor: Colors.red, () => Text(
count: item['badge'] ?? 0, '${item['name']}(${totalCount.value})',
isLabelVisible: item['badge'] != null, style: TextStyle(fontWeight: FontWeight.bold),
alignment: Alignment.topRight, ),
offset: const Offset(14, -6),
child: Text(item['name'], style: const TextStyle(fontWeight: FontWeight.bold)),
), ),
// child: Badge.count(
// backgroundColor: Colors.red,
// count: item['badge'] ?? 0,
// isLabelVisible: item['badge'] != null,
// alignment: Alignment.topRight,
// offset: const Offset(14, -6),
// child: Text(item['name'], style: const TextStyle(fontWeight: FontWeight.bold)),
// ),
); );
}).toList(), }).toList(),
isScrollable: true, // isScrollable: true, //
@ -496,111 +514,133 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
if (listToShow.isEmpty) { if (listToShow.isEmpty) {
return emptyTip('暂无相关数据'); return emptyTip('暂无相关数据');
} }
return NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollUpdateNotification) {
final metrics = notification.metrics;
final isNearBottom = metrics.pixels >= metrics.maxScrollExtent;
return CustomScrollView( if (isNearBottom && !params.isLoading.value && params.hasMore.value) {
slivers: [ loadData(0);
SliverPadding( }
padding: const EdgeInsets.all(10.0), }
sliver: SliverGrid( return false;
delegate: SliverChildBuilderDelegate( },
(context, index) { child: CustomScrollView(
final item = listToShow[index]; slivers: [
return GestureDetector( SliverPadding(
onTap: () { padding: const EdgeInsets.all(10.0),
// sliver: SliverGrid(
Get.toNamed('/videoDetail', arguments: {'videoId': item['id']}); delegate: SliverChildBuilderDelegate(
}, (context, index) {
child: Container( final item = listToShow[index];
decoration: BoxDecoration( return GestureDetector(
borderRadius: BorderRadius.circular(10.0), onTap: () {
boxShadow: [ //
BoxShadow( Get.toNamed('/videoDetail', arguments: {'videoId': item['id']});
color: Colors.black.withOpacity(0.1), },
blurRadius: 4, child: Container(
offset: const Offset(0, 2), decoration: BoxDecoration(
), borderRadius: BorderRadius.circular(10.0),
], boxShadow: [
), BoxShadow(
child: ClipRRect( color: Colors.black.withOpacity(0.1),
borderRadius: BorderRadius.circular(10.0), blurRadius: 4,
child: Stack( offset: const Offset(0, 2),
fit: StackFit.expand,
children: [
//
NetworkOrAssetImage(
imageUrl: item['firstFrameImg'] ?? item['cover'],
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
placeholderAsset: 'assets/images/bk.jpg',
),
//
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 40,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black.withOpacity(0.6),
Colors.transparent,
],
),
),
),
),
//
Positioned(
right: 8,
bottom: 8,
child: Row(
children: [
const Icon(
Icons.favorite,
color: Colors.white,
size: 16,
),
const SizedBox(width: 4),
Text(
'${item['likeCounts'] ?? 0}',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
), ),
], ],
), ),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Stack(
fit: StackFit.expand,
children: [
//
NetworkOrAssetImage(
imageUrl: item['firstFrameImg'] ?? item['cover'],
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
placeholderAsset: 'assets/images/bk.jpg',
),
//
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 40,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black.withOpacity(0.6),
Colors.transparent,
],
),
),
),
),
//
Positioned(
right: 8,
bottom: 8,
child: Row(
children: [
const Icon(
Icons.favorite,
color: Colors.white,
size: 16,
),
const SizedBox(width: 4),
Text(
'${item['likeCounts'] ?? 0}',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
),
), ),
), );
); },
}, childCount: listToShow.length,
childCount: listToShow.length, ),
), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3,
crossAxisCount: 3, crossAxisSpacing: 10.0,
crossAxisSpacing: 10.0, mainAxisSpacing: 10.0,
mainAxisSpacing: 10.0, childAspectRatio: 0.6, // 1=
childAspectRatio: 0.7, // ),
), ),
), ),
), SliverToBoxAdapter(
SliverToBoxAdapter( child: Padding(
child: Padding( padding: const EdgeInsets.symmetric(vertical: 20.0),
padding: const EdgeInsets.symmetric(vertical: 20.0), child: Center(
child: Center( child: Obx(
child: params.hasMore ? const CircularProgressIndicator() : const Text('没有更多数据了'), () {
if (params.isLoading.value) {
return SafeArea(top: false, child: CircularProgressIndicator());
} else if (!params.hasMore.value) {
return SafeArea(top: false, child: Text('没有更多数据了'));
} else {
return SizedBox(height: 20);
}
},
),
),
), ),
), ),
), ],
], ),
); );
} }