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/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/vid_service.dart'; import '../tools_base/event_bus/event_bus_util.dart'; /// 跳转视频/动漫/短视频详情页 /// - [isCartoon] 优先级最高 → 长视频页(标记动漫) /// - newsType == SEED_LINK → ACG 游戏详情页 /// - playTime < 300 且非 0 → 短视频 /// - 其余 → 长视频 /// - [videoModel] / [videoId] 必传其一 Future? pushToVideoPage({ String? videoId, VideoModel? videoModel, bool isCartoon = false, String? videoCover, List? 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 必非 null,playTime 取自它) 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? 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 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 "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.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, ); }