feat: app端首页推荐
This commit is contained in:
@ -7,3 +7,10 @@ class StyleString {
|
||||
static const Radius imgRadius = Radius.circular(10);
|
||||
static const double aspectRatio = 16 / 10;
|
||||
}
|
||||
|
||||
class Constants {
|
||||
static const String appKey = '27eb53fc9058f8c3';
|
||||
static const String thirdSign = '04224646d1fea004e79606d3b038c84a';
|
||||
static const String thirdApi =
|
||||
'https://www.mcbbs.net/template/mcbbs/image/special_photo_bg.png';
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ class Request {
|
||||
log("setCookie, ${e.toString()}");
|
||||
}
|
||||
}
|
||||
var cookieString =
|
||||
cookie.map((cookie) => '${cookie.name}=${cookie.value}').join('; ');
|
||||
dio.options.headers['cookie'] = cookieString;
|
||||
}
|
||||
|
||||
// 移除cookie
|
||||
|
@ -1,6 +1,8 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
// import 'package:get/get.dart' hide Response;
|
||||
|
||||
class ApiInterceptor extends Interceptor {
|
||||
@ -13,8 +15,26 @@ class ApiInterceptor extends Interceptor {
|
||||
handler.next(options);
|
||||
}
|
||||
|
||||
Box setting = GStrorage.setting;
|
||||
|
||||
@override
|
||||
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||||
try {
|
||||
if (response.statusCode == 302) {
|
||||
List<String> locations = response.headers['location']!;
|
||||
if (locations.isNotEmpty) {
|
||||
if (locations.first.startsWith('https://www.mcbbs.net')) {
|
||||
final uri = Uri.parse(locations.first);
|
||||
final accessKey = uri.queryParameters['access_key'];
|
||||
final mid = uri.queryParameters['mid'];
|
||||
setting.put(UserBoxKey.accessKey, {'mid': mid, 'value': accessKey});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
print('ApiInterceptor: $err');
|
||||
}
|
||||
|
||||
handler.next(response);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:pilipala/common/constants.dart';
|
||||
import 'package:pilipala/http/api.dart';
|
||||
import 'package:pilipala/http/constants.dart';
|
||||
import 'package:pilipala/http/init.dart';
|
||||
import 'package:pilipala/models/model_hot_video_item.dart';
|
||||
import 'package:pilipala/models/user/fav_detail.dart';
|
||||
@ -179,4 +182,19 @@ class UserHttp {
|
||||
return {'status': false, 'msg': res.data['message']};
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户凭证
|
||||
static Future thirdLogin() async {
|
||||
var res = await Request().get(
|
||||
'https://passport.bilibili.com/login/app/third',
|
||||
data: {
|
||||
'appkey': Constants.appKey,
|
||||
'api': Constants.thirdApi,
|
||||
'sign': Constants.thirdSign,
|
||||
},
|
||||
);
|
||||
if (res.data['code'] == 0 && res.data['data']['has_login'] == 1) {
|
||||
Request().get(res.data['data']['confirm_uri']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/common/constants.dart';
|
||||
import 'package:pilipala/http/api.dart';
|
||||
import 'package:pilipala/http/init.dart';
|
||||
import 'package:pilipala/models/common/reply_type.dart';
|
||||
@ -9,12 +11,15 @@ import 'package:pilipala/models/model_rec_video_item.dart';
|
||||
import 'package:pilipala/models/user/fav_folder.dart';
|
||||
import 'package:pilipala/models/video/play/url.dart';
|
||||
import 'package:pilipala/models/video_detail_res.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
|
||||
/// res.data['code'] == 0 请求正常返回结果
|
||||
/// res.data['data'] 为结果
|
||||
/// 返回{'status': bool, 'data': List}
|
||||
/// view层根据 status 判断渲染逻辑
|
||||
class VideoHttp {
|
||||
static Box setting = GStrorage.setting;
|
||||
|
||||
// 首页推荐视频
|
||||
static Future rcmdVideoList({required int ps, required int freshIdx}) async {
|
||||
try {
|
||||
@ -55,6 +60,9 @@ class VideoHttp {
|
||||
'device_type': 0,
|
||||
'device_name': 'vivo',
|
||||
'pull': freshIdx == 0 ? 'true' : 'false',
|
||||
'appkey': Constants.appKey,
|
||||
'access_key':
|
||||
setting.get(UserBoxKey.accessKey, defaultValue: {})['value'] ?? ''
|
||||
},
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
class RecVideoItemAppModel {
|
||||
RecVideoItemAppModel({
|
||||
this.id,
|
||||
@ -11,30 +13,60 @@ class RecVideoItemAppModel {
|
||||
this.isFollowed,
|
||||
this.owner,
|
||||
this.rcmdReason,
|
||||
this.goto,
|
||||
this.param,
|
||||
this.uri,
|
||||
this.talkBack,
|
||||
this.bangumiView,
|
||||
this.bangumiFollow,
|
||||
this.bangumiBadge,
|
||||
});
|
||||
|
||||
int? id;
|
||||
int? aid;
|
||||
int? bvid;
|
||||
String? bvid;
|
||||
int? cid;
|
||||
String? pic;
|
||||
Stat? stat;
|
||||
int? duration;
|
||||
String? duration;
|
||||
String? title;
|
||||
int? isFollowed;
|
||||
Owner? owner;
|
||||
String? rcmdReason;
|
||||
RcmdReason? rcmdReason;
|
||||
String? goto;
|
||||
String? param;
|
||||
String? uri;
|
||||
String? talkBack;
|
||||
// 番剧
|
||||
String? bangumiView;
|
||||
String? bangumiFollow;
|
||||
String? bangumiBadge;
|
||||
|
||||
RecVideoItemAppModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['player_args']['aid'];
|
||||
aid = json['player_args']['aid'];
|
||||
cid = json['player_args']['cid'];
|
||||
id = json['player_args'] != null
|
||||
? json['player_args']['aid']
|
||||
: int.parse(json['param'] ?? '-1');
|
||||
aid = json['player_args'] != null ? json['player_args']['aid'] : -1;
|
||||
cid = json['player_args'] != null ? json['player_args']['cid'] : -1;
|
||||
pic = json['cover'];
|
||||
stat = Stat.fromJson(json);
|
||||
duration = json['player_args']['duration'];
|
||||
duration = json['cover_right_text'];
|
||||
title = json['title'];
|
||||
isFollowed = 0;
|
||||
owner = Owner.fromJson(json);
|
||||
rcmdReason = json['rcmd_reason_style'] != null
|
||||
? RcmdReason.fromJson(json['rcmd_reason_style'])
|
||||
: null;
|
||||
goto = json['goto'];
|
||||
param = json['param'];
|
||||
uri = json['uri'];
|
||||
talkBack = json['talk_back'];
|
||||
|
||||
if (json['goto'] == 'bangumi') {
|
||||
bangumiView = json['cover_left_text_1'];
|
||||
bangumiFollow = json['cover_left_text_2'];
|
||||
bangumiBadge = json['badge'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,15 +74,15 @@ class Stat {
|
||||
Stat({
|
||||
this.view,
|
||||
this.like,
|
||||
this.danmaku,
|
||||
this.danmu,
|
||||
});
|
||||
String? view;
|
||||
String? like;
|
||||
String? danmaku;
|
||||
String? danmu;
|
||||
|
||||
Stat.fromJson(Map<String, dynamic> json) {
|
||||
view = json["cover_left_text_1"];
|
||||
danmaku = json['cover_left_text_2'];
|
||||
danmu = json['cover_left_text_2'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,8 +90,29 @@ class Owner {
|
||||
Owner({this.name});
|
||||
|
||||
String? name;
|
||||
int? mid;
|
||||
|
||||
Owner.fromJson(Map<String, dynamic> json) {
|
||||
name = json['args']['up_name'];
|
||||
if (json['goto'] == 'bangumi') {
|
||||
log(json.toString());
|
||||
}
|
||||
name = json['goto'] == 'av'
|
||||
? json['args']['up_name']
|
||||
: json['desc_button'] != null
|
||||
? json['desc_button']['text']
|
||||
: '';
|
||||
mid = json['args']['up_id'] ?? -1;
|
||||
}
|
||||
}
|
||||
|
||||
class RcmdReason {
|
||||
RcmdReason({
|
||||
this.content,
|
||||
});
|
||||
|
||||
String? content;
|
||||
|
||||
RcmdReason.fromJson(Map<String, dynamic> json) {
|
||||
content = json["title"] ?? '';
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/http/index.dart';
|
||||
import 'package:pilipala/http/user.dart';
|
||||
import 'package:pilipala/models/common/tab_type.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
|
||||
@ -54,6 +55,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
||||
if (res.data['code'] == 0) {
|
||||
defaultSearch.value = res.data['data']['name'];
|
||||
}
|
||||
UserHttp.thirdLogin();
|
||||
}
|
||||
|
||||
// 更新登录状态
|
||||
|
@ -2,15 +2,16 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:pilipala/http/video.dart';
|
||||
import 'package:pilipala/models/home/rcmd/result.dart';
|
||||
import 'package:pilipala/models/model_rec_video_item.dart';
|
||||
import 'package:pilipala/utils/storage.dart';
|
||||
|
||||
class RcmdController extends GetxController {
|
||||
final ScrollController scrollController = ScrollController();
|
||||
int count = 12;
|
||||
int _currentPage = 1;
|
||||
int _currentPage = 0;
|
||||
int crossAxisCount = 2;
|
||||
RxList<RecVideoItemModel> videoList = [RecVideoItemModel()].obs;
|
||||
RxList<RecVideoItemAppModel> videoList = [RecVideoItemAppModel()].obs;
|
||||
bool isLoadingMore = false;
|
||||
bool flag = false;
|
||||
OverlayEntry? popupDialog;
|
||||
@ -19,19 +20,22 @@ class RcmdController extends GetxController {
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
if (recVideo.get('cacheList') != null &&
|
||||
recVideo.get('cacheList').isNotEmpty) {
|
||||
List<RecVideoItemModel> list = [];
|
||||
for (var i in recVideo.get('cacheList')) {
|
||||
list.add(i);
|
||||
}
|
||||
videoList.value = list;
|
||||
}
|
||||
// if (recVideo.get('cacheList') != null &&
|
||||
// recVideo.get('cacheList').isNotEmpty) {
|
||||
// List<RecVideoItemModel> list = [];
|
||||
// for (var i in recVideo.get('cacheList')) {
|
||||
// list.add(i);
|
||||
// }
|
||||
// videoList.value = list;
|
||||
// }
|
||||
}
|
||||
|
||||
// 获取推荐
|
||||
Future queryRcmdFeed(type) async {
|
||||
var res = await VideoHttp.rcmdVideoList(
|
||||
if (type == 'onRefresh') {
|
||||
_currentPage = 0;
|
||||
}
|
||||
var res = await VideoHttp.rcmdVideoListApp(
|
||||
ps: count,
|
||||
freshIdx: _currentPage,
|
||||
);
|
||||
@ -47,7 +51,7 @@ class RcmdController extends GetxController {
|
||||
} else if (type == 'onLoad') {
|
||||
videoList.addAll(res['data']);
|
||||
}
|
||||
recVideo.put('cacheList', res['data']);
|
||||
// recVideo.put('cacheList', res['data']);
|
||||
_currentPage += 1;
|
||||
}
|
||||
isLoadingMore = false;
|
||||
|
@ -63,6 +63,8 @@ class UserBoxKey {
|
||||
static const String userMid = 'userMid';
|
||||
// 登录状态
|
||||
static const String userLogin = 'userLogin';
|
||||
// 凭证
|
||||
static const String accessKey = 'accessKey';
|
||||
}
|
||||
|
||||
class SettingBoxKey {
|
||||
|
Reference in New Issue
Block a user