初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:get/get.dart';
import 'package:hgdj/hj_page/mine/mine_vip/pay_order_source.dart';
import 'package:hgdj/routers/jump_router.dart';
class H5Logic extends GetxController {
// ========== 属性声明 ==========
final String? url;
H5Logic({this.url});
InAppWebViewController? webViewCtr;
// url 兜底空字符串,防 null 强解包崩溃
URLRequest get initialUrlRequest => URLRequest(url: WebUri(url ?? ''));
// ========== 公开方法 ==========
void onWebViewCreated(InAppWebViewController controller) {
webViewCtr = controller;
_setupHandlers(controller);
}
// ========== 私有方法 ==========
// 注册 H5 与 native 的 JS 桥
void _setupHandlers(InAppWebViewController controller) {
controller.addJavaScriptHandler(
handlerName: 'prizeBack', callback: (_) => Get.back());
controller.addJavaScriptHandler(
handlerName: 'shopBack', callback: (_) => Get.back());
// 跳金币充值
controller.addJavaScriptHandler(
handlerName: 'shopCharge',
callback: (_) => pushToWalletPage(
tabPosition: 1, sourcePage: PaySourcePage.h5Activity),
);
// H5 触发外部链接跳转
controller.addJavaScriptHandler(
handlerName: 'jumpOutLink',
callback: (args) {
if (args.isNotEmpty && args[0] is String) {
pushToPageByLink(args[0] as String);
}
},
);
// H5 触发:直接跳系统外部浏览器(callHandler('openOutLink', url)
controller.addJavaScriptHandler(
handlerName: 'openOutLink',
callback: (args) {
if (args.isNotEmpty && args[0] is String) {
launchUrlToWeb(args[0] as String);
}
},
);
}
}
+76
View File
@@ -0,0 +1,76 @@
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:get/get.dart';
import 'package:hgdj/assets_tool/images.dart';
import 'package:hgdj/tools_base/unique_tag_mixin.dart';
import 'h5_logic.dart';
import 'h5_webview_settings.dart';
class H5Page extends StatefulWidget {
final String? url;
final String? title;
final bool isNeedScaffold;
final bool showTitle;
final bool showClose;
const H5Page({
super.key,
this.url,
this.title,
this.isNeedScaffold = true,
this.showTitle = true,
this.showClose = false,
});
@override
State<H5Page> createState() => _H5PageState();
}
class _H5PageState extends State<H5Page> with UniqueTagMixin {
@override
Widget build(BuildContext context) {
return GetBuilder<H5Logic>(
tag: uniqueTag, // H5 可跳 H5、多实例并存,用 uniqueTag 隔离各自 logic
init: H5Logic(url: widget.url),
builder: (logic) {
return Scaffold(
appBar:
widget.showTitle ? AppBar(title: Text(widget.title ?? "")) : null,
body: SafeArea(
child: Stack(
children: [
_webView(logic),
if (widget.showClose) _closeButton(),
],
),
),
);
},
);
}
Widget _webView(H5Logic logic) {
return InAppWebView(
initialUrlRequest: logic.initialUrlRequest,
initialSettings: h5WebViewSettings,
initialUserScripts: UnmodifiableListView<UserScript>([]),
onWebViewCreated: logic.onWebViewCreated,
onLoadStart: (_, url) => debugPrint("onPageFinished$url"),
);
}
Widget _closeButton() {
return Positioned(
top: 20,
right: 16,
child: InkWell(
enableFeedback: false,
onTap: () => Get.back(),
child: Image.asset('search_close.png'.commonImgPath, width: 30),
),
);
}
}
@@ -0,0 +1,16 @@
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
/// 项目内 H5 WebView 的公共配置
///
/// iOS 不配这两个媒体开关时,H5 里 <video autoplay muted playsinline> 的动态背景放不出来,
/// 元素区域直接一块纯黑(首页红包雨背景踩过:Android 正常、iOS 全黑,且 H5 侧 play() 的
/// 失败被 catch 吞掉,端上看不到任何报错)。
final h5WebViewSettings = InAppWebViewSettings(
javaScriptEnabled: true,
// 媒体自动播放不要求用户手势:H5 是在 canplay 回调里 play() 的,不配这个会被直接拦掉
mediaPlaybackRequiresUserGesture: false,
// iOS:允许内联播放,不配的话 playsinline 属性会被 WKWebView 忽略,视频只能全屏播
allowsInlineMediaPlayback: true,
// iOS:循环播放的背景视频别进画中画
allowsPictureInPictureMediaPlayback: false,
);