mod: 接口整理、增加up粉丝请求
This commit is contained in:
33
lib/common/widgets/http_error.dart
Normal file
33
lib/common/widgets/http_error.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class HttpError extends StatelessWidget {
|
||||||
|
HttpError({required this.errMsg, required this.fn, super.key});
|
||||||
|
|
||||||
|
String errMsg = '';
|
||||||
|
final Function()? fn;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SliverToBoxAdapter(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 150,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
errMsg,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
fn!();
|
||||||
|
},
|
||||||
|
child: const Text('点击重试'))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,12 @@ class Api {
|
|||||||
static const String hotList = '/x/web-interface/popular';
|
static const String hotList = '/x/web-interface/popular';
|
||||||
// 视频详情
|
// 视频详情
|
||||||
// 竖屏 https://api.bilibili.com/x/web-interface/view?aid=527403921
|
// 竖屏 https://api.bilibili.com/x/web-interface/view?aid=527403921
|
||||||
static const String videoDetail = '/x/web-interface/view';
|
static const String videoIntro = '/x/web-interface/view';
|
||||||
|
|
||||||
// 视频详情页 相关视频
|
// 视频详情页 相关视频
|
||||||
static const String relatedList = '/x/web-interface/archive/related';
|
static const String relatedList = '/x/web-interface/archive/related';
|
||||||
|
|
||||||
|
// 用户(被)关注数、投稿数
|
||||||
|
// https://api.bilibili.com/x/relation/stat?vmid=697166795
|
||||||
|
static const String userStat = '/x/relation/stat';
|
||||||
}
|
}
|
||||||
|
13
lib/http/user.dart
Normal file
13
lib/http/user.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:pilipala/http/api.dart';
|
||||||
|
import 'package:pilipala/http/init.dart';
|
||||||
|
|
||||||
|
class UserHttp {
|
||||||
|
static Future<dynamic> userStat(mid) async {
|
||||||
|
var res = await Request().get(Api.userStat, data: {'vmid': mid});
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {'status': true, 'data': res.data['data']};
|
||||||
|
} else {
|
||||||
|
return {'status': false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,58 @@
|
|||||||
import 'package:pilipala/http/api.dart';
|
import 'package:pilipala/http/api.dart';
|
||||||
import 'package:pilipala/http/init.dart';
|
import 'package:pilipala/http/init.dart';
|
||||||
|
import 'package:pilipala/models/model_hot_video_item.dart';
|
||||||
|
import 'package:pilipala/models/model_rec_video_item.dart';
|
||||||
import 'package:pilipala/models/video_detail_res.dart';
|
import 'package:pilipala/models/video_detail_res.dart';
|
||||||
|
|
||||||
|
/// res.data['code'] == 0 请求正常返回结果
|
||||||
|
/// res.data['data'] 为结果
|
||||||
|
/// 返回{'status': bool, 'data': List}
|
||||||
|
/// view层根据 status 判断渲染逻辑
|
||||||
class VideoHttp {
|
class VideoHttp {
|
||||||
|
// 首页推荐视频
|
||||||
|
static Future rcmdVideoList(data) async {
|
||||||
|
var res = await Request().get(
|
||||||
|
Api.recommendList,
|
||||||
|
data: {
|
||||||
|
'feed_version': 'V3',
|
||||||
|
'ps': data['ps'],
|
||||||
|
'fresh_idx': data['fresh_idx']
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
List<RecVideoItemModel> list = [];
|
||||||
|
for (var i in res.data['data']['item']) {
|
||||||
|
list.add(RecVideoItemModel.fromJson(i));
|
||||||
|
}
|
||||||
|
return {'status': true, 'data': list};
|
||||||
|
} else {
|
||||||
|
return {'status': false, 'data': []};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最热视频
|
||||||
|
static Future hotVideoList(data) async {
|
||||||
|
var res = await Request().get(
|
||||||
|
Api.hotList,
|
||||||
|
data: {
|
||||||
|
'pn': data['pn'],
|
||||||
|
'ps': data['ps'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
List<HotVideoItemModel> list = [];
|
||||||
|
for (var i in res.data['data']['list']) {
|
||||||
|
list.add(HotVideoItemModel.fromJson(i));
|
||||||
|
}
|
||||||
|
return {'status': true, 'data': list};
|
||||||
|
} else {
|
||||||
|
return {'status': false, 'data': []};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 视频信息 标题、简介
|
// 视频信息 标题、简介
|
||||||
static Future videoDetail(data) async {
|
static Future videoIntro(aid) async {
|
||||||
var res = await Request().get(Api.videoDetail, data: data);
|
var res = await Request().get(Api.videoIntro, data: {'aid': aid});
|
||||||
VideoDetailResponse result = VideoDetailResponse.fromJson(res.data);
|
VideoDetailResponse result = VideoDetailResponse.fromJson(res.data);
|
||||||
if (result.code == 0) {
|
if (result.code == 0) {
|
||||||
return {'status': true, 'data': result.data!};
|
return {'status': true, 'data': result.data!};
|
||||||
@ -25,8 +72,17 @@ class VideoHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future videoRecommend(data) async {
|
// 相关视频
|
||||||
var res = await Request().get(Api.relatedList, data: data);
|
static Future relatedVideoList(aid) async {
|
||||||
return res;
|
var res = await Request().get(Api.relatedList, data: {'aid': aid});
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
List<HotVideoItemModel> list = [];
|
||||||
|
for (var i in res.data['data']) {
|
||||||
|
list.add(HotVideoItemModel.fromJson(i));
|
||||||
|
}
|
||||||
|
return {'status': true, 'data': list};
|
||||||
|
} else {
|
||||||
|
return {'status': true, 'data': []};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/api.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/http/init.dart';
|
|
||||||
import 'package:pilipala/models/model_rec_video_item.dart';
|
import 'package:pilipala/models/model_rec_video_item.dart';
|
||||||
|
|
||||||
class HomeController extends GetxController {
|
class HomeController extends GetxController {
|
||||||
@ -21,22 +20,20 @@ class HomeController extends GetxController {
|
|||||||
|
|
||||||
// 获取推荐
|
// 获取推荐
|
||||||
Future queryRcmdFeed(type) async {
|
Future queryRcmdFeed(type) async {
|
||||||
var res = await Request().get(
|
var res = await VideoHttp.rcmdVideoList({
|
||||||
Api.recommendList,
|
'ps': count,
|
||||||
data: {'feed_version': "V3", 'ps': count, 'fresh_idx': _currentPage},
|
'fresh_idx': _currentPage,
|
||||||
);
|
});
|
||||||
List<RecVideoItemModel> list = [];
|
if (res['status']) {
|
||||||
for (var i in res.data['data']['item']) {
|
if (type == 'init') {
|
||||||
list.add(RecVideoItemModel.fromJson(i));
|
videoList.value = res['data'];
|
||||||
|
} else if (type == 'onRefresh') {
|
||||||
|
videoList.insertAll(0, res['data']);
|
||||||
|
} else if (type == 'onLoad') {
|
||||||
|
videoList.addAll(res['data']);
|
||||||
|
}
|
||||||
|
_currentPage += 1;
|
||||||
}
|
}
|
||||||
if (type == 'init') {
|
|
||||||
videoList.value = list;
|
|
||||||
} else if (type == 'onRefresh') {
|
|
||||||
videoList.insertAll(0, list);
|
|
||||||
} else if (type == 'onLoad') {
|
|
||||||
videoList.addAll(list);
|
|
||||||
}
|
|
||||||
_currentPage += 1;
|
|
||||||
isLoadingMore = false;
|
isLoadingMore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import 'package:flutter/animation.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/api.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pilipala/http/init.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/model_hot_video_item.dart';
|
import 'package:pilipala/models/model_hot_video_item.dart';
|
||||||
|
|
||||||
class HotController extends GetxController {
|
class HotController extends GetxController {
|
||||||
@ -21,22 +19,20 @@ class HotController extends GetxController {
|
|||||||
|
|
||||||
// 获取推荐
|
// 获取推荐
|
||||||
Future queryHotFeed(type) async {
|
Future queryHotFeed(type) async {
|
||||||
var res = await Request().get(
|
var res = await VideoHttp.hotVideoList({
|
||||||
Api.hotList,
|
'pn': _currentPage,
|
||||||
data: {'pn': _currentPage, 'ps': _count},
|
'ps': _count,
|
||||||
);
|
});
|
||||||
List<HotVideoItemModel> list = [];
|
if (res['status']) {
|
||||||
for (var i in res.data['data']['list']) {
|
if (type == 'init') {
|
||||||
list.add(HotVideoItemModel.fromJson(i));
|
videoList.value = res['data'];
|
||||||
|
} else if (type == 'onRefresh') {
|
||||||
|
videoList.insertAll(0, res['data']);
|
||||||
|
} else if (type == 'onLoad') {
|
||||||
|
videoList.addAll(res['data']);
|
||||||
|
}
|
||||||
|
_currentPage += 1;
|
||||||
}
|
}
|
||||||
if (type == 'init') {
|
|
||||||
videoList.value = list;
|
|
||||||
} else if (type == 'onRefresh') {
|
|
||||||
videoList.insertAll(0, list);
|
|
||||||
} else if (type == 'onLoad') {
|
|
||||||
videoList.addAll(list);
|
|
||||||
}
|
|
||||||
_currentPage += 1;
|
|
||||||
isLoadingMore = false;
|
isLoadingMore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/api.dart';
|
import 'package:pilipala/http/user.dart';
|
||||||
import 'package:pilipala/http/init.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/video_detail_res.dart';
|
import 'package:pilipala/models/video_detail_res.dart';
|
||||||
import 'package:pilipala/pages/video/detail/controller.dart';
|
import 'package:pilipala/pages/video/detail/controller.dart';
|
||||||
|
|
||||||
@ -20,6 +20,12 @@ class VideoIntroController extends GetxController {
|
|||||||
// 视频详情 请求返回
|
// 视频详情 请求返回
|
||||||
Rx<VideoDetailData> videoDetail = VideoDetailData().obs;
|
Rx<VideoDetailData> videoDetail = VideoDetailData().obs;
|
||||||
|
|
||||||
|
// 请求返回的信息
|
||||||
|
String responseMsg = '请求异常';
|
||||||
|
|
||||||
|
// up主粉丝数
|
||||||
|
Map userStat = {'follower': '-'};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
@ -36,17 +42,28 @@ class VideoIntroController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future queryVideoDetail() async {
|
// 获取视频简介
|
||||||
var res = await Request().get(Api.videoDetail, data: {
|
Future queryVideoIntro() async {
|
||||||
'aid': aid,
|
var result = await VideoHttp.videoIntro(aid);
|
||||||
});
|
if (result['status']) {
|
||||||
VideoDetailResponse result = VideoDetailResponse.fromJson(res.data);
|
videoDetail.value = result['data']!;
|
||||||
videoDetail.value = result.data!;
|
Get.find<VideoDetailController>().tabs.value = [
|
||||||
Get.find<VideoDetailController>().tabs.value = [
|
'简介',
|
||||||
'简介',
|
'评论 ${result['data']!.stat!.reply}'
|
||||||
'评论 ${result.data!.stat!.reply}'
|
];
|
||||||
];
|
} else {
|
||||||
// await Future.delayed(const Duration(seconds: 3));
|
responseMsg = result['msg'];
|
||||||
return true;
|
}
|
||||||
|
// 获取到粉丝数再返回
|
||||||
|
await queryUserStat();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取up主粉丝数
|
||||||
|
Future queryUserStat() async {
|
||||||
|
var result = await UserHttp.userStat(videoDetail.value.owner!.mid);
|
||||||
|
if (result['status']) {
|
||||||
|
userStat = result['data'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pilipala/common/constants.dart';
|
import 'package:pilipala/common/constants.dart';
|
||||||
|
import 'package:pilipala/common/widgets/http_error.dart';
|
||||||
import 'package:pilipala/pages/video/detail/widgets/expandable_section.dart';
|
import 'package:pilipala/pages/video/detail/widgets/expandable_section.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
||||||
@ -43,27 +44,29 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder(
|
return FutureBuilder(
|
||||||
future: videoIntroController.queryVideoDetail(),
|
future: videoIntroController.queryVideoIntro(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
if (snapshot.data) {
|
if (snapshot.data['status']) {
|
||||||
// 请求成功
|
// 请求成功
|
||||||
// return _buildView(context, false, videoDetail);
|
// return _buildView(context, false, videoDetail);
|
||||||
return VideoInfo(loadingStatus: false, videoDetail: videoDetail);
|
return VideoInfo(
|
||||||
|
loadingStatus: false,
|
||||||
|
videoDetail: videoDetail,
|
||||||
|
videoIntroController: videoIntroController);
|
||||||
} else {
|
} else {
|
||||||
// 请求错误
|
// 请求错误
|
||||||
return Center(
|
return HttpError(
|
||||||
child: IconButton(
|
errMsg: snapshot.data['msg'],
|
||||||
icon: const Icon(Icons.refresh),
|
fn: () => setState(() {}),
|
||||||
onPressed: () {
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// return _buildView(context, true, videoDetail);
|
// return _buildView(context, true, videoDetail);
|
||||||
return VideoInfo(loadingStatus: true, videoDetail: videoDetail);
|
return VideoInfo(
|
||||||
|
loadingStatus: true,
|
||||||
|
videoDetail: videoDetail,
|
||||||
|
videoIntroController: videoIntroController);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -90,8 +93,13 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
|||||||
class VideoInfo extends StatefulWidget {
|
class VideoInfo extends StatefulWidget {
|
||||||
bool loadingStatus = false;
|
bool loadingStatus = false;
|
||||||
VideoDetailData? videoDetail;
|
VideoDetailData? videoDetail;
|
||||||
|
VideoIntroController? videoIntroController;
|
||||||
|
|
||||||
VideoInfo({Key? key, required this.loadingStatus, this.videoDetail})
|
VideoInfo(
|
||||||
|
{Key? key,
|
||||||
|
required this.loadingStatus,
|
||||||
|
this.videoDetail,
|
||||||
|
this.videoIntroController})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -150,19 +158,17 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
? widget.videoDetail!.owner!.name
|
? widget.videoDetail!.owner!.name
|
||||||
: videoItem['owner'].name),
|
: videoItem['owner'].name),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
// Text.rich(
|
Text(
|
||||||
// TextSpan(
|
widget.loadingStatus
|
||||||
// style: TextStyle(
|
? '- 粉丝'
|
||||||
// color: Theme.of(context)
|
: '${Utils.numFormat(widget.videoIntroController!.userStat['follower'])}粉丝',
|
||||||
// .colorScheme
|
style: TextStyle(
|
||||||
// .outline,
|
fontSize: Theme.of(context)
|
||||||
// fontSize: 11),
|
.textTheme
|
||||||
// children: const [
|
.labelSmall!
|
||||||
// TextSpan(text: '2.6万粉丝'),
|
.fontSize,
|
||||||
// TextSpan(text: ' '),
|
color: Theme.of(context).colorScheme.outline),
|
||||||
// TextSpan(text: '2.6万粉丝'),
|
)
|
||||||
// ]),
|
|
||||||
// ),
|
|
||||||
]),
|
]),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
AnimatedOpacity(
|
AnimatedOpacity(
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/video.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/model_hot_video_item.dart';
|
|
||||||
|
|
||||||
class ReleatedController extends GetxController {
|
class ReleatedController extends GetxController {
|
||||||
// 视频aid
|
// 视频aid
|
||||||
@ -10,22 +7,5 @@ class ReleatedController extends GetxController {
|
|||||||
// 推荐视频列表
|
// 推荐视频列表
|
||||||
List relatedVideoList = [];
|
List relatedVideoList = [];
|
||||||
|
|
||||||
Future<dynamic> queryVideoRecommend() async {
|
Future<dynamic> queryRelatedVideo() => VideoHttp.relatedVideoList(aid);
|
||||||
try {
|
|
||||||
var res = await VideoHttp.videoRecommend({'aid': aid});
|
|
||||||
List<HotVideoItemModel> list = [];
|
|
||||||
try {
|
|
||||||
for (var i in res.data['data']) {
|
|
||||||
list.add(HotVideoItemModel.fromJson(i));
|
|
||||||
}
|
|
||||||
relatedVideoList = list;
|
|
||||||
} catch (err) {
|
|
||||||
return err.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.data['data'];
|
|
||||||
} catch (err) {
|
|
||||||
return err.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,22 +16,22 @@ class _RelatedVideoPanelState extends State<RelatedVideoPanel> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder(
|
return FutureBuilder(
|
||||||
future: _releatedController.queryVideoRecommend(),
|
future: _releatedController.queryRelatedVideo(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
if (snapshot.data!.isNotEmpty) {
|
if (snapshot.data!['status']) {
|
||||||
// 请求成功
|
// 请求成功
|
||||||
List videoList = _releatedController.relatedVideoList;
|
// List videoList = _releatedController.relatedVideoList;
|
||||||
return SliverList(
|
return SliverList(
|
||||||
delegate: SliverChildBuilderDelegate((context, index) {
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
if (index == videoList.length) {
|
if (index == snapshot.data['data'].length) {
|
||||||
return SizedBox(height: MediaQuery.of(context).padding.bottom);
|
return SizedBox(height: MediaQuery.of(context).padding.bottom);
|
||||||
} else {
|
} else {
|
||||||
return VideoCardH(
|
return VideoCardH(
|
||||||
videoItem: videoList[index],
|
videoItem: snapshot.data['data'][index],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, childCount: videoList.length + 1));
|
}, childCount: snapshot.data['data'].length + 1));
|
||||||
} else {
|
} else {
|
||||||
// 请求错误
|
// 请求错误
|
||||||
return const Center(
|
return const Center(
|
||||||
|
Reference in New Issue
Block a user