2025-08-21 10:50:38 +08:00
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
|
import 'package:loopin/api/shop_api.dart';
|
|
|
|
|
import 'package:loopin/service/http.dart';
|
|
|
|
|
|
|
|
|
|
/// 单个 Tab 的状态
|
|
|
|
|
class TabState {
|
|
|
|
|
final ScrollController scrollController;
|
|
|
|
|
final RxInt currentPage;
|
|
|
|
|
final RxDouble scrollOffset;
|
|
|
|
|
final RxList dataList;
|
|
|
|
|
final RxBool isLoading;
|
|
|
|
|
final RxBool hasLoaded;
|
|
|
|
|
|
|
|
|
|
TabState({
|
|
|
|
|
required this.scrollController,
|
|
|
|
|
required this.currentPage,
|
|
|
|
|
required this.scrollOffset,
|
|
|
|
|
required this.dataList,
|
|
|
|
|
required this.isLoading,
|
|
|
|
|
required this.hasLoaded,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ShopIndexController extends GetxController with GetSingleTickerProviderStateMixin {
|
|
|
|
|
TabController? tabController;
|
|
|
|
|
|
|
|
|
|
///轮播图数据
|
|
|
|
|
RxList<dynamic> swiperData = <dynamic>[].obs;
|
|
|
|
|
|
|
|
|
|
/// tab 分类列表
|
|
|
|
|
RxList<dynamic> tabList = <dynamic>[].obs;
|
|
|
|
|
|
|
|
|
|
/// 每个 tab 对应的状态
|
|
|
|
|
final Map<int, TabState> tabs = {};
|
|
|
|
|
|
|
|
|
|
/// 当前 tab index
|
|
|
|
|
RxInt currentTabIndex = 0.obs;
|
|
|
|
|
|
|
|
|
|
/// 初始化 Tab 分类
|
2025-08-26 17:38:59 +08:00
|
|
|
|
void initTabs({required TickerProvider vsync}) async {
|
2025-08-21 10:50:38 +08:00
|
|
|
|
// 释放旧的 ScrollController
|
|
|
|
|
tabs.forEach((_, state) => state.scrollController.dispose());
|
|
|
|
|
tabs.clear();
|
|
|
|
|
tabList.clear();
|
|
|
|
|
// 先释放旧 TabController(并移除监听)
|
|
|
|
|
tabController?.removeListener(_tabListener);
|
|
|
|
|
tabController?.dispose();
|
|
|
|
|
|
|
|
|
|
// 赋值 tab 数据
|
|
|
|
|
final res = await Http.post(ShopApi.shopCategory, data: {
|
2025-08-26 17:38:59 +08:00
|
|
|
|
'level': 1,
|
2025-08-21 10:50:38 +08:00
|
|
|
|
});
|
2025-08-26 17:38:59 +08:00
|
|
|
|
final data = res['data'] as List<dynamic>;
|
|
|
|
|
// logger.w(data);
|
2025-08-21 10:50:38 +08:00
|
|
|
|
tabList.addAll(data);
|
|
|
|
|
|
|
|
|
|
// 初始化每个 tab 的状态
|
|
|
|
|
for (int i = 0; i < tabList.length; i++) {
|
|
|
|
|
final controller = ScrollController();
|
|
|
|
|
tabs[i] = TabState(
|
|
|
|
|
scrollController: controller,
|
|
|
|
|
currentPage: 1.obs,
|
|
|
|
|
scrollOffset: 0.0.obs,
|
|
|
|
|
dataList: <dynamic>[].obs,
|
|
|
|
|
isLoading: false.obs,
|
|
|
|
|
hasLoaded: false.obs,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建新的 TabController
|
2025-08-26 17:38:59 +08:00
|
|
|
|
tabController = TabController(length: tabList.length, vsync: vsync);
|
|
|
|
|
|
|
|
|
|
tabController?.addListener(_tabListener);
|
2025-08-21 10:50:38 +08:00
|
|
|
|
// 初始化第一个 tab 的数据
|
|
|
|
|
if (tabList.isNotEmpty) {
|
|
|
|
|
loadSwiperData();
|
|
|
|
|
loadData(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Tab 切换监听
|
|
|
|
|
void _tabListener() {
|
|
|
|
|
if (!tabController!.indexIsChanging) {
|
|
|
|
|
currentTabIndex.value = tabController!.index;
|
|
|
|
|
|
|
|
|
|
final tab = tabs[currentTabIndex.value];
|
|
|
|
|
if (tab != null && !tab.hasLoaded.value) {
|
|
|
|
|
loadData(currentTabIndex.value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> refreshData(int index) async {
|
|
|
|
|
await loadSwiperData();
|
|
|
|
|
final tab = tabs[index];
|
|
|
|
|
if (tab == null) return;
|
|
|
|
|
|
|
|
|
|
tab.currentPage.value = 1;
|
|
|
|
|
tab.dataList.clear();
|
|
|
|
|
tab.isLoading.value = false;
|
|
|
|
|
tab.hasLoaded.value = false;
|
|
|
|
|
|
|
|
|
|
await loadData(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 加载pageview数据
|
|
|
|
|
Future<void> loadData(int index) async {
|
|
|
|
|
final tab = tabs[index];
|
|
|
|
|
if (tab == null || tab.isLoading.value) return;
|
|
|
|
|
|
|
|
|
|
tab.isLoading.value = true;
|
|
|
|
|
final res = await Http.post(ShopApi.shopList, data: {
|
|
|
|
|
'size': 10,
|
|
|
|
|
'current': tab.currentPage.value,
|
|
|
|
|
'categoryId': tabList[index]['id'],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
final data = res['data']['records'];
|
|
|
|
|
tab.dataList.addAll(data);
|
2025-08-26 17:38:59 +08:00
|
|
|
|
// logger.w(res);
|
2025-08-21 10:50:38 +08:00
|
|
|
|
|
|
|
|
|
tab.currentPage.value += 1;
|
|
|
|
|
tab.isLoading.value = false;
|
|
|
|
|
tab.hasLoaded.value = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 加载swiper数据
|
|
|
|
|
Future<void> loadSwiperData() async {
|
|
|
|
|
final res = await Http.post(ShopApi.shopSwiperList, data: {
|
|
|
|
|
'type': 1,
|
|
|
|
|
});
|
|
|
|
|
final data = res['data'];
|
2025-08-26 17:38:59 +08:00
|
|
|
|
// logger.w(res);
|
2025-08-21 10:50:38 +08:00
|
|
|
|
swiperData.assignAll(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void onClose() {
|
|
|
|
|
tabController?.removeListener(_tabListener);
|
|
|
|
|
tabs.forEach((_, state) => state.scrollController.dispose());
|
|
|
|
|
super.onClose();
|
|
|
|
|
}
|
|
|
|
|
}
|