feat: 显示联合投稿up

This commit is contained in:
guozhigq
2024-04-27 12:35:43 +08:00
parent 43d70bbf75
commit 1f1d4fe5e9
4 changed files with 206 additions and 39 deletions

View File

@ -192,22 +192,15 @@ class VideoHttp {
// 视频信息 标题、简介 // 视频信息 标题、简介
static Future videoIntro({required String bvid}) async { static Future videoIntro({required String bvid}) async {
var res = await Request().get(Api.videoIntro, data: {'bvid': bvid}); var res = await Request().get(Api.videoIntro, data: {'bvid': bvid});
VideoDetailResponse result = VideoDetailResponse.fromJson(res.data); if (res.data['code'] == 0) {
if (result.code == 0) { VideoDetailResponse result = VideoDetailResponse.fromJson(res.data);
return {'status': true, 'data': result.data!}; return {'status': true, 'data': result.data!};
} else { } else {
Map errMap = {
-400: '请求错误',
-403: '权限不足',
-404: '视频资源失效',
62002: '稿件不可见',
62004: '稿件审核中',
};
return { return {
'status': false, 'status': false,
'data': null, 'data': null,
'code': result.code, 'code': res.data['code'],
'msg': errMap[result.code] ?? '请求异常', 'msg': res.data['message'],
}; };
} }
} }

View File

@ -67,6 +67,7 @@ class VideoDetailData {
String? likeIcon; String? likeIcon;
bool? needJumpBv; bool? needJumpBv;
String? epId; String? epId;
List<Staff>? staff;
VideoDetailData({ VideoDetailData({
this.bvid, this.bvid,
@ -103,6 +104,7 @@ class VideoDetailData {
this.likeIcon, this.likeIcon,
this.needJumpBv, this.needJumpBv,
this.epId, this.epId,
this.staff,
}); });
VideoDetailData.fromJson(Map<String, dynamic> json) { VideoDetailData.fromJson(Map<String, dynamic> json) {
@ -155,6 +157,9 @@ class VideoDetailData {
if (json['redirect_url'] != null) { if (json['redirect_url'] != null) {
epId = resolveEpId(json['redirect_url']); epId = resolveEpId(json['redirect_url']);
} }
staff = json["staff"] != null
? List<Staff>.from(json["staff"]!.map((e) => Staff.fromJson(e)))
: null;
} }
String resolveEpId(url) { String resolveEpId(url) {
@ -652,3 +657,43 @@ class EpisodeItem {
bvid = json['bvid']; bvid = json['bvid'];
} }
} }
class Staff {
Staff({
this.mid,
this.title,
this.name,
this.face,
this.vip,
});
int? mid;
String? title;
String? name;
String? face;
int? status;
Vip? vip;
Staff.fromJson(Map<String, dynamic> json) {
mid = json['mid'];
title = json['title'];
name = json['name'];
face = json['face'];
vip = Vip.fromJson(json['vip']);
}
}
class Vip {
Vip({
this.type,
this.status,
});
int? type;
int? status;
Vip.fromJson(Map<String, dynamic> json) {
type = json['type'];
status = json['status'];
}
}

View File

@ -22,6 +22,7 @@ import 'widgets/fav_panel.dart';
import 'widgets/intro_detail.dart'; import 'widgets/intro_detail.dart';
import 'widgets/page_panel.dart'; import 'widgets/page_panel.dart';
import 'widgets/season_panel.dart'; import 'widgets/season_panel.dart';
import 'widgets/staff_up_item.dart';
class VideoIntroPanel extends StatefulWidget { class VideoIntroPanel extends StatefulWidget {
final String bvid; final String bvid;
@ -409,32 +410,35 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
), ),
) )
], ],
GestureDetector( if (widget.videoDetail!.staff == null)
onTap: onPushMember, GestureDetector(
child: Container( onTap: onPushMember,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 4), child: Container(
child: Row( padding:
children: [ const EdgeInsets.symmetric(vertical: 12, horizontal: 4),
NetworkImgLayer( child: Row(
type: 'avatar', children: [
src: widget.videoDetail!.owner!.face, NetworkImgLayer(
width: 34, type: 'avatar',
height: 34, src: widget.videoDetail!.owner!.face,
fadeInDuration: Duration.zero, width: 34,
fadeOutDuration: Duration.zero, height: 34,
), fadeInDuration: Duration.zero,
const SizedBox(width: 10), fadeOutDuration: Duration.zero,
Text(owner.name, style: const TextStyle(fontSize: 13)),
const SizedBox(width: 6),
Text(
follower,
style: TextStyle(
fontSize: t.textTheme.labelSmall!.fontSize,
color: outline,
), ),
), const SizedBox(width: 10),
const Spacer(), Text(owner.name, style: const TextStyle(fontSize: 13)),
Obx(() => AnimatedOpacity( const SizedBox(width: 6),
Text(
follower,
style: TextStyle(
fontSize: t.textTheme.labelSmall!.fontSize,
color: outline,
),
),
const Spacer(),
Obx(
() => AnimatedOpacity(
opacity: opacity:
videoIntroController.followStatus.isEmpty ? 0 : 1, videoIntroController.followStatus.isEmpty ? 0 : 1,
duration: const Duration(milliseconds: 50), duration: const Duration(milliseconds: 50),
@ -474,11 +478,58 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
), ),
), ),
), ),
)), ),
], ),
],
),
), ),
), ),
), if (widget.videoDetail!.staff != null) ...[
const SizedBox(height: 15),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text.rich(
TextSpan(
style: TextStyle(
fontSize:
Theme.of(context).textTheme.labelMedium!.fontSize,
),
children: [
TextSpan(
text: '创作团队',
style: Theme.of(context)
.textTheme
.titleSmall!
.copyWith(fontWeight: FontWeight.bold),
),
const WidgetSpan(child: SizedBox(width: 6)),
TextSpan(
text: '${widget.videoDetail!.staff!.length}',
style: TextStyle(
color: Theme.of(context).colorScheme.outline,
),
)
],
),
),
SizedBox(
height: 120,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
for (int i = 0;
i < widget.videoDetail!.staff!.length;
i++) ...[
StaffUpItem(item: widget.videoDetail!.staff![i])
],
],
),
),
],
),
]
], ],
)), )),
); );
@ -545,4 +596,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
); );
}); });
} }
// Widget StaffPanel(BuildContext context, videoIntroController) {
// return
// }
} }

View File

@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/models/video_detail_res.dart';
import 'package:pilipala/utils/utils.dart';
class StaffUpItem extends StatelessWidget {
final Staff item;
const StaffUpItem({
super.key,
required this.item,
});
@override
Widget build(BuildContext context) {
final String heroTag = Utils.makeHeroTag(item.mid);
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 15),
GestureDetector(
onTap: () => Get.toNamed(
'/member?mid=${item.mid}',
arguments: {'face': item.face, 'heroTag': heroTag},
),
child: Hero(
tag: heroTag,
child: NetworkImgLayer(
width: 45,
height: 45,
src: item.face,
type: 'avatar',
),
),
),
Padding(
padding: const EdgeInsets.only(top: 4),
child: SizedBox(
width: 85,
child: Text(
item.name!,
overflow: TextOverflow.ellipsis,
softWrap: false,
textAlign: TextAlign.center,
style: TextStyle(
color: item.vip!.status == 1
? const Color.fromARGB(255, 251, 100, 163)
: null,
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 4),
child: SizedBox(
width: 85,
child: Text(
item.title!,
overflow: TextOverflow.ellipsis,
softWrap: false,
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).colorScheme.outline,
fontSize: 12,
),
),
),
),
],
);
}
}