util.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'dart:math';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter/widgets.dart';
  7. import 'log_utils.dart';
  8. import 'package:intl/intl.dart';
  9. class Utils {
  10. /// 是否字符串为空
  11. static bool isEmpty(String? value) {
  12. if (value == null) {
  13. return true;
  14. }
  15. return value.isEmpty || value == 'null';
  16. }
  17. /// 字符串是否不为空
  18. static bool isNotEmpty(String? value) {
  19. return !isEmpty(value);
  20. }
  21. /// 判断邮箱
  22. static isEmail(dynamic value, {String? country = "sg"}) {
  23. switch (country) {
  24. case "sg":
  25. RegExp regExp = RegExp(r"^\w{1,}(.\w+)*@[A-z0-9]+(\.[A-z]{2,6}){1,2}$");
  26. if (regExp.hasMatch(value.toString())) {
  27. return true;
  28. } else {
  29. return false;
  30. }
  31. default:
  32. return false;
  33. }
  34. }
  35. /// 判断中国的11位手机号码
  36. static bool isChinaPhoneNumber(dynamic value) {
  37. RegExp regExp = RegExp(r"^1\d{10}$"); // 匹配以1开头的11位数字
  38. if (regExp.hasMatch(value.toString())) {
  39. return true;
  40. } else {
  41. return false;
  42. }
  43. }
  44. /// 全局的路由key
  45. static final navKey = GlobalKey<NavigatorState>();
  46. /// 全局的组件key
  47. static final widgetKey = GlobalKey<State>();
  48. //页面缓存key
  49. static dynamic pageStorageKey(dynamic keyname) {
  50. return PageStorageKey<dynamic>(keyname);
  51. }
  52. /// 关闭软键盘
  53. static void hideKeyboard(BuildContext context) {
  54. FocusScopeNode currentFocus = FocusScope.of(context);
  55. if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
  56. FocusManager.instance.primaryFocus!.unfocus();
  57. }
  58. }
  59. /// map 转 json 字符串
  60. static String encodeMap(Map<String, dynamic> mapData) {
  61. return json.encode(mapData);
  62. }
  63. /// json 字符串转 map
  64. static Map<String, dynamic> decodeJson(jsonStr) {
  65. return json.decode(jsonStr.toString());
  66. }
  67. /// 判断颜色是否是暗色还是亮色
  68. static num getComputeLuminance(Color color) {
  69. return color.computeLuminance();
  70. }
  71. /// 随机获取指定返回内的数值
  72. static int getRandomRangeInt(int min, int max) {
  73. final Random random = Random();
  74. return min + random.nextInt(max + 1 - min);
  75. }
  76. /// 无参数的防抖函数
  77. static VoidCallback debounce(
  78. VoidCallback func, [
  79. Duration delay = const Duration(milliseconds: 400),
  80. ]) {
  81. late Timer timer;
  82. return () {
  83. if (timer.isActive == true) {
  84. timer.cancel();
  85. }
  86. timer = Timer(delay, () {
  87. func.call();
  88. });
  89. };
  90. }
  91. /// 带参数的防抖函数
  92. static Function debounceArg<T>(
  93. Function func, [
  94. Duration delay = const Duration(milliseconds: 2000),
  95. ]) {
  96. late Timer timer;
  97. return (T arg) {
  98. if (timer.isActive == true) {
  99. timer.cancel();
  100. }
  101. timer = Timer(delay, () {
  102. func.call(arg);
  103. });
  104. };
  105. }
  106. /// 将时间转化为 多久之前
  107. static String getTimeAgo(String? dateTimeStr,{ String? format}) {
  108. if (dateTimeStr == null || dateTimeStr.isEmpty) {
  109. return 'Unknown time'; // 或者返回其他默认值
  110. }
  111. DateTime? dateTime;
  112. try {
  113. if (format == null){
  114. dateTime = DateTime.parse(dateTimeStr);
  115. }else{
  116. //如果有指定的格式可以按照这个格式来解析时间
  117. DateFormat dateFormat = DateFormat(format, 'en_US');
  118. dateTime = dateFormat.parse(dateTimeStr);
  119. Log.d("dateTime:$dateTime");
  120. }
  121. } catch (e) {
  122. Log.e("Error parsing date: $e");
  123. return 'Invalid date format'; // 或者返回其他默认值
  124. }
  125. if (dateTime == null) {
  126. return 'Unknown time'; // 或者返回其他默认值
  127. }
  128. final now = DateTime.now();
  129. final difference = now.difference(dateTime);
  130. if (difference.inHours < 1) {
  131. return "${difference.inMinutes} minutes ago";
  132. } else if (difference.inHours < 24) {
  133. return "${difference.inHours} hours ago";
  134. } else if (difference.inDays < 7) {
  135. return "${difference.inDays} days ago";
  136. } else if (difference.inDays < 30) {
  137. return "${(difference.inDays / 7).floor()} weeks ago";
  138. } else if (difference.inDays < 365) {
  139. return "${(difference.inDays / 30).floor()} months ago";
  140. } else {
  141. return "${(difference.inDays / 365).floor()} years ago";
  142. }
  143. }
  144. /// 从 Url 中找到对应的宽高
  145. static List<double>? extractWidthHeight(String? url) {
  146. if (isEmpty(url)) return null;
  147. // 使用正则表达式来查找形如 "宽x高" 的部分
  148. final RegExp regex = RegExp(r'-(\d+)x(\d+)\.');
  149. final matches = regex.allMatches(url!);
  150. if (matches.isNotEmpty) {
  151. // 获取最后一个匹配项
  152. final lastMatch = matches.last;
  153. final width = double.parse(lastMatch.group(1)!);
  154. final height = double.parse(lastMatch.group(2)!);
  155. return [width, height]; // 返回宽高列表
  156. }
  157. return null; // 未找到宽高
  158. }
  159. /// 将字符串的前三位和后两位显示,中间用 * 替代。
  160. static String maskString(String input) {
  161. // 检查字符串长度
  162. if (input.length <= 5) {
  163. // 如果字符串长度小于等于5,直接返回原字符串
  164. return input;
  165. }
  166. // 获取前三位和后两位
  167. String start = input.substring(0, 3);
  168. String end = input.substring(input.length - 2);
  169. // 计算中间需要的 * 的数量
  170. int asterisksCount = input.length - 5; // 计算需要的 * 的数量
  171. String asterisks = '*' * asterisksCount; // 创建 * 字符串
  172. // 拼接成新的字符串
  173. return '$start$asterisks$end';
  174. }
  175. /// 获取实际手机号码
  176. static String getRealMobile(String mobile) {
  177. mobile = mobile.trim();
  178. // 判断属于哪一个国家区号
  179. if (mobile.startsWith("+1-")) {
  180. return mobile.substring(3);
  181. } else if (mobile.startsWith("+1")) {
  182. return mobile.substring(2);
  183. } else if (mobile.startsWith("+31-")) {
  184. return mobile.substring(4);
  185. } else if (mobile.startsWith("+31")) {
  186. return mobile.substring(3);
  187. } else if (mobile.startsWith("+33-")) {
  188. return mobile.substring(4);
  189. } else if (mobile.startsWith("+33")) {
  190. return mobile.substring(3);
  191. } else if (mobile.startsWith("+34-")) {
  192. return mobile.substring(4);
  193. } else if (mobile.startsWith("+34")) {
  194. return mobile.substring(3);
  195. } else if (mobile.startsWith("+39-")) {
  196. return mobile.substring(4);
  197. } else if (mobile.startsWith("+39")) {
  198. return mobile.substring(3);
  199. } else if (mobile.startsWith("+44-")) {
  200. return mobile.substring(4);
  201. } else if (mobile.startsWith("+44")) {
  202. return mobile.substring(3);
  203. } else if (mobile.startsWith("+49-")) {
  204. return mobile.substring(4);
  205. } else if (mobile.startsWith("+49")) {
  206. return mobile.substring(3);
  207. } else if (mobile.startsWith("+60-")) {
  208. return mobile.substring(4);
  209. } else if (mobile.startsWith("+60")) {
  210. return mobile.substring(3);
  211. } else if (mobile.startsWith("+61-")) {
  212. return mobile.substring(4);
  213. } else if (mobile.startsWith("+61")) {
  214. return mobile.substring(3);
  215. } else if (mobile.startsWith("+62-")) {
  216. return mobile.substring(4);
  217. } else if (mobile.startsWith("+62")) {
  218. return mobile.substring(3);
  219. } else if (mobile.startsWith("+63-")) {
  220. return mobile.substring(4);
  221. } else if (mobile.startsWith("+63")) {
  222. return mobile.substring(3);
  223. } else if (mobile.startsWith("+65-")) {
  224. return mobile.substring(4);
  225. } else if (mobile.startsWith("+65")) {
  226. return mobile.substring(3);
  227. } else if (mobile.startsWith("+66-")) {
  228. return mobile.substring(4);
  229. } else if (mobile.startsWith("+66")) {
  230. return mobile.substring(3);
  231. } else if (mobile.startsWith("+81-")) {
  232. return mobile.substring(4);
  233. } else if (mobile.startsWith("+81")) {
  234. return mobile.substring(3);
  235. } else if (mobile.startsWith("+82-")) {
  236. return mobile.substring(4);
  237. } else if (mobile.startsWith("+82")) {
  238. return mobile.substring(3);
  239. } else if (mobile.startsWith("+84-")) {
  240. return mobile.substring(4);
  241. } else if (mobile.startsWith("+84")) {
  242. return mobile.substring(3);
  243. } else if (mobile.startsWith("+86-")) {
  244. return mobile.substring(4);
  245. } else if (mobile.startsWith("+86")) {
  246. return mobile.substring(3);
  247. } else if (mobile.startsWith("+852-")) {
  248. return mobile.substring(5);
  249. } else if (mobile.startsWith("+852")) {
  250. return mobile.substring(4);
  251. } else if (mobile.startsWith("+855-")) {
  252. return mobile.substring(5);
  253. } else if (mobile.startsWith("+855")) {
  254. return mobile.substring(4);
  255. } else if (mobile.startsWith("+971-")) {
  256. return mobile.substring(5);
  257. } else if (mobile.startsWith("+971")) {
  258. return mobile.substring(4);
  259. } else {
  260. return mobile; // 返回原始手机号
  261. }
  262. }
  263. /// 获取国家区号
  264. static String getMobileCode(String mobile) {
  265. mobile = mobile.trim();
  266. // 判断属于哪一个国家区号
  267. if (mobile.startsWith("1") || mobile.startsWith("+1") || mobile.startsWith("1-") || mobile.startsWith("+1-")) {
  268. return "+1";
  269. } else if (mobile.startsWith("31") || mobile.startsWith("+31") || mobile.startsWith("31-") || mobile.startsWith("+31-")) {
  270. return "+31";
  271. } else if (mobile.startsWith("33") || mobile.startsWith("+33") || mobile.startsWith("33-") || mobile.startsWith("+33-")) {
  272. return "+33";
  273. } else if (mobile.startsWith("34") || mobile.startsWith("+34") || mobile.startsWith("34-") || mobile.startsWith("+34-")) {
  274. return "+34";
  275. } else if (mobile.startsWith("39") || mobile.startsWith("+39") || mobile.startsWith("39-") || mobile.startsWith("+39-")) {
  276. return "+39";
  277. } else if (mobile.startsWith("44") || mobile.startsWith("+44") || mobile.startsWith("44-") || mobile.startsWith("+44-")) {
  278. return "+44";
  279. } else if (mobile.startsWith("49") || mobile.startsWith("+49") || mobile.startsWith("49-") || mobile.startsWith("+49-")) {
  280. return "+49";
  281. } else if (mobile.startsWith("60") || mobile.startsWith("+60") || mobile.startsWith("60-") || mobile.startsWith("+60-")) {
  282. return "+60";
  283. } else if (mobile.startsWith("61") || mobile.startsWith("+61") || mobile.startsWith("61-") || mobile.startsWith("+61-")) {
  284. return "+61";
  285. } else if (mobile.startsWith("62") || mobile.startsWith("+62") || mobile.startsWith("62-") || mobile.startsWith("+62-")) {
  286. return "+62";
  287. } else if (mobile.startsWith("63") || mobile.startsWith("+63") || mobile.startsWith("63-") || mobile.startsWith("+63-")) {
  288. return "+63";
  289. } else if (mobile.startsWith("65") || mobile.startsWith("+65") || mobile.startsWith("65-") || mobile.startsWith("+65-")) {
  290. return "+65";
  291. } else if (mobile.startsWith("66") || mobile.startsWith("+66") || mobile.startsWith("66-") || mobile.startsWith("+66-")) {
  292. return "+66";
  293. } else if (mobile.startsWith("81") || mobile.startsWith("+81") || mobile.startsWith("81-") || mobile.startsWith("+81-")) {
  294. return "+81";
  295. } else if (mobile.startsWith("82") || mobile.startsWith("+82") || mobile.startsWith("82-") || mobile.startsWith("+82-")) {
  296. return "+82";
  297. } else if (mobile.startsWith("84") || mobile.startsWith("+84") || mobile.startsWith("84-") || mobile.startsWith("+84-")) {
  298. return "+84";
  299. } else if (mobile.startsWith("86") || mobile.startsWith("+86") || mobile.startsWith("86-") || mobile.startsWith("+86-")) {
  300. return "+86";
  301. } else if (mobile.startsWith("852") || mobile.startsWith("+852") || mobile.startsWith("852-") || mobile.startsWith("+852-")) {
  302. return "+852";
  303. } else if (mobile.startsWith("855") || mobile.startsWith("+855") || mobile.startsWith("855-") || mobile.startsWith("+855-")) {
  304. return "+855";
  305. } else if (mobile.startsWith("971") || mobile.startsWith("+971") || mobile.startsWith("971-") || mobile.startsWith("+971-")) {
  306. return "+971";
  307. } else {
  308. return ""; // 如果没有匹配的区号,返回空字符串
  309. }
  310. }
  311. }