mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-30 23:58:13 +08:00
show followee votes
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -974,4 +974,6 @@ class Api {
|
|||||||
static const String sameFollowing = '/x/relation/same/followings';
|
static const String sameFollowing = '/x/relation/same/followings';
|
||||||
|
|
||||||
static const String seasonStatus = '/pgc/view/web/season/user/status';
|
static const String seasonStatus = '/pgc/view/web/season/user/status';
|
||||||
|
|
||||||
|
static const String followeeVotes = '${HttpString.tUrl}/vote_svr/v1/vote_svr/followee_votes';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import 'package:PiliPlus/models_new/dynamic/dyn_reserve_info/data.dart';
|
|||||||
import 'package:PiliPlus/models_new/dynamic/dyn_topic_feed/topic_card_list.dart';
|
import 'package:PiliPlus/models_new/dynamic/dyn_topic_feed/topic_card_list.dart';
|
||||||
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/top_details.dart';
|
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/top_details.dart';
|
||||||
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart';
|
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart';
|
||||||
|
import 'package:PiliPlus/models_new/followee_votes/vote.dart';
|
||||||
import 'package:PiliPlus/utils/accounts.dart';
|
import 'package:PiliPlus/utils/accounts.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:PiliPlus/utils/wbi_sign.dart';
|
import 'package:PiliPlus/utils/wbi_sign.dart';
|
||||||
@@ -385,7 +386,7 @@ class DynamicsHttp {
|
|||||||
static Future<LoadingState<VoteInfo>> doVote({
|
static Future<LoadingState<VoteInfo>> doVote({
|
||||||
required int voteId,
|
required int voteId,
|
||||||
required List<int> votes,
|
required List<int> votes,
|
||||||
bool anonymity = false,
|
bool anonymous = false,
|
||||||
int? dynamicId,
|
int? dynamicId,
|
||||||
}) async {
|
}) async {
|
||||||
final csrf = Accounts.main.csrf;
|
final csrf = Accounts.main.csrf;
|
||||||
@@ -393,7 +394,7 @@ class DynamicsHttp {
|
|||||||
'vote_id': voteId,
|
'vote_id': voteId,
|
||||||
'votes': votes,
|
'votes': votes,
|
||||||
'voter_uid': Accounts.main.mid,
|
'voter_uid': Accounts.main.mid,
|
||||||
'status': anonymity ? 1 : 0,
|
'status': anonymous ? 1 : 0,
|
||||||
'op_bit': 0,
|
'op_bit': 0,
|
||||||
'dynamic_id': dynamicId ?? 0,
|
'dynamic_id': dynamicId ?? 0,
|
||||||
'csrf_token': csrf,
|
'csrf_token': csrf,
|
||||||
@@ -654,4 +655,24 @@ class DynamicsHttp {
|
|||||||
return Error(res.data['message']);
|
return Error(res.data['message']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<LoadingState<List<FolloweeVote>?>> followeeVotes({
|
||||||
|
required dynamic voteId,
|
||||||
|
}) async {
|
||||||
|
final res = await Request().get(
|
||||||
|
Api.followeeVotes,
|
||||||
|
queryParameters: {
|
||||||
|
'vote_id': voteId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return Success(
|
||||||
|
(res.data['data']?['votes'] as List?)
|
||||||
|
?.map((e) => FolloweeVote.fromJson(e))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Error(res.data['message']);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
lib/models_new/followee_votes/vote.dart
Normal file
23
lib/models_new/followee_votes/vote.dart
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
class FolloweeVote {
|
||||||
|
int uid;
|
||||||
|
String name;
|
||||||
|
String face;
|
||||||
|
List<int> votes;
|
||||||
|
int ctime;
|
||||||
|
|
||||||
|
FolloweeVote({
|
||||||
|
required this.uid,
|
||||||
|
required this.name,
|
||||||
|
required this.face,
|
||||||
|
required this.votes,
|
||||||
|
required this.ctime,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory FolloweeVote.fromJson(Map<String, dynamic> json) => FolloweeVote(
|
||||||
|
uid: json['uid'],
|
||||||
|
name: json['name'],
|
||||||
|
face: json['face'],
|
||||||
|
votes: List<int>.from(json['votes']),
|
||||||
|
ctime: json['ctime'],
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:PiliPlus/common/widgets/badge.dart';
|
import 'package:PiliPlus/common/widgets/badge.dart';
|
||||||
import 'package:PiliPlus/common/widgets/dialog/report.dart';
|
import 'package:PiliPlus/common/widgets/dialog/report.dart';
|
||||||
@@ -7,6 +8,8 @@ import 'package:PiliPlus/http/dynamics.dart';
|
|||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/models/common/badge_type.dart';
|
import 'package:PiliPlus/models/common/badge_type.dart';
|
||||||
import 'package:PiliPlus/models/dynamics/vote_model.dart';
|
import 'package:PiliPlus/models/dynamics/vote_model.dart';
|
||||||
|
import 'package:PiliPlus/models_new/followee_votes/vote.dart';
|
||||||
|
import 'package:PiliPlus/utils/accounts.dart';
|
||||||
import 'package:PiliPlus/utils/date_utils.dart';
|
import 'package:PiliPlus/utils/date_utils.dart';
|
||||||
import 'package:PiliPlus/utils/grid.dart';
|
import 'package:PiliPlus/utils/grid.dart';
|
||||||
import 'package:PiliPlus/utils/num_utils.dart';
|
import 'package:PiliPlus/utils/num_utils.dart';
|
||||||
@@ -28,7 +31,7 @@ class VotePanel extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _VotePanelState extends State<VotePanel> {
|
class _VotePanelState extends State<VotePanel> {
|
||||||
bool anonymity = false;
|
late bool anonymous = false;
|
||||||
|
|
||||||
late VoteInfo _voteInfo;
|
late VoteInfo _voteInfo;
|
||||||
late final RxList<int> groupValue =
|
late final RxList<int> groupValue =
|
||||||
@@ -39,11 +42,20 @@ class _VotePanelState extends State<VotePanel> {
|
|||||||
_voteInfo.endTime! * 1000 > DateTime.now().millisecondsSinceEpoch;
|
_voteInfo.endTime! * 1000 > DateTime.now().millisecondsSinceEpoch;
|
||||||
late bool _showPercentage = !_enabled;
|
late bool _showPercentage = !_enabled;
|
||||||
late final _maxCnt = _voteInfo.choiceCnt ?? _voteInfo.options.length;
|
late final _maxCnt = _voteInfo.choiceCnt ?? _voteInfo.options.length;
|
||||||
|
final isLogin = Accounts.main.isLogin;
|
||||||
|
late final Rxn<List<FolloweeVote>> followeeVote = Rxn<List<FolloweeVote>>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_voteInfo = widget.voteInfo;
|
_voteInfo = widget.voteInfo;
|
||||||
|
if (isLogin) {
|
||||||
|
DynamicsHttp.followeeVotes(voteId: _voteInfo.voteId).then((res) {
|
||||||
|
if (mounted && res.isSuccess) {
|
||||||
|
followeeVote.value = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -102,7 +114,7 @@ class _VotePanelState extends State<VotePanel> {
|
|||||||
? () async {
|
? () async {
|
||||||
final res = await widget.callback(
|
final res = await widget.callback(
|
||||||
groupValue.toSet(),
|
groupValue.toSet(),
|
||||||
anonymity,
|
anonymous,
|
||||||
);
|
);
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@@ -124,12 +136,153 @@ class _VotePanelState extends State<VotePanel> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
Widget title = Text(
|
||||||
|
_voteInfo.title ?? '',
|
||||||
|
style: theme.textTheme.titleMedium,
|
||||||
|
);
|
||||||
|
if (isLogin) {
|
||||||
|
title = Row(
|
||||||
|
spacing: 3,
|
||||||
|
crossAxisAlignment: .start,
|
||||||
|
children: [
|
||||||
|
Expanded(child: title),
|
||||||
|
Obx(() {
|
||||||
|
final list = followeeVote.value;
|
||||||
|
if (list != null && list.isNotEmpty) {
|
||||||
|
Widget child;
|
||||||
|
const size = 22.0;
|
||||||
|
const gap = 6.0;
|
||||||
|
const offset = size - gap;
|
||||||
|
if (list.length == 1) {
|
||||||
|
child = NetworkImgLayer(
|
||||||
|
src: list.first.face,
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
final decoration = BoxDecoration(
|
||||||
|
shape: .circle,
|
||||||
|
border: Border.all(color: theme.colorScheme.surface),
|
||||||
|
);
|
||||||
|
child = SizedBox(
|
||||||
|
height: size,
|
||||||
|
width: offset * min(3, list.length) + gap,
|
||||||
|
child: Stack(
|
||||||
|
clipBehavior: .none,
|
||||||
|
children: list
|
||||||
|
.take(3)
|
||||||
|
.indexed
|
||||||
|
.map(
|
||||||
|
(e) => Positioned(
|
||||||
|
top: 0,
|
||||||
|
left: e.$1 * offset,
|
||||||
|
bottom: 0,
|
||||||
|
child: DecoratedBox(
|
||||||
|
decoration: decoration,
|
||||||
|
child: Padding(
|
||||||
|
padding: const .all(.8),
|
||||||
|
child: NetworkImgLayer(
|
||||||
|
src: e.$2.face,
|
||||||
|
width: size - .8,
|
||||||
|
height: size - .8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return GestureDetector(
|
||||||
|
behavior: .opaque,
|
||||||
|
onTap: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
final colorScheme = ColorScheme.of(context);
|
||||||
|
return AlertDialog(
|
||||||
|
clipBehavior: .hardEdge,
|
||||||
|
title: const Text('关注的人的投票'),
|
||||||
|
contentPadding: const .only(top: 10, bottom: 12),
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
minWidth: 280,
|
||||||
|
maxWidth: 420,
|
||||||
|
),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: .min,
|
||||||
|
children: list
|
||||||
|
.map(
|
||||||
|
(e) => ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () =>
|
||||||
|
Get.toNamed('/member?mid=${e.uid}'),
|
||||||
|
leading: NetworkImgLayer(
|
||||||
|
src: e.face,
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
type: .avatar,
|
||||||
|
),
|
||||||
|
title: Text.rich(
|
||||||
|
style: const TextStyle(fontSize: 13),
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(text: e.name),
|
||||||
|
TextSpan(
|
||||||
|
text: ' 投给了',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
style: const TextStyle(fontSize: 13),
|
||||||
|
e.votes
|
||||||
|
.map(
|
||||||
|
(vote) => _voteInfo.options
|
||||||
|
.firstWhereOrNull(
|
||||||
|
(e) => e.optIdx == vote,
|
||||||
|
)
|
||||||
|
?.optDesc,
|
||||||
|
)
|
||||||
|
.join('、'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: .min,
|
||||||
|
children: [
|
||||||
|
child,
|
||||||
|
Icon(
|
||||||
|
size: 18,
|
||||||
|
color: theme.colorScheme.outline.withValues(alpha: .7),
|
||||||
|
Icons.keyboard_arrow_right,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
Widget child = Column(
|
Widget child = Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (_voteInfo.title != null)
|
title,
|
||||||
Text(_voteInfo.title!, style: theme.textTheme.titleMedium),
|
|
||||||
if (_voteInfo.desc != null)
|
if (_voteInfo.desc != null)
|
||||||
Text(
|
Text(
|
||||||
_voteInfo.desc!,
|
_voteInfo.desc!,
|
||||||
@@ -196,8 +349,8 @@ class _VotePanelState extends State<VotePanel> {
|
|||||||
),
|
),
|
||||||
CheckBoxText(
|
CheckBoxText(
|
||||||
text: '匿名',
|
text: '匿名',
|
||||||
selected: anonymity,
|
selected: anonymous,
|
||||||
onChanged: (val) => anonymity = val,
|
onChanged: (val) => anonymous = val,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -444,10 +597,10 @@ Future showVoteDialog(
|
|||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: VotePanel(
|
child: VotePanel(
|
||||||
voteInfo: voteInfo.data,
|
voteInfo: voteInfo.data,
|
||||||
callback: (votes, anonymity) => DynamicsHttp.doVote(
|
callback: (votes, anonymous) => DynamicsHttp.doVote(
|
||||||
voteId: voteId,
|
voteId: voteId,
|
||||||
votes: votes.toList(),
|
votes: votes.toList(),
|
||||||
anonymity: anonymity,
|
anonymous: anonymous,
|
||||||
dynamicId: dynamicId,
|
dynamicId: dynamicId,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user