hi-client/lib/app/utils/kr_common_util.dart
2026-01-09 01:36:24 -08:00

148 lines
4.3 KiB
Dart
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher.dart';
import '../widgets/kr_toast.dart';
import '../common/app_config.dart';
import '../routes/app_pages.dart';
import '../widgets/dialogs/hi_dialog.dart';
import '../modules/kr_crisp_chat/controllers/kr_crisp_controller.dart';
class KRCommonUtil {
/// 是否正在打开客服(防重复点击)
static bool _kr_isOpeningCustomerService = false;
/// 预热客服(提前初始化控制器)
static void kr_warmUpCustomerService() {
if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
if (!Get.isRegistered<KRCrispController>()) {
Get.put(KRCrispController(), permanent: true);
debugPrint('客服系统预热中(持久模式)...');
}
}
}
/// 打开客服
static Future<void> kr_openCustomerService() async {
// 🔧 防重复点击
if (_kr_isOpeningCustomerService) {
return;
}
final websiteId = AppConfig.getInstance().kr_website_id;
if (websiteId.isEmpty) {
HIDialog.show(
title: '提示',
message: '加载失败',
);
return;
}
// 🔧 Windows 端直接跳转外部浏览器
if (Platform.isWindows) {
_kr_isOpeningCustomerService = true;
// 显示加载提示
kr_showToast('userInfo.openingCustomerService'.tr);
// 直接使用 zh
final Uri url = Uri.parse(
'https://go.crisp.chat/chat/embed/?website_id=$websiteId&locale=zh',
);
try {
if (await canLaunchUrl(url)) {
await launchUrl(url, mode: LaunchMode.externalApplication);
} else {
kr_showToast("common.cannotOpenBrowser".tr);
}
} catch (e) {
kr_showToast("common.openLinkFailed".tr);
} finally {
// 延迟重置状态
Future.delayed(const Duration(seconds: 2), () {
_kr_isOpeningCustomerService = false;
});
}
return;
}
// 移动平台 (Android/iOS):直接调用原生 SDK避免页面跳转闪烁
if (Platform.isAndroid || Platform.isIOS) {
_kr_isOpeningCustomerService = true;
// 预先显示加载提示(可选,原生 SDK 启动很快)
// kr_showToast('userInfo.openingCustomerService'.tr);
try {
// 优先使用已注册的控制器
KRCrispController crispController;
if (Get.isRegistered<KRCrispController>()) {
crispController = Get.find<KRCrispController>();
} else {
crispController = Get.put(KRCrispController(), permanent: true);
}
// 直接调用原生打开方法
await crispController.kr_openNativeCrispChat();
} catch (e) {
debugPrint('打开原生客服失败: $e');
// 如果原生失败,可以考虑降级到内置页面或报错
Get.toNamed(Routes.KR_CRISP);
} finally {
Future.delayed(const Duration(seconds: 2), () {
_kr_isOpeningCustomerService = false;
});
}
return;
}
// macOS/桌面平台:跳转内置页面 (WebView 实现)
_kr_isOpeningCustomerService = true;
Get.toNamed(Routes.KR_CRISP);
// 延迟重置状态
Future.delayed(const Duration(seconds: 2), () {
_kr_isOpeningCustomerService = false;
});
}
/// 提示 meesage: 提示内容, toastPosition: 提示显示的位置, timeout: 显示时间(毫秒)
static kr_showToast(String message,
{KRToastPosition toastPosition = KRToastPosition.center,
int timeout = 2500}) {
KRToast.kr_showToast(
message,
position: toastPosition,
duration: Duration(milliseconds: timeout),
);
}
/// 显示加载动画
static kr_showLoading({String? message}) {
KRToast.kr_showLoading(message: message);
}
/// 隐藏加载动画
static kr_hideLoading() {
KRToast.kr_hideLoading();
}
/// 格式化字节数为可读字符串
/// [bytes] 字节数
static String kr_formatBytes(int bytes) {
if (bytes <= 0) return "0 B";
const List<String> suffixes = ["B", "KB", "MB", "GB", "TB"];
int i = 0;
double value = bytes.toDouble();
while (value >= 1024 && i < suffixes.length - 1) {
value /= 1024;
i++;
}
return "${value.toStringAsFixed(2)} ${suffixes[i]}";
}
}