feat: sort user search

This commit is contained in:
bggRGjQaUbCoE
2024-09-28 11:57:05 +08:00
parent 9e8ce5b093
commit 80f8c88d0d
4 changed files with 195 additions and 11 deletions

View File

@@ -76,6 +76,8 @@ class SearchHttp {
String? order,
int? duration,
int? tids,
int? orderSort,
int? userType,
}) async {
var reqData = {
'search_type': searchType.type,
@@ -83,9 +85,11 @@ class SearchHttp {
// 'order_sort': 0,
// 'user_type': 0,
'page': page,
if (order != null) 'order': order,
if (order != null && order.isNotEmpty) 'order': order,
if (duration != null) 'duration': duration,
if (tids != null) 'tids': tids,
if (orderSort != null) 'order_sort': orderSort,
if (userType != null) 'user_type': userType,
};
var res = await Request().get(Api.searchByType, data: reqData);
if (res.data['code'] == 0 && res.data['data']['numPages'] > 0) {

View File

@@ -15,6 +15,8 @@ class SearchPanelController extends CommonController {
// 视频时长筛选 仅用于搜索视频
RxInt duration = 0.obs;
int? tids;
int? orderSort;
int? userType;
@override
void onInit() {
@@ -68,8 +70,10 @@ class SearchPanelController extends CommonController {
searchType: searchType!,
keyword: keyword!,
page: currentPage,
order: searchType!.type != 'video' ? null : order.value,
order: order.value,
duration: searchType!.type != 'video' ? null : duration.value,
tids: tids,
orderSort: orderSort,
userType: userType,
);
}

View File

@@ -1,4 +1,9 @@
import 'package:PiliPalaX/pages/search/widgets/search_text.dart';
import 'package:PiliPalaX/pages/search_panel/controller.dart';
import 'package:PiliPalaX/pages/video/detail/reply/view.dart'
show MySliverPersistentHeaderDelegate;
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:PiliPalaX/common/widgets/network_img_layer.dart';
import 'package:PiliPalaX/utils/utils.dart';
@@ -6,12 +11,66 @@ import 'package:PiliPalaX/utils/utils.dart';
import '../../../common/constants.dart';
import '../../../utils/grid.dart';
Widget searchUserPanel(BuildContext context, ctr, list) {
Widget searchUserPanel(BuildContext context, searchPanelCtr, list) {
TextStyle style = TextStyle(
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
color: Theme.of(context).colorScheme.outline);
final ctr = Get.put(UserPanelController());
return CustomScrollView(controller: ctr.scrollController, slivers: [
return CustomScrollView(
controller: searchPanelCtr.scrollController,
slivers: [
SliverPersistentHeader(
pinned: false,
floating: true,
delegate: MySliverPersistentHeaderDelegate(
child: Container(
height: 40,
color: Theme.of(context).colorScheme.surface,
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
children: [
Obx(
() => Text(
'排序: ${ctr.orderFiltersList[ctr.currentOrderFilterval.value]['label']}',
maxLines: 1,
style:
TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
const Spacer(),
Obx(
() => Text(
'用户类型: ${ctr.userTypeFiltersList[ctr.currentUserTypeFilterval.value]['label']}',
maxLines: 1,
style:
TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
const Spacer(),
SizedBox(
width: 32,
height: 32,
child: IconButton(
tooltip: '筛选',
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: () {
ctr.onShowFilterDialog(context, searchPanelCtr);
},
icon: Icon(
Icons.filter_list_outlined,
size: 18,
color: Theme.of(context).colorScheme.primary,
),
),
),
],
),
),
),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
mainAxisSpacing: StyleString.cardSpace,
@@ -77,6 +136,123 @@ Widget searchUserPanel(BuildContext context, ctr, list) {
);
},
childCount: list!.length,
))
]);
),
)
],
);
}
class UserPanelController extends GetxController {
List orderFiltersList = [
{'label': '默认排序', 'value': 0, 'orderSort': 0, 'order': ''},
{'label': '粉丝数由高到低', 'value': 1, 'orderSort': 0, 'order': 'fans'},
{'label': '粉丝数由低到高', 'value': 2, 'orderSort': 1, 'order': 'fans'},
{'label': 'Lv等级由高到低', 'value': 3, 'orderSort': 0, 'order': 'level'},
{'label': 'Lv等级由低到高', 'value': 4, 'orderSort': 1, 'order': 'level'},
];
List userTypeFiltersList = [
{'label': '全部用户', 'value': 0, 'userType': 0},
{'label': 'UP主', 'value': 1, 'userType': 1},
{'label': '普通用户', 'value': 2, 'userType': 2},
{'label': '认证用户', 'value': 3, 'userType': 3},
];
RxInt currentOrderFilterval = 0.obs;
RxInt currentUserTypeFilterval = 0.obs;
onShowFilterDialog(
BuildContext context,
SearchPanelController searchPanelCtr,
) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) => SingleChildScrollView(
child: Container(
width: double.infinity,
padding: EdgeInsets.only(
top: 20,
left: 16,
right: 16,
bottom: 80 + MediaQuery.of(context).padding.bottom,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 10),
const Text('用户粉丝数及等级排序顺序', style: TextStyle(fontSize: 16)),
const SizedBox(height: 10),
Wrap(
spacing: 8,
runSpacing: 8,
children: orderFiltersList
.map(
(item) => SearchText(
searchText: item['label'],
onSelect: (_) async {
Get.back();
currentOrderFilterval.value = item['value'];
SmartDialog.dismiss();
SmartDialog.showToast("${item['label']}」的筛选结果");
SearchPanelController ctr =
Get.find<SearchPanelController>(
tag: 'bili_user${searchPanelCtr.keyword!}');
ctr.orderSort = item['orderSort'];
ctr.order.value = item['order'];
SmartDialog.showLoading(msg: 'loading');
await ctr.onRefresh();
SmartDialog.dismiss();
},
onLongSelect: (_) {},
bgColor: item['value'] == currentOrderFilterval.value
? Theme.of(context).colorScheme.primaryContainer
: null,
textColor: item['value'] == currentOrderFilterval.value
? Theme.of(context).colorScheme.onPrimaryContainer
: null,
),
)
.toList(),
),
const SizedBox(height: 20),
const Text('用户分类', style: TextStyle(fontSize: 16)),
const SizedBox(height: 10),
Wrap(
spacing: 8,
runSpacing: 8,
children: userTypeFiltersList
.map(
(item) => SearchText(
searchText: item['label'],
onSelect: (_) async {
Get.back();
currentUserTypeFilterval.value = item['value'];
SmartDialog.dismiss();
SmartDialog.showToast("${item['label']}」的筛选结果");
SearchPanelController ctr =
Get.find<SearchPanelController>(
tag: 'bili_user${searchPanelCtr.keyword!}');
ctr.userType = item['userType'];
SmartDialog.showLoading(msg: 'loading');
await ctr.onRefresh();
SmartDialog.dismiss();
},
onLongSelect: (_) {},
bgColor: item['value'] == currentUserTypeFilterval.value
? Theme.of(context).colorScheme.primaryContainer
: null,
textColor: item['value'] ==
currentUserTypeFilterval.value
? Theme.of(context).colorScheme.onPrimaryContainer
: null,
),
)
.toList(),
),
],
),
),
),
);
}
}

View File

@@ -133,7 +133,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
SliverPersistentHeader(
pinned: false,
floating: true,
delegate: _MySliverPersistentHeaderDelegate(
delegate: MySliverPersistentHeaderDelegate(
child: Container(
height: 40,
padding: const EdgeInsets.fromLTRB(12, 0, 6, 0),
@@ -257,8 +257,8 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
}
}
class _MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
_MySliverPersistentHeaderDelegate({required this.child});
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
MySliverPersistentHeaderDelegate({required this.child});
final double _minExtent = 45;
final double _maxExtent = 45;
final Widget child;
@@ -281,7 +281,7 @@ class _MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
double get minExtent => _minExtent;
@override
bool shouldRebuild(covariant _MySliverPersistentHeaderDelegate oldDelegate) {
bool shouldRebuild(covariant MySliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}