import 'dart:async'; import 'package:ef/ef.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:vbvs_app/common/color/app_uri_status.dart'; import 'package:vbvs_app/common/util/CommonVariables.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/model/api_response.dart'; ThemeController themeController = Get.find(); Future initDataEf({String key = ""}) async { await ef.init( '${CommonVariables.supabaseUrl}/', key, nosqlEnableWebsocket: false, ); } class MyUtils { static ApiResponse formatResponse( ApiResponse res, String successMsg, String errorMsg, ) { if (res.code == HttpStatusCodes.ok) { // 成功但 msg 为空时填默认成功提示 if (res.msg == null || res.msg!.isEmpty) { res.msg = successMsg; } } else { // 失败且 msg 为空时填默认失败提示 if (res.msg == null || res.msg!.isEmpty) { res.msg = errorMsg; } } return res; } static String timestampToDateString(int timestamp) { DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp); String formattedDate = '${dateTime.year}-${dateTime.month.toString().padLeft(2, '0')}-${dateTime.day.toString().padLeft(2, '0')} ' '${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}:${dateTime.second.toString().padLeft(2, '0')}'; return formattedDate; } static String hidePhoneNumber(String phoneNumber) { if (phoneNumber.length != 11) { // 检查手机号是否为11位 throw Exception("手机号格式不正确"); } // 将中间四位替换为星号 return phoneNumber.replaceRange(3, 7, '****'); } static double initialScrollOffset = 0.0; // 判断手机号格式是否正确的方法 static bool isValidPhoneNumber(String phoneNumber) { final RegExp phoneRegExp = RegExp(r'^1[3-9]\d{9}$'); return phoneRegExp.hasMatch(phoneNumber); } static bool isValidEmail(String email) { final RegExp emailRegExp = RegExp( r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', ); return emailRegExp.hasMatch(email); } static Future makePhoneCall(String phoneNumber) async { final Uri launchUri = Uri( scheme: 'tel', path: phoneNumber, ); if (await canLaunchUrl(launchUri)) { await launchUrl(launchUri); } else { throw '无法拨打电话'; } } static String formatDateTime(DateTime dateTime) { // 定义日期格式 // dateTime.toLocal(); final DateFormat formatter = DateFormat('yyyy-MM-dd HH:mm'); // 返回格式化后的字符串 return formatter.format(dateTime); } static void scrollToFocusedInput(FocusNode focusNode, _scrollController) { // 获取输入框相对于整个页面的偏移量 RenderObject? object = focusNode.context?.findRenderObject(); if (object != null) { final RenderBox box = object as RenderBox; final Offset position = box.localToGlobal(Offset.zero); // 将页面滚动到使输入框显示在屏幕上的位置 _scrollController.animateTo( position.dy - MediaQuery.of(focusNode.context!).size.height / 4, duration: Duration(milliseconds: 300), curve: Curves.easeInOut, ); } } static void resetScrollPosition(_scrollController) { _scrollController.animateTo( initialScrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeInOut, ); } } Color stringToColor(String hexColor) { String formattedColor = hexColor.replaceAll("#", ""); int colorValue = int.parse("0xFF$formattedColor"); return Color(colorValue); } //字节转16进制 String ab2str(List buffer) { return buffer.map((x) => x.toRadixString(16).padLeft(2, '0')).join(''); } enum ToastColor { success, error, warn } ToastColor color_success = ToastColor.success; ToastColor color_warning = ToastColor.warn; ToastColor color_error = ToastColor.error; showToast(String msg, {ToastColor color = ToastColor.error, int closeTime = 3}) { // Fluttertoast.showToast( // msg: msg, // toastLength: Toast.LENGTH_LONG, // gravity: ToastGravity.CENTER, // timeInSecForIosWeb: 1, // backgroundColor: color == null ? color_error : color, // fontSize: 14.0, // ); final context = Get.overlayContext; // 获取 Overlay 的上下文 Color background = Colors.red; Color color_text = stringToColor("#FA5A4C"); String icon = ""; if (color == color_success) { background = stringToColor("#DBF1E1"); icon = "success"; color_text = stringToColor("#31CA79"); } else if (color == color_warning) { background = stringToColor("#FDF6EC"); icon = "warn"; color_text = stringToColor("#F8AE00"); } else if (color == color_error) { background = stringToColor("#FEF0F0"); icon = "error"; color_text = stringToColor("#FA5A4C"); } if (context == null) return; OverlayEntry overlayEntry = OverlayEntry( builder: (context) => Positioned( top: MediaQuery.of(context).size.height * 0.10, left: MediaQuery.of(context).size.width * 0.5 - 225.rpx, child: Material( color: Colors.transparent, child: Container( width: 450.rpx, padding: EdgeInsets.only(top: 20.rpx, bottom: 20.rpx), decoration: BoxDecoration( color: background, borderRadius: BorderRadius.circular(10.rpx), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( "assets/images/toast/${icon}_.png", width: 30.rpx, height: 30.rpx, ), SizedBox( width: 18.rpx, ), Container( constraints: BoxConstraints(maxWidth: 380.rpx), child: Text( msg, maxLines: 9, style: TextStyle( color: color_text, fontSize: 28.rpx, fontWeight: FontWeight.w400), ), ) ], ), ), ), ), ); Overlay.of(context)?.insert(overlayEntry); Future.delayed(Duration(seconds: closeTime), () { overlayEntry.remove(); }); } var closeIcon = GestureDetector( onTapDown: (f) { Get.back(); }, child: Container( padding: EdgeInsets.fromLTRB(10.rpx, 18.rpx, 10.rpx, 10.rpx), child: Container( height: 42.rpx, width: 42.rpx, alignment: Alignment.center, child: Icon( Icons.close, ), ), ), ); var closeIconWhite = GestureDetector( onTapDown: (f) { Get.back(); }, child: Container( padding: EdgeInsets.all(10.rpx), child: Container( height: 42.rpx, width: 42.rpx, alignment: Alignment.center, child: Icon( Icons.close, color: themeController.currentColor.sc3, ), ), ), ); var returnIconButtom = IconButton( // padding: EdgeInsets.zero, // 去除默认 padding // constraints: BoxConstraints(), // 去除最小尺寸限制 onPressed: () => Get.back(), icon: Icon(Icons.navigate_before, size: 60.rpx), ); var returnIconButtomAddCallback = (returnCallBack) { return IconButton( onPressed: () { returnCallBack?.call(); Get.back(); }, icon: Icon(Icons.navigate_before, size: 60.rpx), ); }; String time_08_Formatter(String time) { if (time == null || time == "") { return ""; } return DateFormat("yyyy-MM-dd HH:mm:ss") .format(DateTime.parse(time).toLocal()); } String time_08_Formatter_pattern(String time, String pattern) { if (time == null || time == "") { return ""; } return DateFormat(pattern).format(DateTime.parse(time).toLocal()); } String storagePubSrc = "${CommonVariables.supabaseUrl}/storage/v1/object/public/"; getStorageResourceUrl(String v) { if (v.contains('http')) { return v; } return storagePubSrc + v; } enum LoadingDialogIcon { ble, wifi, none } class LoadingDialog { static show(String name, {LoadingDialogIcon icon = LoadingDialogIcon.none}) { ThemeController themeController = Get.find(); String iconUrl = ""; if (icon == LoadingDialogIcon.wifi) { iconUrl = "wifi"; } else if (icon == LoadingDialogIcon.ble) { iconUrl = "ble"; } Get.dialog( PopScope( canPop: false, child: Container( // color: Colors.transparent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( constraints: BoxConstraints(minWidth: 300.rpx, maxWidth: 500.rpx), decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if (iconUrl.isNotEmpty) Container( width: 120.rpx, height: 120.rpx, margin: EdgeInsets.only(bottom: 60.rpx), child: Image.asset("assets/images/toast/${iconUrl}.png"), ), Text( textAlign: TextAlign.center, name, style: TextStyle( fontSize: 16, color: themeController.currentColor.sc3, decoration: TextDecoration.none), ), SizedBox( height: 30.rpx, ), CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( themeController.currentColor.sc3, ), ), ], ), ) ], ), ), ), barrierDismissible: false, barrierColor: Color.fromRGBO(0, 0, 0, 0.8)); } static hide() { Get.back(); } }