feat: 用户拉黑功能 issues #107

This commit is contained in:
guozhigq
2023-09-12 22:49:59 +08:00
parent 838467451b
commit fff54a55a1
5 changed files with 225 additions and 84 deletions

View File

@ -97,6 +97,9 @@ class Api {
// 操作用户关系 // 操作用户关系
static const String relationMod = '/x/relation/modify'; static const String relationMod = '/x/relation/modify';
// 相互关系查询
static const String relationSearch = '/x/space/wbi/acc/relation';
// 评论列表 // 评论列表
// https://api.bilibili.com/x/v2/reply/main?csrf=6e22efc1a47225ea25f901f922b5cfdd&mode=3&oid=254175381&pagination_str=%7B%22offset%22:%22%22%7D&plat=1&seek_rpid=0&type=11 // https://api.bilibili.com/x/v2/reply/main?csrf=6e22efc1a47225ea25f901f922b5cfdd&mode=3&oid=254175381&pagination_str=%7B%22offset%22:%22%22%7D&plat=1&seek_rpid=0&type=11
static const String replyList = '/x/v2/reply'; static const String replyList = '/x/v2/reply';

View File

@ -8,6 +8,7 @@ import 'package:pilipala/models/user/fav_folder.dart';
import 'package:pilipala/models/user/history.dart'; import 'package:pilipala/models/user/history.dart';
import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/user/info.dart';
import 'package:pilipala/models/user/stat.dart'; import 'package:pilipala/models/user/stat.dart';
import 'package:pilipala/utils/wbi_sign.dart';
class UserHttp { class UserHttp {
static Future<dynamic> userStat({required int mid}) async { static Future<dynamic> userStat({required int mid}) async {
@ -248,4 +249,29 @@ class UserHttp {
return {'status': false, 'msg': res.data['message']}; return {'status': false, 'msg': res.data['message']};
} }
} }
// 相互关系查询
static Future relationSearch(int mid) async {
Map params = await WbiSign().makSign({
'mid': mid,
'token': '',
'platform': 'web',
'web_location': 1550101,
});
var res = await Request().get(
Api.relationSearch,
data: {
'mid': mid,
'w_rid': params['w_rid'],
'wts': params['wts'],
},
);
if (res.data['code'] == 0) {
// relation 主动状态
// 被动状态
return {'status': true, 'data': res.data['data']};
} else {
return {'status': false, 'msg': res.data['message']};
}
}
} }

View File

