feat: 番剧播放
This commit is contained in:
@ -157,4 +157,7 @@ class Api {
|
|||||||
|
|
||||||
// 查询视频分P列表 (avid/bvid转cid)
|
// 查询视频分P列表 (avid/bvid转cid)
|
||||||
static const String ab2c = '/x/player/pagelist';
|
static const String ab2c = '/x/player/pagelist';
|
||||||
|
|
||||||
|
// 番剧/剧集明细
|
||||||
|
static const String bangumiInfo = '/pgc/view/web/season';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:pilipala/http/index.dart';
|
import 'package:pilipala/http/index.dart';
|
||||||
|
import 'package:pilipala/models/bangumi/info.dart';
|
||||||
import 'package:pilipala/models/common/search_type.dart';
|
import 'package:pilipala/models/common/search_type.dart';
|
||||||
import 'package:pilipala/models/search/hot.dart';
|
import 'package:pilipala/models/search/hot.dart';
|
||||||
import 'package:pilipala/models/search/result.dart';
|
import 'package:pilipala/models/search/result.dart';
|
||||||
@ -94,4 +95,26 @@ class SearchHttp {
|
|||||||
var res = await Request().get(Api.ab2c, data: {...data});
|
var res = await Request().get(Api.ab2c, data: {...data});
|
||||||
return res.data['data'].first['cid'];
|
return res.data['data'].first['cid'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future bangumiInfo({int? seasonId, int? epId}) async {
|
||||||
|
Map<String, dynamic> data = {};
|
||||||
|
if (seasonId != null) {
|
||||||
|
data['season_id'] = seasonId;
|
||||||
|
} else if (epId != null) {
|
||||||
|
data['ep_id'] = epId;
|
||||||
|
}
|
||||||
|
var res = await Request().get(Api.bangumiInfo, data: {...data});
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': BangumiInfoModel.fromJson(res.data['result']),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': [],
|
||||||
|
'msg': '请求错误 🙅',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
214
lib/models/bangumi/info.dart
Normal file
214
lib/models/bangumi/info.dart
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
class BangumiInfoModel {
|
||||||
|
BangumiInfoModel({
|
||||||
|
this.activity,
|
||||||
|
this.actors,
|
||||||
|
this.alias,
|
||||||
|
this.areas,
|
||||||
|
this.bkgCover,
|
||||||
|
this.cover,
|
||||||
|
this.enableVt,
|
||||||
|
this.episodes,
|
||||||
|
this.evaluate,
|
||||||
|
this.freya,
|
||||||
|
this.jpTitle,
|
||||||
|
this.link,
|
||||||
|
this.mediaId,
|
||||||
|
this.newEp,
|
||||||
|
this.playStrategy,
|
||||||
|
this.positive,
|
||||||
|
this.publish,
|
||||||
|
this.rating,
|
||||||
|
this.record,
|
||||||
|
this.rights,
|
||||||
|
this.seasonId,
|
||||||
|
this.seasonTitle,
|
||||||
|
this.seasons,
|
||||||
|
this.series,
|
||||||
|
this.shareCopy,
|
||||||
|
this.shareSubTitle,
|
||||||
|
this.shareUrl,
|
||||||
|
this.show,
|
||||||
|
this.showSeasonType,
|
||||||
|
this.squareCover,
|
||||||
|
this.stat,
|
||||||
|
this.status,
|
||||||
|
this.styles,
|
||||||
|
this.subTitle,
|
||||||
|
this.title,
|
||||||
|
this.total,
|
||||||
|
this.type,
|
||||||
|
this.userStatus,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map? activity;
|
||||||
|
String? actors;
|
||||||
|
String? alias;
|
||||||
|
List? areas;
|
||||||
|
String? bkgCover;
|
||||||
|
String? cover;
|
||||||
|
String? enableVt;
|
||||||
|
List<EpisodeItem>? episodes;
|
||||||
|
String? evaluate;
|
||||||
|
Map? freya;
|
||||||
|
String? jpTitle;
|
||||||
|
String? link;
|
||||||
|
int? mediaId;
|
||||||
|
Map? newEp;
|
||||||
|
Map? playStrategy;
|
||||||
|
Map? positive;
|
||||||
|
Map? publish;
|
||||||
|
Map? rating;
|
||||||
|
String? record;
|
||||||
|
Map? rights;
|
||||||
|
int? seasonId;
|
||||||
|
String? seasonTitle;
|
||||||
|
List? seasons;
|
||||||
|
Map? series;
|
||||||
|
String? shareCopy;
|
||||||
|
String? shareSubTitle;
|
||||||
|
String? shareUrl;
|
||||||
|
Map? show;
|
||||||
|
int? showSeasonType;
|
||||||
|
String? squareCover;
|
||||||
|
Map? stat;
|
||||||
|
int? status;
|
||||||
|
List? styles;
|
||||||
|
String? subTitle;
|
||||||
|
String? title;
|
||||||
|
int? total;
|
||||||
|
int? type;
|
||||||
|
Map? userStatus;
|
||||||
|
|
||||||
|
BangumiInfoModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
activity = json['activity'];
|
||||||
|
actors = json['actors'];
|
||||||
|
alias = json['alias'];
|
||||||
|
areas = json['areas'];
|
||||||
|
bkgCover = json['bkg_cover'];
|
||||||
|
cover = json['cover'];
|
||||||
|
enableVt = json['enableVt'];
|
||||||
|
episodes = json['episodes']
|
||||||
|
.map<EpisodeItem>((e) => EpisodeItem.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
evaluate = json['evaluate'];
|
||||||
|
freya = json['freya'];
|
||||||
|
jpTitle = json['jp_title'];
|
||||||
|
link = json['link'];
|
||||||
|
mediaId = json['media_id'];
|
||||||
|
newEp = json['newEp'];
|
||||||
|
playStrategy = json['play_strategy'];
|
||||||
|
positive = json['positive'];
|
||||||
|
publish = json['publish'];
|
||||||
|
rating = json['rating'];
|
||||||
|
record = json['record'];
|
||||||
|
rights = json['rights'];
|
||||||
|
seasonId = json['season_id'];
|
||||||
|
seasonTitle = json['season_title'];
|
||||||
|
seasons = json['seasons'];
|
||||||
|
series = json['series'];
|
||||||
|
shareCopy = json['share_copy'];
|
||||||
|
shareSubTitle = json['share_sub_title'];
|
||||||
|
shareUrl = json['share_url'];
|
||||||
|
show = json['show'];
|
||||||
|
showSeasonType = json['show_season_type'];
|
||||||
|
squareCover = json['square_cover'];
|
||||||
|
stat = json['stat'];
|
||||||
|
status = json['status'];
|
||||||
|
styles = json['styles'];
|
||||||
|
subTitle = json['sub_title'];
|
||||||
|
title = json['title'];
|
||||||
|
total = json['total'];
|
||||||
|
type = json['type'];
|
||||||
|
userStatus = json['user_status'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EpisodeItem {
|
||||||
|
EpisodeItem({
|
||||||
|
this.aid,
|
||||||
|
this.badge,
|
||||||
|
this.badgeInfo,
|
||||||
|
this.badgeType,
|
||||||
|
this.bvid,
|
||||||
|
this.cid,
|
||||||
|
this.cover,
|
||||||
|
this.dimension,
|
||||||
|
this.duration,
|
||||||
|
this.enableVt,
|
||||||
|
this.from,
|
||||||
|
this.id,
|
||||||
|
this.isViewHide,
|
||||||
|
this.link,
|
||||||
|
this.longTitle,
|
||||||
|
this.pubTime,
|
||||||
|
this.pv,
|
||||||
|
this.releaseDate,
|
||||||
|
this.rights,
|
||||||
|
this.shareCopy,
|
||||||
|
this.shareUrl,
|
||||||
|
this.shortLink,
|
||||||
|
this.skip,
|
||||||
|
this.status,
|
||||||
|
this.subtitle,
|
||||||
|
this.title,
|
||||||
|
this.vid,
|
||||||
|
});
|
||||||
|
|
||||||
|
int? aid;
|
||||||
|
String? badge;
|
||||||
|
Map? badgeInfo;
|
||||||
|
int? badgeType;
|
||||||
|
String? bvid;
|
||||||
|
int? cid;
|
||||||
|
String? cover;
|
||||||
|
Map? dimension;
|
||||||
|
int? duration;
|
||||||
|
bool? enableVt;
|
||||||
|
String? from;
|
||||||
|
int? id;
|
||||||
|
bool? isViewHide;
|
||||||
|
String? link;
|
||||||
|
String? longTitle;
|
||||||
|
int? pubTime;
|
||||||
|
int? pv;
|
||||||
|
String? releaseDate;
|
||||||
|
Map? rights;
|
||||||
|
String? shareCopy;
|
||||||
|
String? shareUrl;
|
||||||
|
String? shortLink;
|
||||||
|
Map? skip;
|
||||||
|
int? status;
|
||||||
|
String? subtitle;
|
||||||
|
String? title;
|
||||||
|
String? vid;
|
||||||
|
|
||||||
|
EpisodeItem.fromJson(Map<String, dynamic> json) {
|
||||||
|
aid = json['aid'];
|
||||||
|
badge = json['badge'];
|
||||||
|
badgeInfo = json['badge_info'];
|
||||||
|
badgeType = json['badge_type'];
|
||||||
|
bvid = json['bvid'];
|
||||||
|
cid = json['cid'];
|
||||||
|
cover = json['cover'];
|
||||||
|
dimension = json['dimension'];
|
||||||
|
duration = json['duration'];
|
||||||
|
enableVt = json['enable_vt'];
|
||||||
|
from = json['from'];
|
||||||
|
id = json['id'];
|
||||||
|
isViewHide = json['is_view_hide'];
|
||||||
|
link = json['link'];
|
||||||
|
longTitle = json['long_title'];
|
||||||
|
pubTime = json['pub_time'];
|
||||||
|
pv = json['pv'];
|
||||||
|
releaseDate = json['release_date'];
|
||||||
|
rights = json['rights'];
|
||||||
|
shareCopy = json['share_copy'];
|
||||||
|
shareUrl = json['share_url'];
|
||||||
|
shortLink = json['short_link'];
|
||||||
|
skip = json['skip'];
|
||||||
|
status = json['status'];
|
||||||
|
subtitle = json['subtitle'];
|
||||||
|
title = json['title'];
|
||||||
|
vid = json['vid'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/http/search.dart';
|
||||||
|
import 'package:pilipala/models/bangumi/info.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
Widget searchMbangumiPanel(BuildContext context, ctr, list) {
|
Widget searchMbangumiPanel(BuildContext context, ctr, list) {
|
||||||
|
TextStyle style =
|
||||||
|
TextStyle(fontSize: Theme.of(context).textTheme.labelMedium!.fontSize);
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
controller: ctr!.scrollController,
|
controller: ctr!.scrollController,
|
||||||
addAutomaticKeepAlives: false,
|
addAutomaticKeepAlives: false,
|
||||||
@ -21,10 +26,15 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) {
|
|||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
NetworkImgLayer(
|
Stack(
|
||||||
width: 111,
|
children: [
|
||||||
height: 148,
|
NetworkImgLayer(
|
||||||
src: i.cover,
|
width: 111,
|
||||||
|
height: 148,
|
||||||
|
src: i.cover,
|
||||||
|
),
|
||||||
|
Positioned(top: 6, right: 4, child: UpTag(type: i.mediaType))
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -33,11 +43,12 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
RichText(
|
RichText(
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).colorScheme.onSurface),
|
color: Theme.of(context).colorScheme.onSurface),
|
||||||
children: [
|
children: [
|
||||||
WidgetSpan(child: UpTag(type: i.mediaType)),
|
|
||||||
for (var i in i.title) ...[
|
for (var i in i.title) ...[
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: i['text'],
|
text: i['text'],
|
||||||
@ -57,30 +68,54 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text('评分:${i.mediaScore['score'].toString()}'),
|
Text('评分:${i.mediaScore['score'].toString()}',
|
||||||
const SizedBox(height: 2),
|
style: style),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(i.areas),
|
Text(i.areas, style: style),
|
||||||
const SizedBox(width: 3),
|
const SizedBox(width: 3),
|
||||||
const Text('·'),
|
const Text('·'),
|
||||||
const SizedBox(width: 3),
|
const SizedBox(width: 3),
|
||||||
Text(Utils.dateFormat(i.pubtime).toString()),
|
Text(Utils.dateFormat(i.pubtime).toString(),
|
||||||
|
style: style),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(i.styles),
|
Text(i.styles, style: style),
|
||||||
const SizedBox(width: 3),
|
const SizedBox(width: 3),
|
||||||
const Text('·'),
|
const Text('·'),
|
||||||
const SizedBox(width: 3),
|
const SizedBox(width: 3),
|
||||||
Text(i.indexShow),
|
Text(i.indexShow, style: style),
|
||||||
const SizedBox(width: 3),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// Text('声优:${i.cv}'),
|
const SizedBox(height: 18),
|
||||||
const SizedBox(height: 6),
|
SizedBox(
|
||||||
Text(i.desc, overflow: TextOverflow.ellipsis, maxLines: 2),
|
height: 32,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
SmartDialog.showLoading(msg: '获取中...');
|
||||||
|
var res = await SearchHttp.bangumiInfo(
|
||||||
|
seasonId: i.seasonId);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
if (res['status']) {
|
||||||
|
EpisodeItem episode = res['data'].episodes.first;
|
||||||
|
String bvid = episode.bvid!;
|
||||||
|
int cid = episode.cid!;
|
||||||
|
String pic = episode.cover!;
|
||||||
|
String heroTag = Utils.makeHeroTag(cid);
|
||||||
|
Get.toNamed(
|
||||||
|
'/video?bvid=$bvid&cid=$cid',
|
||||||
|
arguments: {
|
||||||
|
'pic': pic,
|
||||||
|
'heroTag': heroTag,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Text('观看'),
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user