From 170b2aa6d9a883c3f887882e4db6f05212558e9e Mon Sep 17 00:00:00 2001 From: My-Responsitories <107370289+My-Responsitories@users.noreply.github.com> Date: Tue, 5 Aug 2025 20:52:11 +0800 Subject: [PATCH] opt: GroupPanel (#940) * opt: GroupPanel * mod: int? operator --- lib/http/member.dart | 13 +++---- lib/models/member/tags.dart | 4 +- lib/pages/article/controller.dart | 11 +++--- lib/pages/follow/controller.dart | 9 ++--- lib/pages/group_panel/view.dart | 61 +++++++++++-------------------- lib/utils/extension.dart | 5 +++ lib/utils/request_utils.dart | 4 +- 7 files changed, 44 insertions(+), 63 deletions(-) diff --git a/lib/http/member.dart b/lib/http/member.dart index 7062bb0d6..db00de766 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -466,17 +466,16 @@ class MemberHttp { } // 查询分组 - static Future followUpTags() async { + static Future>> followUpTags() async { var res = await Request().get(Api.followUpTag); if (res.data['code'] == 0) { - return { - 'status': true, - 'data': res.data['data'] - .map((e) => MemberTagItemModel.fromJson(e)) + return Success( + (res.data['data'] as List) + .map((e) => MemberTagItemModel.fromJson(e)) .toList(), - }; + ); } else { - return {'status': false, 'msg': res.data['message']}; + return Error(res.data['message']); } } diff --git a/lib/models/member/tags.dart b/lib/models/member/tags.dart index 0e7eaa431..e6c9c4daa 100644 --- a/lib/models/member/tags.dart +++ b/lib/models/member/tags.dart @@ -1,6 +1,4 @@ -import 'package:PiliPlus/pages/common/multi_select/base.dart'; - -class MemberTagItemModel with MultiSelectData { +class MemberTagItemModel { MemberTagItemModel({ this.count, this.name, diff --git a/lib/pages/article/controller.dart b/lib/pages/article/controller.dart index f072e29f3..6802795d5 100644 --- a/lib/pages/article/controller.dart +++ b/lib/pages/article/controller.dart @@ -13,6 +13,7 @@ import 'package:PiliPlus/models_new/article/article_info/data.dart'; import 'package:PiliPlus/models_new/article/article_view/data.dart'; import 'package:PiliPlus/pages/common/dyn/common_dyn_controller.dart'; import 'package:PiliPlus/utils/accounts.dart'; +import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/url_utils.dart'; import 'package:flutter/rendering.dart' show ScrollDirection; @@ -194,11 +195,10 @@ class ArticleController extends CommonDynController { : await FavHttp.communityAction(opusId: id, action: isFav ? 4 : 3); if (res['status']) { favorite?.status = !isFav; - var count = favorite?.count ?? 0; if (isFav) { - favorite?.count = count - 1; + favorite?.count--; } else { - favorite?.count = count + 1; + favorite?.count++; } stats.refresh(); SmartDialog.showToast('${isFav ? '取消' : ''}收藏成功'); @@ -216,11 +216,10 @@ class ArticleController extends CommonDynController { ); if (res['status']) { like?.status = !isLike; - int count = like?.count ?? 0; if (isLike) { - like?.count = count - 1; + like?.count--; } else { - like?.count = count + 1; + like?.count++; } stats.refresh(); SmartDialog.showToast(!isLike ? '点赞成功' : '取消赞'); diff --git a/lib/pages/follow/controller.dart b/lib/pages/follow/controller.dart index 489d781d7..728b7d34e 100644 --- a/lib/pages/follow/controller.dart +++ b/lib/pages/follow/controller.dart @@ -32,11 +32,10 @@ class FollowController extends GetxController with GetTickerProviderStateMixin { Future queryFollowUpTags() async { var res = await MemberHttp.followUpTags(); - if (res['status']) { + if (res.isSuccess) { tabs - ..clear() - ..addAll(res['data']) - ..insert(0, MemberTagItemModel(name: '全部关注')); + ..assign(MemberTagItemModel(name: '全部关注')) + ..addAll(res.data); int initialIndex = 0; if (tabController != null) { initialIndex = tabController!.index.clamp(0, tabs.length - 1); @@ -49,7 +48,7 @@ class FollowController extends GetxController with GetTickerProviderStateMixin { ); followState.value = Success(tabs.hashCode); } else { - followState.value = Error(res['msg']); + followState.value = res; } } diff --git a/lib/pages/group_panel/view.dart b/lib/pages/group_panel/view.dart index f611e81bf..3fa906cf8 100644 --- a/lib/pages/group_panel/view.dart +++ b/lib/pages/group_panel/view.dart @@ -2,18 +2,19 @@ import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/member.dart'; import 'package:PiliPlus/models/member/tags.dart'; +import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; class GroupPanel extends StatefulWidget { - final int? mid; + final int mid; final List? tags; final ScrollController? scrollController; const GroupPanel({ super.key, - this.mid, + required this.mid, this.tags, this.scrollController, }); @@ -23,9 +24,9 @@ class GroupPanel extends StatefulWidget { } class _GroupPanelState extends State { - LoadingState> loadingState = - LoadingState>.loading(); + LoadingState> loadingState = LoadingState.loading(); RxBool showDefaultBtn = true.obs; + late final Set tags = widget.tags?.cast().toSet() ?? {}; @override void initState() { @@ -36,19 +37,8 @@ class _GroupPanelState extends State { void _query() { MemberHttp.followUpTags().then((res) { if (mounted) { - if (res['status']) { - List tagsList = - (res['data'] as List) - ..removeWhere((item) => item.tagid == 0) - ..map((item) { - return item.checked = - widget.tags?.contains(item.tagid) == true; - }).toList(); - showDefaultBtn.value = !tagsList.any((e) => e.checked == true); - loadingState = Success(tagsList); - } else { - loadingState = Error(res['msg']); - } + loadingState = res..dataOrNull.removeFirstWhere((e) => e.tagid == 0); + showDefaultBtn.value = tags.isEmpty; setState(() {}); } }); @@ -60,28 +50,14 @@ class _GroupPanelState extends State { return; } feedBack(); - // 是否有选中的 有选中的带id,没选使用默认0 - List tagsList = loadingState.data; - final bool anyHasChecked = tagsList.any( - (MemberTagItemModel e) => e.checked == true, - ); - late List tagidList; - if (anyHasChecked) { - final List checkedList = tagsList - .where((MemberTagItemModel e) => e.checked == true) - .toList(); - tagidList = checkedList.map((e) => e.tagid!).toList(); - } else { - tagidList = [0]; - } // 保存 final res = await MemberHttp.addUsers( widget.mid.toString(), - tagidList.join(','), + tags.isEmpty ? '0' : tags.join(','), ); SmartDialog.showToast(res['msg']); if (res['status']) { - Get.back(result: tagidList); + Get.back(result: tags); } } @@ -98,11 +74,16 @@ class _GroupPanelState extends State { child: Builder( builder: (context) { void onTap() { - item.checked = !item.checked!; + final tagid = item.tagid!; + if (tags.contains(tagid)) { + tags.remove(tagid); + item.count--; + } else { + tags.add(tagid); + item.count++; + } (context as Element).markNeedsBuild(); - showDefaultBtn.value = !response.any( - (e) => e.checked == true, - ); + showDefaultBtn.value = tags.isEmpty; } return ListTile( @@ -110,15 +91,15 @@ class _GroupPanelState extends State { dense: true, leading: const Icon(Icons.group_outlined), minLeadingWidth: 0, - title: Text(item.name ?? ''), + title: Text('${item.name} (${item.count})'), subtitle: item.tip?.isNotEmpty == true ? Text(item.tip!) : null, trailing: Transform.scale( scale: 0.9, child: Checkbox( - value: item.checked, - onChanged: (bool? checkValue) => onTap(), + value: tags.contains(item.tagid), + onChanged: (_) => onTap(), ), ), ); diff --git a/lib/utils/extension.dart b/lib/utils/extension.dart index 124436709..4a5185599 100644 --- a/lib/utils/extension.dart +++ b/lib/utils/extension.dart @@ -19,6 +19,11 @@ extension ImageExtension on num? { } } +extension IntExt on int? { + int? operator +(int other) => this == null ? null : this! + other; + int? operator -(int other) => this == null ? null : this! - other; +} + extension ScrollControllerExt on ScrollController { void animToTop() { if (!hasClients) return; diff --git a/lib/utils/request_utils.dart b/lib/utils/request_utils.dart index fb24c5ea5..f8531b9b2 100644 --- a/lib/utils/request_utils.dart +++ b/lib/utils/request_utils.dart @@ -158,7 +158,7 @@ class RequestUtils { dense: true, onTap: () async { Get.back(); - var result = await showModalBottomSheet( + var result = await showModalBottomSheet>( context: context, useSafeArea: true, isScrollControlled: true, @@ -190,7 +190,7 @@ class RequestUtils { ); }, ); - followStatus!['tag'] = result; + followStatus!['tag'] = result?.toList(); if (result != null) { callback?.call(result.contains(-10) ? -10 : 2); }