@ -3,10 +3,12 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:pilipala/http/member.dart'; import 'package:pilipala/http/member.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/http/video.dart'; import 'package:pilipala/http/video.dart';
import 'package:pilipala/models/member/archive.dart'; import 'package:pilipala/models/member/archive.dart';
import 'package:pilipala/models/member/info.dart'; import 'package:pilipala/models/member/info.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
import 'package:share_plus/share_plus.dart';
class MemberController extends GetxController { class MemberController extends GetxController {
late int mid; late int mid;
@ -19,6 +21,8 @@ class MemberController extends GetxController {
// 投稿列表 // 投稿列表
RxList<VListItemModel>? archiveList = [VListItemModel()].obs; RxList<VListItemModel>? archiveList = [VListItemModel()].obs;
var userInfo; var userInfo;
RxInt attribute = (-1).obs;
RxString attributeText = '关注'.obs;
@override @override
void onInit() { void onInit() {
@ -28,6 +32,7 @@ class MemberController extends GetxController {
ownerMid = userInfo != null ? userInfo.mid : -1; ownerMid = userInfo != null ? userInfo.mid : -1;
face = Get.arguments['face'] ?? ''; face = Get.arguments['face'] ?? '';
heroTag = Get.arguments['heroTag'] ?? ''; heroTag = Get.arguments['heroTag'] ?? '';
relationSearch();
} }
// 获取用户信息 // 获取用户信息
@ -63,7 +68,10 @@ class MemberController extends GetxController {
SmartDialog.showToast('账号未登录'); SmartDialog.showToast('账号未登录');
return; return;
} }
if (attribute.value == 128) {
blockUser();
return;
}
SmartDialog.show( SmartDialog.show(
useSystem: true, useSystem: true,
animationType: SmartAnimationType.centerFade_otherSlide, animationType: SmartAnimationType.centerFade_otherSlide,
@ -73,8 +81,12 @@ class MemberController extends GetxController {
content: Text(memberInfo.value.isFollowed! ? '取消关注UP主?' : '关注UP主?'), content: Text(memberInfo.value.isFollowed! ? '取消关注UP主?' : '关注UP主?'),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => SmartDialog.dismiss(), onPressed: () => SmartDialog.dismiss(),
child: const Text('点错了')), child: Text(
'点错了',
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton( TextButton(
onPressed: () async { onPressed: () async {
await VideoHttp.relationMod( await VideoHttp.relationMod(
@ -83,8 +95,7 @@ class MemberController extends GetxController {
reSrc: 11, reSrc: 11,
); );
memberInfo.value.isFollowed = !memberInfo.value.isFollowed!; memberInfo.value.isFollowed = !memberInfo.value.isFollowed!;
SmartDialog.dismiss(); relationSearch();
SmartDialog.showLoading();
SmartDialog.dismiss(); SmartDialog.dismiss();
memberInfo.update((val) {}); memberInfo.update((val) {});
}, },
@ -95,4 +106,69 @@ class MemberController extends GetxController {
}, },
); );
} }
// 关系查询
Future relationSearch() async {
if (userInfo == null) return;
var res = await UserHttp.relationSearch(mid);
if (res['status']) {
attribute.value = res['data']['relation']['attribute'];
attributeText.value = attribute.value == 0
? '关注'
: attribute.value == 2
? '已关注'
: attribute.value == 2
? '已互粉'
: '已拉黑';
}
}
// 拉黑用户
Future blockUser() async {
if (userInfo == null) {
SmartDialog.showToast('账号未登录');
return;
}
SmartDialog.show(
useSystem: true,
animationType: SmartAnimationType.centerFade_otherSlide,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('提示'),
content: Text(attribute.value != 128 ? '确定拉黑UP主?' : '从黑名单移除UP主'),
actions: [
TextButton(
onPressed: () => SmartDialog.dismiss(),
child: Text(
'点错了',
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
onPressed: () async {
var res = await VideoHttp.relationMod(
mid: mid,
act: attribute.value != 128 ? 5 : 6,
reSrc: 11,
);
SmartDialog.dismiss();
if (res['status']) {
attribute.value = attribute.value != 128 ? 128 : 0;
attributeText.value = attribute.value == 128 ? '已拉黑' : '关注';
memberInfo.value.isFollowed = false;
relationSearch();
memberInfo.update((val) {});
}
},
child: const Text('确认'),
)
],
);
},
);
}
void shareUser() {
Share.share('${memberInfo.value.name} - https://space.bilibili.com/$mid');
}
} }

View File

@ -102,7 +102,35 @@ class _MemberPageState extends State<MemberPage>
}, },
), ),
actions: [ actions: [
IconButton(onPressed: () {}, icon: const Icon(Icons.more_vert)), PopupMenuButton(
icon: const Icon(Icons.more_vert),
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
PopupMenuItem(
onTap: () => _memberController.blockUser(),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.block, size: 19),
const SizedBox(width: 10),
Text(_memberController.attribute.value != 128
? '加入黑名单'
: '移除黑名单'),
],
),
),
PopupMenuItem(
onTap: () => _memberController.shareUser(),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.share_outlined, size: 19),
SizedBox(width: 10),
Text('分享UP主'),
],
),
),
],
),
const SizedBox(width: 4), const SizedBox(width: 4),
], ],
flexibleSpace: FlexibleSpaceBar( flexibleSpace: FlexibleSpaceBar(

View File

@ -15,62 +15,63 @@ Widget profile(ctr, {loadingStatus = false}) {
child: Row( child: Row(
children: [ children: [
Hero( Hero(
tag: ctr.heroTag!, tag: ctr.heroTag!,
child: Stack( child: Stack(
children: [ children: [
NetworkImgLayer( NetworkImgLayer(
width: 90, width: 90,
height: 90, height: 90,
type: 'avatar', type: 'avatar',
src: !loadingStatus ? memberInfo.face : ctr.face, src: !loadingStatus ? memberInfo.face : ctr.face,
), ),
if (!loadingStatus && if (!loadingStatus &&
memberInfo.liveRoom != null && memberInfo.liveRoom != null &&
memberInfo.liveRoom!.liveStatus == 1) memberInfo.liveRoom!.liveStatus == 1)
Positioned( Positioned(
bottom: 0, bottom: 0,
left: 14, left: 14,
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
LiveItemModel liveItem = LiveItemModel.fromJson({ LiveItemModel liveItem = LiveItemModel.fromJson({
'title': memberInfo.liveRoom!.title, 'title': memberInfo.liveRoom!.title,
'uname': memberInfo.name, 'uname': memberInfo.name,
'face': memberInfo.face, 'face': memberInfo.face,
'roomid': memberInfo.liveRoom!.roomId, 'roomid': memberInfo.liveRoom!.roomId,
'watched_show': memberInfo.liveRoom!.watchedShow, 'watched_show': memberInfo.liveRoom!.watchedShow,
}); });
Get.toNamed( Get.toNamed(
'/liveRoom?roomid=${memberInfo.liveRoom!.roomId}', '/liveRoom?roomid=${memberInfo.liveRoom!.roomId}',
arguments: {'liveItem': liveItem}, arguments: {'liveItem': liveItem},
); );
}, },
child: Container( child: Container(
padding: const EdgeInsets.fromLTRB(6, 2, 6, 2), padding: const EdgeInsets.fromLTRB(6, 2, 6, 2),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
borderRadius: borderRadius:
const BorderRadius.all(Radius.circular(10)), const BorderRadius.all(Radius.circular(10)),
),
child: Row(children: [
Image.asset(
'assets/images/live.gif',
height: 10,
),
Text(
' 直播中',
style: TextStyle(
color: Colors.white,
fontSize: Theme.of(context)
.textTheme
.labelSmall!
.fontSize),
)
]),
), ),
child: Row(children: [
Image.asset(
'assets/images/live.gif',
height: 10,
),
Text(
' 直播中',
style: TextStyle(
color: Colors.white,
fontSize: Theme.of(context)
.textTheme
.labelSmall!
.fontSize),
)
]),
), ),
) ),
], )
)), ],
),
),
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: Column( child: Column(
@ -152,34 +153,41 @@ Widget profile(ctr, {loadingStatus = false}) {
if (ctr.ownerMid != ctr.mid) ...[ if (ctr.ownerMid != ctr.mid) ...[
Row( Row(
children: [ children: [
TextButton( Obx(
onPressed: () => ctr.actionRelationMod(), () => Expanded(
style: TextButton.styleFrom( child: TextButton(
padding: const EdgeInsets.only(left: 42, right: 42), onPressed: () => ctr.actionRelationMod(),
foregroundColor: style: TextButton.styleFrom(
!loadingStatus && memberInfo.isFollowed! foregroundColor: ctr.attribute.value == -1
? Theme.of(context).colorScheme.outline ? Colors.transparent
: Theme.of(context).colorScheme.onPrimary, : ctr.attribute.value != 0
backgroundColor: !loadingStatus && ? Theme.of(context).colorScheme.outline
memberInfo.isFollowed! : Theme.of(context)
? Theme.of(context).colorScheme.onInverseSurface .colorScheme
: Theme.of(context) .onPrimary,
.colorScheme backgroundColor: ctr.attribute.value != 0
.primary, // 设置按钮背景色 ? Theme.of(context)
.colorScheme
.onInverseSurface
: Theme.of(context)
.colorScheme
.primary, // 设置按钮背景色
),
child: Obx(() => Text(ctr.attributeText.value)),
),
), ),
child: Text(!loadingStatus && memberInfo.isFollowed!
? '取关'
: '关注'),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
TextButton( Expanded(
onPressed: () {}, child: TextButton(
style: TextButton.styleFrom( onPressed: () {},
padding: const EdgeInsets.only(left: 42, right: 42), style: TextButton.styleFrom(
backgroundColor: backgroundColor: Theme.of(context)
Theme.of(context).colorScheme.onInverseSurface, .colorScheme
.onInverseSurface,
),
child: const Text('发消息'),
), ),
child: const Text('发消息'),
) )
], ],
) )