mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
refactor: fan
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
|
import 'package:PiliPalaX/http/loading_state.dart';
|
||||||
|
|
||||||
import '../models/fans/result.dart';
|
import '../models/fans/result.dart';
|
||||||
import 'index.dart';
|
import 'index.dart';
|
||||||
|
|
||||||
class FanHttp {
|
class FanHttp {
|
||||||
static Future fans({int? vmid, int? pn, int? ps, String? orderType}) async {
|
static Future<LoadingState> fans(
|
||||||
|
{int? vmid, int? pn, int? ps, String? orderType}) async {
|
||||||
var res = await Request().get(Api.fans, data: {
|
var res = await Request().get(Api.fans, data: {
|
||||||
'vmid': vmid,
|
'vmid': vmid,
|
||||||
'pn': pn,
|
'pn': pn,
|
||||||
@@ -11,13 +14,9 @@ class FanHttp {
|
|||||||
'order_type': orderType,
|
'order_type': orderType,
|
||||||
});
|
});
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': FansDataModel.fromJson(res.data['data'])};
|
return LoadingState.success(FansDataModel.fromJson(res.data['data']));
|
||||||
} else {
|
} else {
|
||||||
return {
|
return LoadingState.error(res.data['message']);
|
||||||
'status': false,
|
|
||||||
'data': [],
|
|
||||||
'msg': res.data['message'],
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:PiliPalaX/http/fan.dart';
|
||||||
|
import 'package:PiliPalaX/http/loading_state.dart';
|
||||||
|
import 'package:PiliPalaX/pages/common/common_controller.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:PiliPalaX/http/fan.dart';
|
|
||||||
import 'package:PiliPalaX/models/fans/result.dart';
|
|
||||||
import 'package:PiliPalaX/utils/storage.dart';
|
import 'package:PiliPalaX/utils/storage.dart';
|
||||||
|
|
||||||
class FansController extends GetxController {
|
class FansController extends CommonController {
|
||||||
Box userInfoCache = GStorage.userInfo;
|
Box userInfoCache = GStorage.userInfo;
|
||||||
int pn = 1;
|
|
||||||
int ps = 20;
|
int ps = 20;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
RxList<FansItemModel> fansList = <FansItemModel>[].obs;
|
|
||||||
late int? mid;
|
late int? mid;
|
||||||
late String? name;
|
late String? name;
|
||||||
dynamic userInfo;
|
dynamic userInfo;
|
||||||
RxString loadingText = '加载中...'.obs;
|
|
||||||
RxBool isOwner = false.obs;
|
RxBool isOwner = false.obs;
|
||||||
|
bool isEnd = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@@ -26,40 +24,44 @@ class FansController extends GetxController {
|
|||||||
: userInfo?.mid;
|
: userInfo?.mid;
|
||||||
isOwner.value = mid == userInfo?.mid;
|
isOwner.value = mid == userInfo?.mid;
|
||||||
name = Get.parameters['name'] ?? userInfo?.uname;
|
name = Get.parameters['name'] ?? userInfo?.uname;
|
||||||
|
|
||||||
|
queryData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future queryFans(type) async {
|
@override
|
||||||
if (type == 'init' || type == 'refresh') {
|
Future onRefresh() {
|
||||||
pn = 1;
|
isEnd = false;
|
||||||
loadingText.value == '加载中...';
|
return super.onRefresh();
|
||||||
}
|
|
||||||
if (loadingText.value == '没有更多了') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var res = await FanHttp.fans(
|
|
||||||
vmid: mid,
|
|
||||||
pn: pn,
|
|
||||||
ps: ps,
|
|
||||||
orderType: 'attention',
|
|
||||||
);
|
|
||||||
if (res['status']) {
|
|
||||||
if (type == 'init') {
|
|
||||||
fansList.value = res['data'].list;
|
|
||||||
total = res['data'].total;
|
|
||||||
} else if (type == 'onLoad') {
|
|
||||||
fansList.addAll(res['data'].list);
|
|
||||||
}
|
|
||||||
print('fansList: ${fansList.length}, total: $total');
|
|
||||||
if ((pn == 1 && total < ps) || res['data'].list.isEmpty) {
|
|
||||||
loadingText.value = '没有更多了';
|
|
||||||
}
|
|
||||||
pn += 1;
|
|
||||||
if (total > ps && pn == 2) {
|
|
||||||
queryFans('onLoad');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SmartDialog.showToast(res['msg']);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future queryData([bool isRefresh = true]) {
|
||||||
|
if (isEnd) {
|
||||||
|
return Future.value();
|
||||||
|
}
|
||||||
|
return super.queryData(isRefresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool customHandleResponse(Success response) {
|
||||||
|
if ((currentPage == 1 && response.response.total < ps) ||
|
||||||
|
response.response.list.isEmpty) {
|
||||||
|
isEnd = true;
|
||||||
|
}
|
||||||
|
List currentList = loadingState.value is Success
|
||||||
|
? (loadingState.value as Success).response
|
||||||
|
: [];
|
||||||
|
loadingState.value = currentPage == 1
|
||||||
|
? LoadingState.success(response.response.list)
|
||||||
|
: LoadingState.success(currentList + response.response.list);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<LoadingState> customGetData() => FanHttp.fans(
|
||||||
|
vmid: mid,
|
||||||
|
pn: currentPage,
|
||||||
|
ps: ps,
|
||||||
|
orderType: 'attention',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import 'package:PiliPalaX/http/loading_state.dart';
|
||||||
import 'package:easy_debounce/easy_throttle.dart';
|
import 'package:easy_debounce/easy_throttle.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:PiliPalaX/common/widgets/http_error.dart';
|
import 'package:PiliPalaX/common/widgets/http_error.dart';
|
||||||
import 'package:PiliPalaX/common/widgets/no_data.dart';
|
import 'package:PiliPalaX/common/widgets/no_data.dart';
|
||||||
import 'package:PiliPalaX/models/fans/result.dart';
|
|
||||||
|
|
||||||
import '../../common/constants.dart';
|
import '../../common/constants.dart';
|
||||||
import '../../utils/grid.dart';
|
import '../../utils/grid.dart';
|
||||||
@@ -20,21 +20,18 @@ class FansPage extends StatefulWidget {
|
|||||||
class _FansPageState extends State<FansPage> {
|
class _FansPageState extends State<FansPage> {
|
||||||
late String mid;
|
late String mid;
|
||||||
late FansController _fansController;
|
late FansController _fansController;
|
||||||
final ScrollController scrollController = ScrollController();
|
|
||||||
Future? _futureBuilderFuture;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
mid = Get.parameters['mid']!;
|
mid = Get.parameters['mid']!;
|
||||||
_fansController = Get.put(FansController(), tag: mid);
|
_fansController = Get.put(FansController(), tag: mid);
|
||||||
_futureBuilderFuture = _fansController.queryFans('init');
|
_fansController.scrollController.addListener(
|
||||||
scrollController.addListener(
|
|
||||||
() async {
|
() async {
|
||||||
if (scrollController.position.pixels >=
|
if (_fansController.scrollController.position.pixels >=
|
||||||
scrollController.position.maxScrollExtent - 200) {
|
_fansController.scrollController.position.maxScrollExtent - 200) {
|
||||||
EasyThrottle.throttle('follow', const Duration(seconds: 1), () {
|
EasyThrottle.throttle('follow', const Duration(seconds: 1), () {
|
||||||
_fansController.queryFans('onLoad');
|
_fansController.onLoadMore();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -43,8 +40,7 @@ class _FansPageState extends State<FansPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
scrollController.removeListener(() {});
|
_fansController.scrollController.removeListener(() {});
|
||||||
scrollController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,58 +58,46 @@ class _FansPageState extends State<FansPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () async => await _fansController.queryFans('init'),
|
onRefresh: () async => await _fansController.onRefresh(),
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
controller: scrollController,
|
controller: _fansController.scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
FutureBuilder(
|
Obx(() => _buildBody(_fansController.loadingState.value)),
|
||||||
future: _futureBuilderFuture,
|
],
|
||||||
builder: (context, snapshot) {
|
),
|
||||||
if (snapshot.connectionState == ConnectionState.done &&
|
|
||||||
snapshot.data != null) {
|
|
||||||
var data = snapshot.data;
|
|
||||||
if (data['status']) {
|
|
||||||
return Obx(() {
|
|
||||||
List<FansItemModel> list = _fansController.fansList;
|
|
||||||
return list.isNotEmpty
|
|
||||||
? SliverGrid(
|
|
||||||
gridDelegate:
|
|
||||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
|
||||||
mainAxisSpacing: StyleString.cardSpace,
|
|
||||||
crossAxisSpacing: StyleString.safeSpace,
|
|
||||||
maxCrossAxisExtent:
|
|
||||||
Grid.maxRowWidth * 2,
|
|
||||||
mainAxisExtent: 56),
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(BuildContext context, int index) {
|
|
||||||
return fanItem(item: list[index]);
|
|
||||||
},
|
|
||||||
childCount: list.length,
|
|
||||||
))
|
|
||||||
: const NoData();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return HttpError(
|
|
||||||
errMsg: data['msg'],
|
|
||||||
fn: () => _fansController.queryFans('init'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 骨架屏
|
|
||||||
return const SliverToBoxAdapter(
|
|
||||||
child: SizedBox(
|
|
||||||
height: 200,
|
|
||||||
child: Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildBody(LoadingState loadingState) {
|
||||||
|
return loadingState is Success
|
||||||
|
? loadingState.response.isNotEmpty
|
||||||
|
? SliverGrid(
|
||||||
|
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
|
mainAxisSpacing: StyleString.cardSpace,
|
||||||
|
crossAxisSpacing: StyleString.safeSpace,
|
||||||
|
maxCrossAxisExtent: Grid.maxRowWidth * 2,
|
||||||
|
mainAxisExtent: 56),
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(BuildContext context, int index) {
|
||||||
|
return fanItem(item: loadingState.response[index]);
|
||||||
|
},
|
||||||
|
childCount: loadingState.response.length,
|
||||||
|
))
|
||||||
|
: const NoData()
|
||||||
|
: loadingState is Error
|
||||||
|
? HttpError(
|
||||||
|
errMsg: loadingState.errMsg,
|
||||||
|
fn: _fansController.onReload,
|
||||||
|
)
|
||||||
|
: const SliverToBoxAdapter(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 200,
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user