初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
import 'package:intl/intl.dart';
extension DateTimeNullableX on DateTime? {
String yyyyMMDDFormat({String gap = "-"}) {
if (this == null) return "";
return DateFormat("yyyy${gap}MM${gap}dd HH:mm:ss").format(this!);
}
String ymdSMFormat({String gap = "-"}) {
if (this == null) return "";
return DateFormat("yyyy${gap}MM${gap}dd HH:mm").format(this!);
}
}
+5
View File
@@ -0,0 +1,5 @@
/// 可空 double 扩展
extension DoubleNullableX on double? {
/// 防止字段为空报错
double em() => this ?? 0.0;
}
+8
View File
@@ -0,0 +1,8 @@
/// 通用基础类型扩展统一入口
export 'datetime_extension.dart';
export 'double_extension.dart';
export 'int_extension.dart';
export 'list_extension.dart';
export 'map_extension.dart';
export 'num_extension.dart';
export 'string_extension.dart';
+19
View File
@@ -0,0 +1,19 @@
import '../hj_utils/date_time_util.dart';
/// 可空 int 扩展
extension IntNullableX on int? {
/// 人性化数量:1234 / 1.2w / 1.3亿;0、负数、null 一律 '0'
String get countStr {
final v = this ?? 0;
if (v <= 0) return '0';
if (v < 10000) return '$v';
if (v < 100000000) return '${(v / 10000).toStringAsFixed(1)}w';
return '${(v / 100000000).toStringAsFixed(1)}亿';
}
/// 同 [countStr],但 0/null 返回 [def](按钮上显示「点赞」而不是「0」)
String countOr(String? def) => (this ?? 0) <= 0 ? (def ?? '0') : countStr;
/// 秒数 → mm:ss 或 HH:mm:ss
String get hmsStr => DateTimeUtil.formatHMS(this ?? 0);
}
+11
View File
@@ -0,0 +1,11 @@
/// 可空 List 扩展
extension ListNullableX on List? {
/// 长度,null 视为 0
int em() => this?.length ?? 0;
/// 是否为空(null 也视为空)
bool empty() => this == null || this!.isEmpty;
/// 是否非空
bool notEmpty() => this != null && this!.isNotEmpty;
}
+5
View File
@@ -0,0 +1,5 @@
/// 可空 Map 扩展
extension MapNullableX on Map? {
/// 长度,null 视为 0
int em() => this?.length ?? 0;
}
+17
View File
@@ -0,0 +1,17 @@
/// 可空 num 扩展
extension NumNullableX on num? {
/// 防止字段为空报错
num em() => this ?? 0;
/// 数字转金额保留两位小数
String toAmount() => em().toStringAsFixed(2);
}
/// 非空 num 扩展
extension NumX on num {
/// 小数点截取 [fractionDigits] 位(直接截断,不四舍五入)
String fixed(int fractionDigits) {
final fixString = toStringAsFixed(fractionDigits + 1);
return fixString.substring(0, fixString.length - 1);
}
}
+76
View File
@@ -0,0 +1,76 @@
import 'package:intl/intl.dart';
import 'datetime_extension.dart';
/// DateFormat 构造要解析 pattern,列表里高频调用,按 pattern 缓存
final _formatters = <String, DateFormat>{};
DateFormat _formatterOf(String pattern) => _formatters.putIfAbsent(pattern, () => DateFormat(pattern));
/// 可空字符串扩展
extension StringNullableX on String? {
DateTime? get _localDateTime {
final value = this?.trim();
if (value == null || value.isEmpty) return null;
return DateTime.tryParse(value)?.toLocal();
}
String _format(String pattern) {
final date = _localDateTime;
return date == null ? '' : _formatterOf(pattern).format(date);
}
// ============= utc 字符串 → 各种本地格式 =============
/// yyyy-MM-dd HH:mm:ss
String utcToYMDHMS() => _format('yyyy-MM-dd HH:mm:ss');
/// yyyy-MM-dd HH:mm
String utcToYMDHM({String gap = '-'}) => _format('yyyy${gap}MM${gap}dd HH:mm');
/// yyyy-MM-dd
String utcToYMD({String gap = '-'}) => _format('yyyy${gap}MM${gap}dd');
/// MM月dd日
String utcToCnMD() {
final date = _localDateTime;
return date == null ? '' : '${date.month}${date.day}';
}
/// 相对时间:"刚刚 / N分钟前 / N小时前 / N天前 / yyyy-MM-dd HH:mm"
String utcToAgo({String gap = '-'}) {
final date = _localDateTime;
//解析不出:本来就是空值兜底“近期”,脏数据给空串
if (date == null) return this?.trim().isNotEmpty == true ? '' : '近期';
final diff = DateTime.now().difference(date);
final s = diff.inSeconds;
if (s >= 0 && s < 60) return '刚刚';
final m = diff.inMinutes;
if (m > 0 && m < 60) return '${m + 1}分钟前';
final h = diff.inHours;
if (h > 0 && h < 24) return '${h + 1}小时前';
final d = diff.inDays;
if (d > 0 && d < 3) return '${d + 1}天前';
return date.ymdSMFormat(gap: gap);
}
}
/// 非空字符串扩展
extension StringX on String {
/// 截断到最大长度
String limit(int max) {
if (max <= 0) return '';
return length <= max ? this : substring(0, max);
}
/// 是否含 16 个以上的 0,用于识别全零设备号(如全零 UUID)
bool hasManyZeros() {
const zero = 0x30; //'0'
var count = 0;
for (var i = 0; i < length; i++) {
if (codeUnitAt(i) == zero && ++count >= 16) return true;
}
return false;
}
}