193 lines
6.5 KiB
Dart
Executable File
193 lines
6.5 KiB
Dart
Executable File
import 'package:get/get.dart';
|
|
import 'package:webview_flutter/webview_flutter.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
|
import 'dart:io' show Platform;
|
|
|
|
import 'package:kaer_with_panels/app/services/api_service/api.dart';
|
|
import 'package:kaer_with_panels/app/services/api_service/kr_web_api.dart';
|
|
import 'package:kaer_with_panels/app/localization/app_translations.dart';
|
|
|
|
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
|
|
|
|
/// WebView 控制器
|
|
/// 用于管理 WebView 的状态和行为
|
|
class KRWebViewController extends GetxController {
|
|
// 页面加载状态
|
|
final RxBool kr_isLoading = true.obs;
|
|
|
|
// 页面标题
|
|
final RxString kr_title = ''.obs;
|
|
|
|
// WebView 控制器
|
|
late final WebViewController kr_webViewController;
|
|
|
|
// 默认URL
|
|
static const String kr_defaultUrl = '';
|
|
|
|
final String kr_url = Get.arguments['url'] as String;
|
|
|
|
// Web API 实例
|
|
final KRWebApi _kr_webApi = KRWebApi();
|
|
|
|
// 内容类型
|
|
final RxBool kr_isHtml = false.obs;
|
|
final RxBool kr_isMarkdown = false.obs;
|
|
final RxString kr_content = ''.obs;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
// 根据 URL 类型决定初始化方式
|
|
if (kr_url.contains(Api.kr_getSiteTos) || kr_url.contains(Api.kr_getSitePrivacy)) {
|
|
// 用户协议和隐私政策页面,直接获取文本内容
|
|
if (kr_url.contains(Api.kr_getSiteTos)) {
|
|
kr_title.value = AppTranslations.kr_login.termsOfService;
|
|
} else {
|
|
kr_title.value = AppTranslations.kr_login.privacyPolicy;
|
|
}
|
|
kr_getWebText();
|
|
} else {
|
|
// 其他页面,初始化 WebView
|
|
kr_initWebView();
|
|
}
|
|
}
|
|
|
|
/// 初始化 WebView
|
|
void kr_initWebView() {
|
|
kr_webViewController = WebViewController()
|
|
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
|
..setNavigationDelegate(
|
|
NavigationDelegate(
|
|
onNavigationRequest: (NavigationRequest request) async {
|
|
// 只在移动平台处理支付应用跳转
|
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
|
KRLogUtil.kr_i('处理支付链接: ${request.url}', tag: 'WebViewController');
|
|
// 处理支付链接
|
|
if (await kr_handleUrlLaunch(request.url)) {
|
|
return NavigationDecision.prevent;
|
|
}
|
|
}
|
|
return NavigationDecision.navigate;
|
|
},
|
|
onPageStarted: kr_handlePageStarted,
|
|
onPageFinished: kr_handlePageFinished,
|
|
),
|
|
);
|
|
|
|
// 检查是否是用户协议或隐私政策
|
|
if (kr_url.contains(Api.kr_getSiteTos) || kr_url.contains(Api.kr_getSitePrivacy)) {
|
|
kr_getWebText();
|
|
} else {
|
|
kr_webViewController.loadRequest(Uri.parse(kr_url));
|
|
}
|
|
}
|
|
|
|
/// 获取网页文本内容并加载到 WebView
|
|
Future<void> kr_getWebText() async {
|
|
try {
|
|
final response = await _kr_webApi.kr_getWebText(kr_url);
|
|
response.fold(
|
|
(error) async {
|
|
KRLogUtil.kr_e('获取网页内容失败: $error', tag: 'WebViewController');
|
|
// 如果获取失败,直接设置错误内容
|
|
kr_content.value = 'Failed to load, please try again later';
|
|
kr_isLoading.value = false;
|
|
},
|
|
(content) async {
|
|
KRLogUtil.kr_i('获取到内容: $content', tag: 'WebViewController');
|
|
// 判断内容类型,优先判断 Markdown
|
|
kr_isMarkdown.value = content.contains('**') ||
|
|
content.contains('*') ||
|
|
content.contains('#') ||
|
|
content.contains('- ') ||
|
|
content.contains('[');
|
|
kr_isHtml.value = !kr_isMarkdown.value && content.contains('<') && content.contains('>');
|
|
|
|
KRLogUtil.kr_i('内容类型 - Markdown: ${kr_isMarkdown.value}, HTML: ${kr_isHtml.value}', tag: 'WebViewController');
|
|
|
|
if (kr_isMarkdown.value) {
|
|
// 如果是 Markdown 内容,直接使用
|
|
kr_content.value = content;
|
|
} else if (kr_isHtml.value) {
|
|
// 如果是 HTML 内容,直接使用
|
|
kr_content.value = content;
|
|
} else {
|
|
// 如果是普通文本,直接使用
|
|
kr_content.value = content;
|
|
}
|
|
|
|
kr_isLoading.value = false;
|
|
},
|
|
);
|
|
} catch (e) {
|
|
KRLogUtil.kr_e('获取网页内容出错: $e', tag: 'WebViewController');
|
|
kr_content.value = 'Loading error, please try again later';
|
|
kr_isLoading.value = false;
|
|
}
|
|
}
|
|
|
|
/// 处理页面开始加载事件
|
|
void kr_handlePageStarted(String url) {
|
|
kr_isLoading.value = true;
|
|
}
|
|
|
|
/// 处理页面加载完成事件
|
|
void kr_handlePageFinished(String url) async {
|
|
kr_isLoading.value = false;
|
|
await kr_updateTitle();
|
|
}
|
|
|
|
/// 更新页面标题
|
|
Future<void> kr_updateTitle() async {
|
|
final String? kr_pageTitle = await kr_webViewController.getTitle();
|
|
kr_title.value = kr_pageTitle ?? '';
|
|
}
|
|
|
|
/// 重新加载页面
|
|
Future<void> kr_reloadPage() async {
|
|
await kr_webViewController.reload();
|
|
}
|
|
|
|
/// 加载新的URL
|
|
Future<void> kr_loadUrl(String url) async {
|
|
await kr_webViewController.loadRequest(Uri.parse(url));
|
|
}
|
|
|
|
/// 处理URL启动
|
|
Future<bool> kr_handleUrlLaunch(String url) async {
|
|
try {
|
|
KRLogUtil.kr_i('正在处理URL跳转: $url', tag: 'WebViewController');
|
|
final uri = Uri.parse(url);
|
|
// 处理支付应用和外部链接
|
|
if (uri.scheme == 'alipays' ||
|
|
uri.scheme == 'alipay' ||
|
|
uri.scheme == 'weixin' ||
|
|
uri.scheme == 'wx') {
|
|
KRLogUtil.kr_i('检测到支付应用scheme: ${uri.scheme}', tag: 'WebViewController');
|
|
// 尝试打开支付应用
|
|
if (await canLaunchUrl(uri)) {
|
|
return await launchUrl(
|
|
uri,
|
|
mode: LaunchMode.externalApplication,
|
|
);
|
|
}
|
|
// 如果支付应用无法打开,尝试使用外部浏览器打开
|
|
final httpUri = Uri.parse('https://${uri.host}${uri.path}?${uri.query}');
|
|
KRLogUtil.kr_i('尝试使用浏览器打开: $httpUri', tag: 'WebViewController');
|
|
if (await canLaunchUrl(httpUri)) {
|
|
return await launchUrl(
|
|
httpUri,
|
|
mode: LaunchMode.externalApplication,
|
|
);
|
|
}
|
|
KRLogUtil.kr_e('无法启动URL: $url', tag: 'WebViewController');
|
|
}
|
|
return false;
|
|
} catch (e) {
|
|
KRLogUtil.kr_e('URL跳转错误: $e', tag: 'WebViewController');
|
|
return false;
|
|
}
|
|
}
|
|
}
|