初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
+286
View File
@@ -0,0 +1,286 @@
import 'package:get/get.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/hj_page/pre_sale/pre_sale_page.dart';
import 'package:hgdj/hj_page/pre_sale/pre_sale_provider.dart';
import 'package:hgdj/hj_page/user_center_page/user_center_page.dart';
import 'package:hgdj/hj_page/video/video_page.dart';
import 'package:hgdj/tools_base/debug_log.dart';
import 'package:hgdj/tools_base/event_bus/events.dart';
import 'package:hgdj/tools_base/headphone_monitor.dart';
import 'package:hgdj/tools_base/loading/loading_helper.dart';
import 'package:hgdj/tools_base/toast.dart';
import 'package:url_launcher/url_launcher.dart';
import '../config/address.dart';
import '../config/config.dart';
import '../hj_model/cartoon_media_info.dart';
import '../hj_page/cartoon/cartoon_detail_page.dart';
import '../hj_page/cartoon/novel_detail_page.dart';
import '../hj_page/community/post_detail_page/post_detail_page.dart';
import '../hj_page/community/publish_page/publish_page.dart';
import '../hj_page/find/acg_game_detail_page.dart';
import '../hj_page/find/rank_module/rank_main_page.dart';
import '../hj_page/mine/mine_setting/bing_phone_page.dart';
import '../hj_page/mine/mine_share/mine_share_page.dart';
import '../hj_page/mine/mine_vip/mine_charge_coin_page.dart';
import '../hj_page/mine/mine_vip/mine_charge_vip_page.dart';
import '../hj_page/mine/mine_vip/pay_order_source.dart';
import '../hj_page/mine/welfare/welfare_home_page.dart';
import '../hj_page/short_video/short_video_page.dart';
import '../hj_page/web_page/h5_page.dart';
import '../hj_utils/api_service/mine_service.dart';
import '../hj_utils/api_service/vid_service.dart';
import '../tools_base/event_bus/event_bus_util.dart';
import '../tools_base/loading/loading_alert_widget.dart';
/// 跳转视频/动漫/短视频详情页
/// - [isCartoon] 优先级最高 → 长视频页(标记动漫)
/// - newsType == SEED_LINK → ACG 游戏详情页
/// - playTime < 300 且非 0 → 短视频
/// - 其余 → 长视频
/// - [videoModel] / [videoId] 必传其一
Future? pushToVideoPage({
String? videoId,
VideoModel? videoModel,
bool isCartoon = false,
String? videoCover,
List<VideoModel>? videoArr,
}) {
// 1. 动漫优先:跳长视频
if (isCartoon) {
return Get.to(
() => VideoPage(
id: videoModel?.id ?? videoId,
isCartoon: true,
videoCover: videoCover ?? videoModel?.cover,
),
preventDuplicates: false,
);
}
// 2. SEED_LINK:跳 ACG 游戏详情
if (videoModel?.newsType == 'SEED_LINK') {
return Get.to(() => AcgGameDetailPage(id: videoModel?.id ?? ''),
preventDuplicates: false);
}
// 3. 短视频:playTime < 300 且非 0(此分支 videoModel 必非 nullplayTime 取自它)
final playTime = videoModel?.playTime ?? 1000;
if (playTime < 300 && playTime != 0) {
final list = videoArr?.isNotEmpty == true ? videoArr! : [videoModel!];
final idx = list.indexWhere((e) => e.id == videoModel?.id);
return Get.to(
() => ShortVideoPage(
type: VideoListType.SECOND,
videoList: list,
pageIndex: idx < 0 ? 0 : idx,
),
preventDuplicates: false,
);
}
// 4. 默认:长视频
return Get.to(() => VideoPage(
id: videoId ?? videoModel?.id,
videoCover: videoCover ?? videoModel?.cover,
model: videoModel,
));
}
/// 跳转卡通详情:按 mediaType 分发
void pushToCartoonPage(CartoonMediaInfo? info) {
switch (info?.mediaType) {
case 'image':
Get.to(
CartoonDetailPage(id: info?.id ?? '', heroTag: info?.heroTag),
preventDuplicates: false,
);
return;
case 'text':
Get.to(NovelDetailPage(info?.id), preventDuplicates: false);
return;
case 'video':
pushToVideoPage(
videoId: info?.id ?? '', isCartoon: true, videoCover: info?.coverV);
return;
}
}
/// 解析 deeplink/h5 链接并执行跳转
/// [sourcePage] 链接落到会员/金币页时的下单来源(如首页浮窗),不传走 pushToWalletPage 的默认
Future? pushToPageByLink(String? url,
{Map<String, dynamic>? arguments, PaySourcePage? sourcePage}) async {
if (url?.isNotEmpty != true) return null;
Uri? uri;
try {
uri = Uri.parse(url!);
} catch (e) {
debugLog("go func", e.toString());
}
if (uri == null) return null;
arguments ??= {};
arguments.addAll(uri.queryParameters);
final host = uri.host.toLowerCase().removeAllWhitespace;
if (uri.scheme == "yinseinner") {
return _handleYinseInnerLink(host, arguments, sourcePage);
}
// http(s):默认走外部浏览器;带 inner=1 走内部 H5
if (uri.scheme.startsWith("http")) {
if (uri.queryParameters["inner"] == "1") {
// InAppWebView 是 PlatformView,创建时会重建渲染 Surface;视频在播放(Texture持续产帧)会导致部分机型画面放大/闪烁,先暂停所有播放
HeadphoneMonitor.instance.pauseAll();
return Get.to(H5Page(url: url!, showTitle: false, showClose: true),
popGesture: true);
}
return launchUrlToWeb(url!);
}
showToast("未知链接");
return null;
}
/// 处理 yinseinner:// 内部 scheme 跳转
Future? _handleYinseInnerLink(String host, Map<String, dynamic> arguments,
[PaySourcePage? sourcePage]) async {
switch (host) {
case "submodule": // 亚模块分类
eventBus.emit(YinseinnerModel(routeName: "module", id: arguments["id"]));
return null;
case "navigation_bar": // 导航栏 亚模块菜单弹出
eventBus.emit(YinseinnerModel(routeName: "navigation_bar"));
return null;
case "community_module": // 社区
eventBus.emit(
YinseinnerModel(routeName: "community_module", id: arguments["id"]));
return null;
case "vip_page": // 会员中心
return pushToWalletPage(vipId: arguments['id'], sourcePage: sourcePage);
case "wallet_page": // 金币购买
return pushToWalletPage(tabPosition: 1, sourcePage: sourcePage);
case "universal_agent": // 分享推广
return Get.to(() => MineSharePage(), preventDuplicates: false);
case "lottery": // 抽奖
presaleProvider.openLuckyDraw();
return null;
case "rankinglist": // 排行榜
return Get.to(RankMainPage(), preventDuplicates: false);
case "postdetail": // 帖子详情
return Get.to(() => PostDetailPage(
argument: PostDetailPageArgument(id: arguments["id"])));
case "video_page": // 长视频播放页
return Get.to(() => VideoPage(id: arguments["id"]),
preventDuplicates: false);
case "taskhall": // 福利任务
return Get.to(() => const WelfareHomePage(index: 1),
preventDuplicates: false);
case "advancepage": // 预售
return Get.to(() => const PreSalePage());
case "live_streaming": // 直播
eventBus.emit(YinseinnerModel(routeName: "live_streaming"));
return null;
case "shop_page": // 原味商店
if (!Config.isStoreOpen) return null;
try {
LoadingHelper.showLoading();
final result = await VidService.getShopAddress();
LoadingHelper.dismissLoading();
if (result is String && result.isEmpty) {
showToast("获取商店地址失败~");
return null;
}
HeadphoneMonitor.instance.pauseAll();
return Get.to(H5Page(url: result), popGesture: true);
} catch (e) {
LoadingHelper.dismissLoading();
debugLog(e);
return null;
}
case "kefu": // 在线客服
pushToCustomService();
return null;
case "userhomepage": // 跳转博主
final uid = arguments["uid"] ?? 0;
if (uid == 0) return null;
return pushToPersonCenter(uid);
case "publish_page": // 发布
return Get.to(() => const PublishPage(type: PublishType.homeImgText));
case "binding_page": // 绑定手机
return Get.to(() => const BindPhonePage(pageType: PhonePageType.bind));
case "science": // AI
eventBus.emit(YinseinnerModel(routeName: "ai"));
return null;
default:
showToast("未处理链接");
return null;
}
}
/// 浏览器跳转(先 externalApplication,再 platformDefault 兜底)
Future launchUrlToWeb(String url, {String? tip}) async {
final uri = Uri.tryParse(url);
if (uri == null) {
debugLog('launchUrlToWeb invalid url: $url');
return;
}
const launchModes = <LaunchMode>[
LaunchMode.externalApplication,
LaunchMode.platformDefault,
];
try {
for (final mode in launchModes) {
final launched = await launchUrl(uri, mode: mode);
if (launched) {
if (tip?.isNotEmpty == true) showToast(tip!);
return;
}
}
debugLog('launchUrlToWeb failed: $url');
} catch (e) {
debugLog(e);
}
}
/// 跳转个人中心
/// [type]==1 历史业务(ActressMainPage)已下线
/// [id] 深链传进来可能是字符串,统一收敛成 int
Future? pushToPersonCenter(dynamic id, {int? type}) {
if (type == 1) return null;
final uid = id is int ? id : int.tryParse('$id') ?? 0;
return Get.to(() => UserCenterPage(uid: uid), preventDuplicates: false);
}
/// 跳转到充值/会员页(tabPosition==1 → 金币,否则 → 会员)
/// [sourcePage] 落地页下单时的来源。不传时各分支用各自的默认:会员页记会员中心
/// (绝大多数入口都是「跳进会员页再下单」),金币页记 UNKNOWN(没有专属枚举,别拿会员的顶上);
/// 有独立来源的(H5 活动等)自己传
Future pushToWalletPage(
{int? tabPosition, String? vipId, PaySourcePage? sourcePage}) async {
if (tabPosition == 1) {
return Get.to(
MineChargeCoinPage(sourcePage: sourcePage ?? PaySourcePage.unknown),
preventDuplicates: false);
}
return Get.to(
MineChargeVipPage(
vipID: vipId?.isNotEmpty == true ? vipId : null,
sourcePage: sourcePage ?? PaySourcePage.vipCenter,
),
preventDuplicates: false,
);
}
/// 跳转客服系统
void pushToCustomService() async {
LoadingAlertWidget.show();
final url = await MineService.fetchCustomService();
LoadingAlertWidget.cancel();
if (url?.isNotEmpty == true) {
final h5Url = '${Address.baseHost}/api$url';
Get.to(H5Page(url: h5Url, title: '在线客服'), opaque: false);
}
}
+33
View File
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgdj/tools_base/global_store/store.dart';
import '../hj_page/mine/mine_setting/mine_password_logic.dart';
import '../hj_page/mine/mine_setting/mine_password_page.dart';
import '../hj_page/splash/splash_page.dart';
/// 只保留这两条:其余页面一律 Get.to(() => XxxPage())。
/// SplashPage 是 initialRoute
/// MinePasswordPage 是中间件 redirect 的目标,只能按名解析。
class AppRoutes {
static final routePages = [
GetPage(
name: SplashPage.routeName,
page: () => const SplashPage(),
middlewares: [SplashPasswordMiddleware()],
),
GetPage(
name: MinePasswordPage.routeName,
page: () => const MinePasswordPage()), //设置锁屏密码
];
}
class SplashPasswordMiddleware extends GetMiddleware {
@override
RouteSettings? redirect(String? route) {
if (globalStore.password.isEmpty || globalStore.isUnlocked)
return super.redirect(route);
return RouteSettings(
name: MinePasswordPage.routeName, arguments: MinePasswordType.check);
}
}