From 0312c8d01d6d8623de6f23c3fc9af8b58f2a81e3 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 12:35:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=98=BE=E7=A4=BA=E8=81=94=E5=90=88?= =?UTF-8?q?=E6=8A=95=E7=A8=BFup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/video.dart | 15 +-- lib/models/video_detail_res.dart | 45 +++++++ lib/pages/video/detail/introduction/view.dart | 111 +++++++++++++----- .../introduction/widgets/staff_up_item.dart | 74 ++++++++++++ 4 files changed, 206 insertions(+), 39 deletions(-) create mode 100644 lib/pages/video/detail/introduction/widgets/staff_up_item.dart diff --git a/lib/http/video.dart b/lib/http/video.dart index d43656b2..bdfaedf7 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -192,22 +192,15 @@ class VideoHttp { // 视频信息 标题、简介 static Future videoIntro({required String bvid}) async { var res = await Request().get(Api.videoIntro, data: {'bvid': bvid}); - VideoDetailResponse result = VideoDetailResponse.fromJson(res.data); - if (result.code == 0) { + if (res.data['code'] == 0) { + VideoDetailResponse result = VideoDetailResponse.fromJson(res.data); return {'status': true, 'data': result.data!}; } else { - Map errMap = { - -400: '请求错误', - -403: '权限不足', - -404: '视频资源失效', - 62002: '稿件不可见', - 62004: '稿件审核中', - }; return { 'status': false, 'data': null, - 'code': result.code, - 'msg': errMap[result.code] ?? '请求异常', + 'code': res.data['code'], + 'msg': res.data['message'], }; } } diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index 38e0b877..a82b6fbb 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -67,6 +67,7 @@ class VideoDetailData { String? likeIcon; bool? needJumpBv; String? epId; + List? staff; VideoDetailData({ this.bvid, @@ -103,6 +104,7 @@ class VideoDetailData { this.likeIcon, this.needJumpBv, this.epId, + this.staff, }); VideoDetailData.fromJson(Map json) { @@ -155,6 +157,9 @@ class VideoDetailData { if (json['redirect_url'] != null) { epId = resolveEpId(json['redirect_url']); } + staff = json["staff"] != null + ? List.from(json["staff"]!.map((e) => Staff.fromJson(e))) + : null; } String resolveEpId(url) { @@ -652,3 +657,43 @@ class EpisodeItem { 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 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 json) { + type = json['type']; + status = json['status']; + } +} diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index a7eae6d2..597b6def 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -22,6 +22,7 @@ import 'widgets/fav_panel.dart'; import 'widgets/intro_detail.dart'; import 'widgets/page_panel.dart'; import 'widgets/season_panel.dart'; +import 'widgets/staff_up_item.dart'; class VideoIntroPanel extends StatefulWidget { final String bvid; @@ -409,32 +410,35 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ) ], - GestureDetector( - onTap: onPushMember, - child: Container( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 4), - child: Row( - children: [ - NetworkImgLayer( - type: 'avatar', - src: widget.videoDetail!.owner!.face, - width: 34, - height: 34, - fadeInDuration: Duration.zero, - fadeOutDuration: Duration.zero, - ), - const SizedBox(width: 10), - Text(owner.name, style: const TextStyle(fontSize: 13)), - const SizedBox(width: 6), - Text( - follower, - style: TextStyle( - fontSize: t.textTheme.labelSmall!.fontSize, - color: outline, + if (widget.videoDetail!.staff == null) + GestureDetector( + onTap: onPushMember, + child: Container( + padding: + const EdgeInsets.symmetric(vertical: 12, horizontal: 4), + child: Row( + children: [ + NetworkImgLayer( + type: 'avatar', + src: widget.videoDetail!.owner!.face, + width: 34, + height: 34, + fadeInDuration: Duration.zero, + fadeOutDuration: Duration.zero, ), - ), - const Spacer(), - Obx(() => AnimatedOpacity( + const SizedBox(width: 10), + Text(owner.name, style: const TextStyle(fontSize: 13)), + const SizedBox(width: 6), + Text( + follower, + style: TextStyle( + fontSize: t.textTheme.labelSmall!.fontSize, + color: outline, + ), + ), + const Spacer(), + Obx( + () => AnimatedOpacity( opacity: videoIntroController.followStatus.isEmpty ? 0 : 1, duration: const Duration(milliseconds: 50), @@ -474,11 +478,58 @@ class _VideoInfoState extends State 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 with TickerProviderStateMixin { ); }); } + + // Widget StaffPanel(BuildContext context, videoIntroController) { + // return + // } } diff --git a/lib/pages/video/detail/introduction/widgets/staff_up_item.dart b/lib/pages/video/detail/introduction/widgets/staff_up_item.dart new file mode 100644 index 00000000..7b18d95d --- /dev/null +++ b/lib/pages/video/detail/introduction/widgets/staff_up_item.dart @@ -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, + ), + ), + ), + ), + ], + ); + } +}