2025-07-21 15:46:30 +08:00
|
|
|
/// 封装常用函数
|
|
|
|
library;
|
|
|
|
|
|
|
|
import 'dart:math';
|
|
|
|
|
|
|
|
import 'package:photo_manager/photo_manager.dart';
|
|
|
|
import 'package:uuid/uuid.dart';
|
|
|
|
|
|
|
|
class Utils {
|
|
|
|
/// 随机字符串
|
|
|
|
/// * [len] 字符串长度
|
|
|
|
static guid({int len = 32}) {
|
|
|
|
String str = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
|
|
String chars = '';
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
|
|
chars += str[Random().nextInt(str.length)];
|
|
|
|
}
|
|
|
|
return chars;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 获取全局唯一标识符uuid
|
|
|
|
/// * [type] uuid类型
|
|
|
|
/// * [namespace] 生成指定内容uuid
|
|
|
|
/// https://pub.dev/packages/uuid
|
|
|
|
static uuid({String type = 'v1', String? namespace}) {
|
|
|
|
var uuid = const Uuid();
|
|
|
|
switch (type) {
|
|
|
|
// Generate a v1 (time-based) id
|
|
|
|
case 'v1':
|
|
|
|
return uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
|
|
|
|
// Generate a v4 (random) id
|
|
|
|
case 'v4':
|
|
|
|
return uuid.v4();
|
|
|
|
// Generate a v5 (namespace-name-sha1-based) id
|
|
|
|
case 'v5':
|
|
|
|
return uuid.v5(Namespace.url.value, namespace);
|
|
|
|
// Generate a v6 (time-based) id
|
|
|
|
case 'v6':
|
|
|
|
return uuid.v6();
|
|
|
|
// Generate a v7 (time-based) id
|
|
|
|
case 'v7':
|
|
|
|
return uuid.v7();
|
|
|
|
// Generate a v8 (time-random) id
|
|
|
|
case 'v8':
|
|
|
|
return uuid.v8();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 验证手机号是否正确
|
|
|
|
/// * [tel] 手机号码
|
|
|
|
static bool checkTel(tel) {
|
|
|
|
if (tel == null || tel.trim().isEmpty) return false;
|
|
|
|
final reg = RegExp(r'^1[3-9]\d{9}$');
|
|
|
|
return reg.hasMatch(tel.trim());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 是否为空
|
2025-08-21 10:50:38 +08:00
|
|
|
static bool isEmpty(val) {
|
2025-07-21 15:46:30 +08:00
|
|
|
if (val == null) return true;
|
|
|
|
if (val is bool && val == false) return true;
|
|
|
|
if (val is String) return val.isEmpty;
|
|
|
|
if (val is Iterable) return val.isEmpty;
|
|
|
|
if (val is Map) return val.isEmpty;
|
|
|
|
if (val is Set) return val.isEmpty;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 网址正则
|
|
|
|
static isUrl(path) {
|
|
|
|
// 网址正则
|
|
|
|
String urlExpString = r"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?";
|
|
|
|
RegExp reg = RegExp(urlExpString);
|
|
|
|
if (reg.hasMatch(path)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 秒数转换为时分秒
|
|
|
|
static secondsToHms(double seconds) {
|
|
|
|
// String h = ((seconds / 3600) % 24).floor().toString().padLeft(2, '0');
|
|
|
|
String m = (seconds % 3600 / 60).floor().toString().padLeft(2, '0');
|
|
|
|
String s = (seconds % 3600 % 60).floor().toString().padLeft(2, '0');
|
|
|
|
// return "$h:$m:$s";
|
|
|
|
return "$m:$s";
|
|
|
|
}
|
|
|
|
|
|
|
|
//翻译媒体库title
|
|
|
|
static String translateAlbumName(AssetPathEntity album) {
|
2025-08-21 10:50:38 +08:00
|
|
|
// logger.i(album.name);
|
2025-07-21 15:46:30 +08:00
|
|
|
final Map<String, String> albumNameMap = {
|
|
|
|
'recents': '最近项目',
|
|
|
|
'favorites': '收藏',
|
|
|
|
'videos': '视频',
|
|
|
|
'selfies': '自拍',
|
|
|
|
'live photos': '实况照片',
|
|
|
|
'portrait': '人像',
|
|
|
|
'long exposure': '长曝光',
|
|
|
|
'spatial': '空间照片',
|
|
|
|
'panoramas': '全景',
|
|
|
|
'time-lapse': '延时摄影',
|
|
|
|
'slo-mo': '慢动作',
|
|
|
|
'cinematic': '电影效果',
|
|
|
|
'bursts': '连拍',
|
|
|
|
'screenshots': '屏幕截图',
|
|
|
|
'animated': '动图',
|
|
|
|
'raw': 'RAW格式',
|
|
|
|
'hidden': '已隐藏',
|
2025-08-21 10:50:38 +08:00
|
|
|
'recent': '最近项目', // 安卓
|
|
|
|
'camera': '相机', // 安卓
|
2025-07-21 15:46:30 +08:00
|
|
|
};
|
|
|
|
return albumNameMap[album.name.toLowerCase()] ?? album.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 大数字转换
|
2025-09-20 11:21:32 +08:00
|
|
|
static String graceNumber(dynamic value) {
|
|
|
|
int number;
|
|
|
|
if (value is int) {
|
|
|
|
number = value;
|
|
|
|
} else if (value is String) {
|
|
|
|
number = int.tryParse(value) ?? 0;
|
|
|
|
} else {
|
|
|
|
number = 0;
|
|
|
|
}
|
|
|
|
|
2025-07-21 15:46:30 +08:00
|
|
|
if (number == 0) return "0";
|
|
|
|
|
|
|
|
if (number < 1000) {
|
|
|
|
return "$number";
|
|
|
|
} else if (number < 10000) {
|
|
|
|
double result = number / 1000;
|
|
|
|
return "${_trimTrailingZero(result)}k";
|
|
|
|
} else if (number < 100000000) {
|
|
|
|
double result = number / 10000;
|
|
|
|
return "${_trimTrailingZero(result)}w";
|
|
|
|
} else {
|
|
|
|
double result = number / 100000000;
|
|
|
|
return "${_trimTrailingZero(result)}亿+";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-09-03 11:25:31 +08:00
|
|
|
static String _trimTrailingZero(double number) {
|
2025-07-21 15:46:30 +08:00
|
|
|
return number.toStringAsFixed(1).replaceAll(RegExp(r'\.0$'), '');
|
|
|
|
}
|
|
|
|
|
2025-08-26 17:38:59 +08:00
|
|
|
// 处理聊天消息时间
|
2025-09-03 11:25:31 +08:00
|
|
|
static String formatChatTime(int timestamp) {
|
2025-07-21 15:46:30 +08:00
|
|
|
// timestamp 是秒级时间戳,转成 DateTime
|
|
|
|
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
|
|
|
|
|
|
|
|
final now = DateTime.now();
|
|
|
|
final today = DateTime(now.year, now.month, now.day);
|
|
|
|
final msgDay = DateTime(dateTime.year, dateTime.month, dateTime.day);
|
|
|
|
|
|
|
|
final difference = now.difference(dateTime);
|
|
|
|
|
|
|
|
if (msgDay == today) {
|
|
|
|
return _formatHourMinute(dateTime);
|
|
|
|
} else if (msgDay == today.subtract(Duration(days: 1))) {
|
|
|
|
return "昨天 ${_formatHourMinute(dateTime)}";
|
|
|
|
} else if (difference.inDays < 7) {
|
|
|
|
return "${_weekdayLabel(dateTime.weekday)} ${_formatHourMinute(dateTime)}";
|
|
|
|
} else if (dateTime.year == now.year) {
|
|
|
|
return "${dateTime.month}月${dateTime.day}日 ${_formatHourMinute(dateTime)}";
|
|
|
|
} else {
|
|
|
|
return "${dateTime.year}年${dateTime.month}月${dateTime.day}日 ${_formatHourMinute(dateTime)}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-08-26 17:38:59 +08:00
|
|
|
// 处理IM消息时间显示
|
|
|
|
static String formatTime(int timestamp) {
|
2025-08-27 23:26:29 +08:00
|
|
|
// 确保是毫秒级
|
|
|
|
int ms = timestamp.toString().length == 10 ? timestamp * 1000 : timestamp;
|
|
|
|
|
|
|
|
final messageTime = DateTime.fromMillisecondsSinceEpoch(ms).toLocal();
|
2025-08-26 17:38:59 +08:00
|
|
|
final now = DateTime.now();
|
2025-08-27 23:26:29 +08:00
|
|
|
|
|
|
|
bool isSameDay = messageTime.year == now.year && messageTime.month == now.month && messageTime.day == now.day;
|
|
|
|
|
|
|
|
if (isSameDay) {
|
|
|
|
// 同一天:显示时:分
|
|
|
|
return '${messageTime.hour.toString().padLeft(2, '0')}:${messageTime.minute.toString().padLeft(2, '0')}';
|
|
|
|
}
|
|
|
|
|
2025-08-26 17:38:59 +08:00
|
|
|
if (messageTime.year == now.year) {
|
2025-08-27 23:26:29 +08:00
|
|
|
// 同一年:显示月-日 时:分
|
|
|
|
return '${messageTime.month.toString().padLeft(2, '0')}-'
|
|
|
|
'${messageTime.day.toString().padLeft(2, '0')} '
|
|
|
|
'${messageTime.hour.toString().padLeft(2, '0')}:'
|
|
|
|
'${messageTime.minute.toString().padLeft(2, '0')}';
|
2025-08-26 17:38:59 +08:00
|
|
|
}
|
2025-08-27 23:26:29 +08:00
|
|
|
|
|
|
|
// 不同年:显示完整日期
|
|
|
|
return '${messageTime.year}-'
|
|
|
|
'${messageTime.month.toString().padLeft(2, '0')}-'
|
|
|
|
'${messageTime.day.toString().padLeft(2, '0')} '
|
|
|
|
'${messageTime.hour.toString().padLeft(2, '0')}:'
|
|
|
|
'${messageTime.minute.toString().padLeft(2, '0')}';
|
2025-08-26 17:38:59 +08:00
|
|
|
}
|
|
|
|
|
2025-09-03 11:25:31 +08:00
|
|
|
static String _formatHourMinute(DateTime dt) {
|
2025-07-21 15:46:30 +08:00
|
|
|
final hour = dt.hour.toString().padLeft(2, '0');
|
|
|
|
final minute = dt.minute.toString().padLeft(2, '0');
|
|
|
|
return "$hour:$minute";
|
|
|
|
}
|
|
|
|
|
2025-09-03 11:25:31 +08:00
|
|
|
static String _weekdayLabel(int weekday) {
|
2025-07-21 15:46:30 +08:00
|
|
|
const weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
|
|
|
|
return weekdays[(weekday - 1) % 7];
|
|
|
|
}
|
2025-09-03 10:39:38 +08:00
|
|
|
|
2025-09-03 11:25:31 +08:00
|
|
|
static String getTipText(int realFollowType) {
|
|
|
|
switch (realFollowType) {
|
|
|
|
case 0:
|
|
|
|
return '关注';
|
|
|
|
case 1:
|
|
|
|
return '已关注';
|
|
|
|
case 2:
|
|
|
|
return '回关';
|
|
|
|
case 3:
|
|
|
|
return '已互关';
|
|
|
|
default:
|
|
|
|
return '未知状态';
|
|
|
|
}
|
2025-09-03 10:39:38 +08:00
|
|
|
}
|
2025-09-13 17:01:01 +08:00
|
|
|
|
|
|
|
// 处理IM的名字
|
|
|
|
static String handleText(String? nameCard, String? nickName, String defaultValue) {
|
|
|
|
if (nameCard != null && nameCard.trim().isNotEmpty) {
|
|
|
|
return nameCard;
|
|
|
|
}
|
|
|
|
if (nickName != null && nickName.trim().isNotEmpty) {
|
|
|
|
return nickName;
|
|
|
|
}
|
|
|
|
return defaultValue;
|
|
|
|
}
|
2025-07-21 15:46:30 +08:00
|
|
|
}
|