feat: 请求数据和配置

This commit is contained in:
chengsiwen committed 2026-07-06 15:21:29 +08:00
1 parent 557f900187
commit 9b0fe51fa4
21 files changed
+1026 -60

No files matched your search

-12
View File
@@ -39,17 +39,6 @@ class AppService {
// 添加自定义拦截器
_dio.interceptors.add(NyNetworkIntercept());
// 开发环境添加日志
// if (!kReleaseMode) {
// _dio.interceptors.add(TalkerDioLogger(
// settings: TalkerDioLoggerSettings(
// printRequestHeaders: true,
// printRequestData: true,
// printResponseData: true,
// printResponseHeaders: false,
// ),
// ));
// }
}
/// 更新配置
@@ -279,7 +268,6 @@ class ApiRequest {
throw Exception("retry failed (unreachable)");
}
// ============ 错误处理 ============
static HttpResult<T> _handleError<T>(DioException e) {
final Response? resp = e.response;
+1 -1
View File
@@ -2,7 +2,7 @@
// https://api-glimzodf.glimzodf.com/glimzodf/
class ApiString {
static const String baseUrl = "https://api-glimzodf.glimzodf.com/";
static const String baseUrl = "https://api-glimzodf.glimzodf.com/glimzodf";
static const String appName = 'Novyronst';
+11 -29
View File
@@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import 'package:novyronst/common/help/help_log.dart';
import 'package:novyronst/common/help/help_time.dart';
import 'package:novyronst/common/help/help_token.dart';
@@ -11,19 +11,18 @@ import '../help/help_encrypt.dart';
/// 网络请求拦截器
class NyNetworkIntercept extends Interceptor {
final bool enableLog = !kReleaseMode;
final Logger _logger = Logger();
@override
Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
// 添加公共请求头
await _addRequestHeaders(options);
// 打印请求日志
_logInfo("🔶 REQUEST [${options.method.toUpperCase()}] ${options.uri}");
_logDebug("Headers: ${options.headers}");
HelpLog.print("🔶 REQUEST [${options.method.toUpperCase()}] ${options.uri}");
HelpLog.print("Headers: ${options.headers}");
if (options.data != null) {
_logDebug("Payload: ${options.data}");
HelpLog.print("Payload: ${options.data}");
}
handler.next(options);
@@ -31,7 +30,7 @@ class NyNetworkIntercept extends Interceptor {
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
_logInfo("🟢 RESPONSE [${response.statusCode}] ${response.requestOptions.uri}");
HelpLog.print("🟢 RESPONSE [${response.statusCode}] ${response.requestOptions.uri}");
// _logDebug("Body: ${response.data}");
// 处理 401 / 402 Token 过期
@@ -56,7 +55,7 @@ class NyNetworkIntercept extends Interceptor {
final deStr = HelpEncrypt.deStr(response.data);
response.data = jsonDecode(deStr);
} catch (e) {
_logError("解密失败: $e");
HelpLog.print("解密失败: $e");
}
}
@@ -65,14 +64,13 @@ class NyNetworkIntercept extends Interceptor {
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
_logError("🔴 Error: ${err.message}");
HelpLog.print("🔴 Error: ${err.message}", tag: 'in onError');
handler.next(err);
}
// ============ 私有方法 ============
Future<void> _addRequestHeaders(RequestOptions options) async {
// 开发模式添加 security: false
if (!kReleaseMode) {
options.headers['security'] = 'false';
}
@@ -80,7 +78,6 @@ class NyNetworkIntercept extends Interceptor {
// 注入 Token
final tokenManager = HelpToken();
final token = tokenManager.get();
// print('查看token: $token');
if (token.isNotEmpty) {
options.headers['Authorization'] = 'Bearer $token';
}
@@ -104,7 +101,6 @@ class NyNetworkIntercept extends Interceptor {
'device-gaid': '',
});
// 处理 prevToken(从请求体中提取)
await _handleOldToken(options);
}
@@ -117,25 +113,11 @@ class NyNetworkIntercept extends Interceptor {
options.headers['Authorization'] = prevToken.toString();
}
}
} catch (_) {
// 非 JSON 请求跳过
}
} catch (_) {}
}
void _logInfo(String message) {
if (enableLog) _logger.i(message);
}
void _logDebug(String message) {
if (enableLog) _logger.d('💡 $message');
}
void _logError(String message) {
if (enableLog) _logger.e(message);
}
void _handleError(dynamic e, bool error) {
_logError("🔴 Error: $e");
// 这里可以根据需要处理错误提示
HelpLog.print("🔴 Error: $e", tag: 'in ---- _handleError');
}
}
+62
View File
@@ -2,6 +2,7 @@
import 'package:novyronst/common/api/api_request.dart';
import 'package:novyronst/common/api/api_string.dart';
import 'package:novyronst/common/help/help_log.dart';
import 'package:novyronst/common/help/help_token.dart';
import 'package:novyronst/common/model/novyronst_user.dart';
import 'package:novyronst/common/model/register_model.dart';
@@ -38,4 +39,65 @@ class UserRequest {
return null;
});
}
static Future eventCreateHis({
required String shortPlayId,
required String videoId
}) {
// {"short_play_id": shortPlayId, "video_id": videoId}
Map<String, dynamic> params = {"short_play_id": shortPlayId, "video_id": videoId};
return ApiRequest.post(ApiStringUser.eventCreateHistory, data: params).then((value) {
HelpLog.print(value.data, tag: "eventCreateHis");
});
}
static Future eventEnterApp() {
return ApiRequest.post(ApiStringUser.eventUserEnterApp).then((value) {});
}
static Future<bool> eventOnline({String? oldToken}) {
String token = HelpToken().get();
if (token == '') return Future<bool>.value(false);
final body = <String, dynamic>{};
if (oldToken != null) body['token'] = oldToken;
return ApiRequest.post(ApiStringUser.eventUserOnline, data: body).then((value) {
return value.isSuccess;
});
}
static Future<bool> eventOLeaveApp({String? oldToken}) {
String token = HelpToken().get();
if (token == '') return Future<bool>.value(false);
final body = <String, dynamic>{};
if (oldToken != null) body['token'] = oldToken;
return ApiRequest.post(ApiStringUser.eventUserLeaveApp, data: body).then((value) {
return value.isSuccess;
});
}
// 上报播放时长
static Future eventPlaySeconds({
required int shortPlayId,
required int videoId,
required int seconds,
}) {
return ApiRequest.post(ApiStringUser.eventPlaySeconds, data: {
"short_play_id": shortPlayId,
"video_id": videoId,
"play_seconds": seconds,
}).then((value) {});
}
// 上报观看时长
static Future eventWatchTime({
required int shortPlayId,
required int seconds,
}) {
return ApiRequest.post(ApiStringUser.eventWatchTime, data: {
"short_play_id": shortPlayId,
// 时间戳的毫秒数
"request_id": DateTime.now().millisecondsSinceEpoch,
"duration": seconds,
}).then((value) {});
}
}
+181
View File
@@ -0,0 +1,181 @@
import 'package:novyronst/common/api/api_request.dart';
import 'package:novyronst/common/api/api_string.dart';
import 'package:novyronst/common/help/help_log.dart';
import 'package:novyronst/common/model/ny_category_model.dart';
import 'package:novyronst/common/model/ny_drama_model.dart';
import 'package:novyronst/common/model/ny_home_model.dart';
import '../model/ny_detail_model.dart';
class VideoRequest {
static Future<List<NyHomeModel>> getHomeData() {
return ApiRequest.get(ApiStringVideo.getHomeModules).then((value) {
if (value.isSuccess) {
List? list = value.data['data']['list'];
List<NyHomeModel> homeList = [];
if (list != null) {
homeList = list.map((e) => NyHomeModel.fromJson(e)).toList();
}
return homeList;
}
return [];
});
}
static Future<List<NyCategoryModel>> getCategoriesList() {
return ApiRequest.get(ApiStringVideo.getCategoriesList).then((value) {
// SkyLog.print('vvvvv: ${value.data}');
if (!value.isSuccess) return [];
Map<String, dynamic> data = value.data['data'];
List? list = data['list'];
List<NyCategoryModel> categoryList = [];
if (list != null) {
// id 28 不显示,删除
categoryList = list.map((e) => NyCategoryModel.fromJson(e)).toList();
categoryList.removeWhere((element) => element.id == 28);
categoryList.removeWhere((element) => element.name.length >= 10);
}
return categoryList;
});
}
static Future<List<NyDramaModel>> getCategoriesDetail({
required int categoryId,
int page = 1,
int pageSize = 20,
}) {
return ApiRequest.fetchPage<NyDramaModel>(
ApiStringVideo.getCategoriesDetail,
page: page,
pageSize: pageSize,
extraParams: {'category_id': categoryId},
fromJson: (json) => NyDramaModel.fromJson(json),
);
}
// getSearchHots
static Future<List<NyDramaModel>> getSearchHots() {
return ApiRequest.get(ApiStringVideo.getSearchHots).then((value) {
if (value.isSuccess) {
HelpLog.print('getSearchHots: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
// search
static Future<List<NyDramaModel>> search({required String keyword}) {
return ApiRequest.get(ApiStringVideo.getSearch, queryParameters: {
'search': keyword,
}).then((value) {
if (value.isSuccess) {
HelpLog.print('getSearchHots: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
//getCollections
static Future<List<NyDramaModel>> getCollections({
int page = 1,
int pageSize = 10,
}) {
Map<String, dynamic> params = _setPage(page: page, pageSize: pageSize);
return ApiRequest.get(
ApiStringVideo.getCollections,
queryParameters: params,
).then((value) {
if (value.isSuccess) {
HelpLog.print('getCollections: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
// getHistory
static Future<List<NyDramaModel>> getHistory({
int page = 1,
int pageSize = 10,
}) {
Map<String, dynamic> params = _setPage(page: page, pageSize: pageSize);
return ApiRequest.get(
ApiStringVideo.getHistories,
queryParameters: params,
).then((value) {
if (value.isSuccess) {
HelpLog.print('getHistory: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
// getVideoDetail
static Future<NyDetailModel?> getVideoDetail({
required int shortPlayId,
required int shortPlayVideoId,
}) {
Map<String, dynamic> params = {};
params['short_play_id'] = shortPlayId;
params['short_play_video_id'] = shortPlayVideoId;
return ApiRequest.get(
ApiStringVideo.getVideoDetail,
queryParameters: params,
).then((value) {
if (value.isSuccess) {
HelpLog.print('getVideoDetail: ${value.data['data']}');
return NyDetailModel.fromJson(value.data['data']);
}
return null;
});
}
// collect
static Future<bool> collect({
required int shortPlayId,
required int videoId,
}) {
Map<String, dynamic> params = {};
params['short_play_id'] = shortPlayId;
params['video_id'] = videoId;
return ApiRequest.post(ApiStringVideo.collect, data: params).then((value) {
HelpLog.print('collecttttt: ${value.data}');
if (value.isSuccess) {}
return value.isSuccess;
});
}
// cancelCollect
static Future<bool> cancelCollect({required int shortPlayId}) {
Map<String, dynamic> params = {};
params['short_play_id'] = shortPlayId;
return ApiRequest.post(ApiStringVideo.cancelCollect, data: params).then((
value,
) {
HelpLog.print('cancelCollectttt: ${value.data}');
if (value.isSuccess) {}
return value.isSuccess;
});
}
static Map<String, dynamic> _setPage({int page = 1, int pageSize = 10}) {
return {'current_page': page, 'page_size': pageSize};
}
static List parseDataForList(Map<String, dynamic> data) {
Map<String, dynamic> map = data['data'];
List? listData = map['list'];
return listData ?? [];
}
}
+1
View File
@@ -15,6 +15,7 @@ class ConstImage {
static const String btCollectSel = "assets/main/bt_collect_seled.png";
static const String btMineSel = "assets/main/bt_mine_seled.png";
static const String spaceImg = "assets/main/space_img.png";
static const String launcher = "assets/main/launcher.png";
/// imgs
static const String searchBg = "assets/imgs/search_bg.png";
+35
View File
@@ -0,0 +1,35 @@
import 'package:get/get.dart';
import 'package:novyronst/pages/play/pages/laucher_page.dart';
class HelpRouters {
static const String launcher = '/launcher';
}
class HelpPages {
static const initial = HelpRouters.launcher;
static final List<GetPage> routes = [
routePage(name: HelpRouters.launcher, page: ()=> LauncherPage())
];
}
GetPage routePage({
required String name,
required GetPageBuilder page,
Bindings? binding,
Transition transition = Transition.rightToLeft,
Duration transitionDuration = const Duration(milliseconds: 300),
CustomTransition? customTransition,
bool popGesture = true, // Allow iOS swipe-back gesture by default
}) {
return GetPage(
name: name,
page: page,
binding: binding,
transition: transition,
transitionDuration: transitionDuration,
customTransition: customTransition,
popGesture: popGesture, // Pass through to GetPage
);
}
-9
View File
@@ -65,7 +65,6 @@ class HelpToken {
}
}
// ============ 便捷属性 ============
/// 判断 Token 是否为空
bool get isEmpty => get().isEmpty;
@@ -82,7 +81,6 @@ class HelpToken {
return null;
}
// ============ 用户信息扩展(原项目没有,但建议加上) ============
/// 保存用户信息
void saveUserInfo(Map<String, dynamic> userInfo) {
@@ -107,12 +105,9 @@ class HelpToken {
return null;
}
// ============ 私有存储方法 ============
String? _getFromStorage(String key) {
try {
// 使用 SharedPreferences 同步获取(但 SharedPreferences 是异步的)
// 为了保持与原项目一致的同步接口,这里使用异步转同步
// 但更好的方式是在初始化时预加载
return _getFromStorageSync(key);
} catch (e) {
@@ -121,13 +116,9 @@ class HelpToken {
}
}
// 同步读取(注意:SharedPreferences 本身是异步的,这里用同步方式需要谨慎)
String? _getFromStorageSync(String key) {
// 由于 SharedPreferences 是异步的,我们使用一个全局缓存
// 实际项目中建议在 main 中调用 init() 预加载
try {
// 这里为了简化,直接返回 null,实际应该用异步方式
// 建议使用下面的异步版本
return null;
} catch (_) {
return null;
+24
View File
@@ -0,0 +1,24 @@
import 'package:novyronst/common/model/parse_model.dart';
class NyCategoryModel {
final int id;
final String name;
const NyCategoryModel({required this.id, required this.name});
factory NyCategoryModel.fromJson(Map<String, dynamic> json) {
return NyCategoryModel(
id: parseInt(json['id']),
name: parseString(json['name']),
);
}
Map<String, dynamic> toJson() {
return {'id': id, 'name': name};
}
NyCategoryModel copyWith({int? id, String? name}) {
return NyCategoryModel(id: id ?? this.id, name: name ?? this.name);
}
}
+113
View File
@@ -0,0 +1,113 @@
import 'package:novyronst/common/model/ny_drama_model.dart';
import 'package:novyronst/common/model/ny_episode_model.dart';
import 'package:novyronst/common/model/parse_model.dart';
class NyDetailModel {
final NyDramaModel? videoInfo;
final NyDramaModel? shortPlayInfo;
final List<NyEpisodeModel> episodeList;
final String? businessModel;
bool? isCollect;
final bool? showShareCoin;
final int? shareCoin;
final int? revolution;
final String? userLevel;
final int? jumpType;
final int? jumpShortPlayId;
final List<int>? checkPoint;
NyDetailModel({
required this.videoInfo,
this.shortPlayInfo,
required this.episodeList,
this.businessModel,
this.isCollect,
this.showShareCoin,
this.shareCoin,
this.revolution,
this.userLevel,
this.jumpType,
this.jumpShortPlayId,
this.checkPoint,
});
factory NyDetailModel.fromJson(Map<String, dynamic> json) {
return NyDetailModel(
videoInfo: parseMap(json['video_info']) == null
? null
: NyDramaModel.fromJson(parseMap(json['video_info'])!),
shortPlayInfo: parseMap(json['shortPlayInfo']) == null
? null
: NyDramaModel.fromJson(parseMap(json['shortPlayInfo'])!),
episodeList: parseModelList(json['episodeList'], NyEpisodeModel.fromJson),
businessModel: json['business_model'] as String?,
isCollect: json['is_collect'] == null
? null
: parseBool(json['is_collect']),
showShareCoin: json['show_share_coin'] == null
? null
: parseBool(json['show_share_coin']),
shareCoin: json['share_coin'] == null
? null
: parseInt(json['share_coin']),
revolution: json['revolution'] == null
? null
: parseInt(json['revolution']),
userLevel: json['user_level'] as String?,
jumpType: json['jump_type'] == null ? null : parseInt(json['jump_type']),
jumpShortPlayId: json['jump_short_play_id'] == null
? null
: parseInt(json['jump_short_play_id']),
checkPoint: parseIntList(json['check_point']),
);
}
Map<String, dynamic> toJson() {
return {
'video_info': videoInfo?.toJson(),
'shortPlayInfo': shortPlayInfo?.toJson(),
'episodeList': episodeList.map((item) => item.toJson()).toList(),
'business_model': businessModel,
'is_collect': isCollect,
'show_share_coin': showShareCoin,
'share_coin': shareCoin,
'revolution': revolution,
'user_level': userLevel,
'jump_type': jumpType,
'jump_short_play_id': jumpShortPlayId,
'check_point': checkPoint,
};
}
NyDetailModel copyWith({
NyDramaModel? videoInfo,
NyDramaModel? shortPlayInfo,
List<NyEpisodeModel>? episodeList,
String? businessModel,
bool? isCollect,
bool? showShareCoin,
int? shareCoin,
int? revolution,
String? userLevel,
int? jumpType,
int? jumpShortPlayId,
List<int>? checkPoint,
}) {
return NyDetailModel(
videoInfo: videoInfo ?? this.videoInfo,
shortPlayInfo: shortPlayInfo ?? this.shortPlayInfo,
episodeList: episodeList ?? this.episodeList,
businessModel: businessModel ?? this.businessModel,
isCollect: isCollect ?? this.isCollect,
showShareCoin: showShareCoin ?? this.showShareCoin,
shareCoin: shareCoin ?? this.shareCoin,
revolution: revolution ?? this.revolution,
userLevel: userLevel ?? this.userLevel,
jumpType: jumpType ?? this.jumpType,
jumpShortPlayId: jumpShortPlayId ?? this.jumpShortPlayId,
checkPoint: checkPoint ?? this.checkPoint,
);
}
}
+185
View File
@@ -0,0 +1,185 @@
import 'package:novyronst/common/model/parse_model.dart';
import 'ny_category_model.dart';
class NyDramaModel {
final int? id;
final int shortId;
int? shortPlayId;
final String name;
final String description;
final String imageUrl;
final String horizontallyImg;
int collectTotal;
final int watchTotal;
final int episodeTotal;
final String? playSeconds;
bool? isCollect;
final String? videoUrl;
final Map<String, dynamic>? videoInfo;
final List<String>? category;
final List<NyCategoryModel>? categoryList;
final String tagType;
int? episode;
final int? process;
final int? buyType;
final int? searchClickTotal;
final int? shortPlayVideoId;
final int? currentEpisode;
int? historyTime;
NyDramaModel({
this.id,
required this.shortId,
this.shortPlayId,
required this.name,
required this.description,
required this.imageUrl,
required this.horizontallyImg,
required this.collectTotal,
required this.watchTotal,
required this.episodeTotal,
this.playSeconds,
this.isCollect,
this.videoUrl,
this.videoInfo,
this.category,
this.categoryList,
required this.tagType,
this.episode,
this.process,
this.buyType,
this.searchClickTotal,
this.shortPlayVideoId,
this.currentEpisode,
this.historyTime,
});
factory NyDramaModel.fromJson(Map<String, dynamic> json) {
return NyDramaModel(
id: json['id'] == null ? null : parseInt(json['id']),
shortId: parseInt(json['short_id']),
shortPlayId: json['short_play_id'] == null
? null
: parseInt(json['short_play_id']),
name: parseString(json['name']),
description: parseString(json['description']),
imageUrl: parseString(json['image_url']),
horizontallyImg: parseString(json['horizontally_img']),
collectTotal: parseInt(json['collect_total']),
watchTotal: parseInt(json['watch_total']),
episodeTotal: parseInt(json['episode_total']),
playSeconds: json['play_seconds'] as String?,
isCollect: json['is_collect'] == null
? null
: parseBool(json['is_collect']),
videoUrl: json['video_url'] as String?,
videoInfo: parseMap(json['video_info']),
category: parseStringList(json['category']),
categoryList: json['categoryList'] == null
? null
: parseModelList(json['categoryList'], NyCategoryModel.fromJson),
tagType: parseString(json['tag_type']),
episode: json['episode'] == null ? null : parseInt(json['episode']),
process: json['process'] == null ? null : parseInt(json['process']),
buyType: json['buy_type'] == null ? null : parseInt(json['buy_type']),
searchClickTotal: json['search_click_total'] == null
? null
: parseInt(json['search_click_total']),
shortPlayVideoId: json['short_play_video_id'] == null
? null
: parseInt(json['short_play_video_id']),
currentEpisode: json['current_episode'] == null
? null
: parseInt(json['current_episode']),
historyTime: json['history_time'] == null
? null
: parseInt(json['history_time']),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'short_id': shortId,
'short_play_id': shortPlayId,
'name': name,
'description': description,
'image_url': imageUrl,
'horizontally_img': horizontallyImg,
'collect_total': collectTotal,
'watch_total': watchTotal,
'episode_total': episodeTotal,
'play_seconds': playSeconds,
'is_collect': isCollect,
'video_url': videoUrl,
'video_info': videoInfo,
'category': category,
'categoryList': categoryList?.map((item) => item.toJson()).toList(),
'tag_type': tagType,
'episode': episode,
'process': process,
'buy_type': buyType,
'search_click_total': searchClickTotal,
'short_play_video_id': shortPlayVideoId,
'current_episode': currentEpisode,
'history_time': historyTime,
};
}
NyDramaModel copyWith({
int? id,
int? shortId,
int? shortPlayId,
String? name,
String? description,
String? imageUrl,
String? horizontallyImg,
int? collectTotal,
int? watchTotal,
int? episodeTotal,
String? playSeconds,
bool? isCollect,
String? videoUrl,
Map<String, dynamic>? videoInfo,
List<String>? category,
List<NyCategoryModel>? categoryList,
String? tagType,
int? episode,
int? process,
int? buyType,
int? searchClickTotal,
int? shortPlayVideoId,
int? currentEpisode,
int? historyTime,
}) {
return NyDramaModel(
id: id ?? this.id,
shortId: shortId ?? this.shortId,
shortPlayId: shortPlayId ?? this.shortPlayId,
name: name ?? this.name,
description: description ?? this.description,
imageUrl: imageUrl ?? this.imageUrl,
horizontallyImg: horizontallyImg ?? this.horizontallyImg,
collectTotal: collectTotal ?? this.collectTotal,
watchTotal: watchTotal ?? this.watchTotal,
episodeTotal: episodeTotal ?? this.episodeTotal,
playSeconds: playSeconds ?? this.playSeconds,
isCollect: isCollect ?? this.isCollect,
videoUrl: videoUrl ?? this.videoUrl,
videoInfo: videoInfo ?? this.videoInfo,
category: category ?? this.category,
categoryList: categoryList ?? this.categoryList,
tagType: tagType ?? this.tagType,
episode: episode ?? this.episode,
process: process ?? this.process,
buyType: buyType ?? this.buyType,
searchClickTotal: searchClickTotal ?? this.searchClickTotal,
shortPlayVideoId: shortPlayVideoId ?? this.shortPlayVideoId,
currentEpisode: currentEpisode ?? this.currentEpisode,
historyTime: historyTime ?? this.historyTime,
);
}
}
+93
View File
@@ -0,0 +1,93 @@
import 'package:novyronst/common/model/parse_model.dart';
class NyEpisodeModel {
final int id;
final int shortId;
final int shortPlayId;
final int shortPlayVideoId;
final int episode;
final String videoUrl;
final int? promiseViewAd;
final int iaaPopUp;
bool isLock;
String playSeconds;
int? viewAdCount;
NyEpisodeModel({
required this.id,
required this.shortId,
required this.shortPlayId,
required this.shortPlayVideoId,
required this.episode,
required this.videoUrl,
required this.playSeconds,
required this.isLock,
this.promiseViewAd,
required this.iaaPopUp,
required this.viewAdCount,
});
factory NyEpisodeModel.fromJson(Map<String, dynamic> json) {
return NyEpisodeModel(
id: parseInt(json['id']),
shortId: parseInt(json['short_id']),
shortPlayId: parseInt(json['short_play_id']),
shortPlayVideoId: parseInt(json['short_play_video_id']),
episode: parseInt(json['episode']),
videoUrl: parseString(json['video_url']),
playSeconds: parseString(json['play_seconds']),
isLock: parseBool(json['is_lock']),
promiseViewAd: json['promise_view_ad'] == null
? null
: parseInt(json['promise_view_ad']),
iaaPopUp: parseInt(json['iaa_pop_up']),
viewAdCount: parseInt(json['view_ad_count']),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'short_id': shortId,
'short_play_id': shortPlayId,
'short_play_video_id': shortPlayVideoId,
'episode': episode,
'video_url': videoUrl,
'promise_view_ad': promiseViewAd,
'iaa_pop_up': iaaPopUp,
'is_lock': isLock,
'play_seconds': playSeconds,
'view_ad_count': viewAdCount,
};
}
NyEpisodeModel copyWith({
int? id,
int? shortId,
int? shortPlayId,
int? shortPlayVideoId,
int? episode,
String? videoUrl,
bool? isLock,
String? playSeconds,
String? durationSeconds,
int? promiseViewAd,
int? viewAdCount,
int? iaaPopUp,
}) {
return NyEpisodeModel(
id: id ?? this.id,
shortId: shortId ?? this.shortId,
shortPlayId: shortPlayId ?? this.shortPlayId,
shortPlayVideoId: shortPlayVideoId ?? this.shortPlayVideoId,
episode: episode ?? this.episode,
videoUrl: videoUrl ?? this.videoUrl,
isLock: isLock ?? this.isLock,
playSeconds: playSeconds ?? this.playSeconds,
promiseViewAd: promiseViewAd ?? this.promiseViewAd,
viewAdCount: viewAdCount ?? this.viewAdCount,
iaaPopUp: iaaPopUp ?? this.iaaPopUp,
);
}
}
+39
View File
@@ -0,0 +1,39 @@
import 'ny_drama_model.dart';
class NyHomeModel {
final String? moduleKey;
final List<NyDramaModel> dataList;
const NyHomeModel({required this.moduleKey, required this.dataList});
factory NyHomeModel.fromJson(Map<String, dynamic> json) {
final data = json['data'];
List<NyDramaModel> videos = [];
if (data is Map<String, dynamic>) {
final list = data['list'];
if (list is List) {
videos = list.map((e) => NyDramaModel.fromJson(e)).toList();
}
} else if (data is List) {
videos = data.map((e) => NyDramaModel.fromJson(e)).toList();
}
return NyHomeModel(
moduleKey: json['module_key'] as String?,
dataList: videos,
);
}
Map<String, dynamic> toJson() {
return {'module_key': moduleKey, 'dataList': dataList};
}
NyHomeModel copyWith({String? moduleKey, dynamic data}) {
return NyHomeModel(
moduleKey: moduleKey ?? this.moduleKey,
dataList: data ?? dataList,
);
}
}
+13 -7
View File
@@ -3,18 +3,26 @@ import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:novyronst/common/help/help_token.dart';
import 'package:novyronst/root/lib_export.dart';
import 'package:novyronst/root/root_page.dart';
import 'package:novyronst/tools/util/ny_device_info.dart';
void main() {
import 'common/help/help_pages.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initManage();
runApp(const RootApp());
}
Future<void> initManage() async {
await NyDeviceInfo.init();
await HelpToken().init();
}
class RootApp extends StatefulWidget {
@@ -50,12 +58,11 @@ class _RootAppState extends State<RootApp> with WidgetsBindingObserver {
designSize: Size(375, 812),
child: GetMaterialApp(
debugShowCheckedModeBanner: false,
// translations: AppLanguage(),
locale: widget.locale ?? Get.deviceLocale,
fallbackLocale: const Locale('en'),
initialBinding: AppBindings(),
// initialRoute: SkyPages.initial,
// getPages: SkyPages.routes,
initialRoute: HelpRouters.launcher,
getPages: HelpPages.routes,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: ConstColor.themeColor,
@@ -75,7 +82,6 @@ class _RootAppState extends State<RootApp> with WidgetsBindingObserver {
);
},
),
home: widget.home ?? RootPage(),
onInit: () {},
),
)
+48 -1
View File
@@ -1,7 +1,13 @@
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:novyronst/common/api/video_request.dart';
import 'package:novyronst/common/help/app_nav.dart';
import 'package:novyronst/common/model/ny_category_model.dart';
import 'package:novyronst/common/model/ny_drama_model.dart';
import 'package:novyronst/common/model/ny_home_model.dart';
import 'package:novyronst/pages/first/pages/search_page.dart';
import 'package:novyronst/pages/first/widgets/home_first_view.dart';
import 'package:novyronst/pages/first/widgets/home_rank_widget.dart';
import 'package:novyronst/pages/first/widgets/home_remaining_sections.dart';
import 'package:novyronst/pages/first/widgets/search_view.dart';
import 'package:novyronst/root/lib_export.dart';
@@ -18,6 +24,41 @@ class FirstPage extends StatefulWidget {
}
class _RootPageState extends State<FirstPage> {
List<NyCategoryModel> _categories = [];
List<NyHomeModel> _homeDatas = [];
final EasyRefreshController _refreshController = EasyRefreshController(
controlFinishRefresh: true,
);
@override
void initState() {
super.initState();
_getCategoryData();
_getAllData();
}
void _getAllData() {
VideoRequest.getHomeData().then((value) {
setState(() {
_homeDatas = value;
});
for (NyHomeModel element in value) {
print('ele len===: ${element.moduleKey} : ${element.dataList.length}');
}
});
}
void _getCategoryData() {
VideoRequest.getCategoriesList().then((value) {
setState(() {
_categories = value;
});
});
}
@override
Widget build(BuildContext context) {
return AppBgPage(
@@ -34,11 +75,17 @@ class _RootPageState extends State<FirstPage> {
slivers: [
SliverToBoxAdapter(child: HomeFirstView()),
SliverPadding(
padding: const EdgeInsets.only(left: 16, right: 10, top: 16),
padding: const EdgeInsets.only(left: 16, right: 10, top: 16, bottom: 8),
sliver: SliverToBoxAdapter(
child: HelpImage.asset(ConstImage.homeRank),
)
),
SliverPadding(
padding: const EdgeInsetsGeometry.symmetric(horizontal: 16),
sliver: SliverToBoxAdapter(
child: HomeRankWidget(),
),
),
const SliverToBoxAdapter(child: HomeRemainingSections()),
],
),
+1 -1
View File
@@ -84,7 +84,7 @@ class _HomeFirstViewState extends State<HomeFirstView> {
);
}
_buildVideoItem() {
Widget _buildVideoItem() {
return Padding(
padding: const EdgeInsets.all(8),
child: Column(
@@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:novyronst/common/const/const_string.dart';
import 'package:novyronst/tools/widgets/novy_com_widget.dart';
import '../../../tools/util/app_screen.dart';
import '../../../tools/widgets/novy_button_bg.dart';
import '../../widgets/cut_corner_clipper.dart';
import '../../widgets/ny_tag_widget.dart';
class HomeRankWidget extends StatelessWidget {
const HomeRankWidget({super.key});
@override
Widget build(BuildContext context) {
return CutCornerClipper(
width: AppScreen.screenWidth - 32,
cutCorner: CutCorner.bottomLeft,
cutSize: 40,
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
children: [
_buildRankList(),
const SizedBox(height: 5),
Row(
children: [
SizedBox(width: 20.w),
NovyButtonBg(text: 'Keep Watching', width: 308.w,)
],
)
],
),
),
);
}
Row _buildRankList() {
return Row(
children: [
_firstVideoView(),
const SizedBox(width: 8),
_otherVideoView(),
],
);
}
Widget _firstVideoView() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 160.w, height: 240.w,
decoration: BoxDecoration(
color: Colors.red,
)
),
const SizedBox(height: 10),
NovyText('Star of the ocean', fontSize: 15,
color: Colors.black,
fontFamily: ConstFont.montMedium,
),
const SizedBox(height: 5),
NyTagWidget(text: 'Safiray'),
const SizedBox(height: 8),
],
);
}
Widget _otherVideoView() {
return Column(
children: List.generate(3, (index) {
return Container(
margin: const EdgeInsets.only(bottom: 8),
width: 160.w, height: 93.w,
decoration: BoxDecoration(
color: Colors.grey,
)
);
})
);
}
}
+52
View File
@@ -0,0 +1,52 @@
import 'package:flutter/material.dart';
import 'package:novyronst/common/api/user_request.dart';
import 'package:novyronst/common/help/app_nav.dart';
import 'package:novyronst/common/help/help_image.dart';
import 'package:novyronst/common/help/help_token.dart';
import 'package:novyronst/root/root_page.dart';
class LauncherPage extends StatefulWidget {
const LauncherPage({super.key});
@override
State<StatefulWidget> createState() {
return _LauncherPageState();
}
}
class _LauncherPageState extends State<LauncherPage> {
@override
void initState() {
super.initState();
_userRegister();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: HelpImage.asset(ConstImage.launcher, fit: BoxFit.cover),
);
}
void _userRegister() async {
// 先拿token没有的话去注册
final tm = HelpToken();
String token = tm.get();
if (token.isNotEmpty) {
// 成功后去到主页面
Future.delayed(const Duration(seconds: 1), () {
AppNav.off(RootPage());
});
return;
}
final res = await UserRequest.register();
if (res != null) {
tm.save(res.token);
AppNav.off(RootPage());
}
}
}