/// 对应 iOS BasicModule/Extension/Extension+Optional.swift。 extension NullableStringX on String? { /// null 或空字符串时返回 "-"(对应 iOS orPlaceholder)。 /// UI 层硬约束:所有 Optional 字符串展示前必须 .orPlaceholder。 String get orPlaceholder { if (this == null || this!.isEmpty) return '-'; return this!; } /// 简洁的非空判断(替代散落的 `s != null && s!.isNotEmpty` 三段式)。 bool get isNotNullOrEmpty => this != null && this!.isNotEmpty; /// 反向:null 或空。 bool get isNullOrEmpty => this == null || this!.isEmpty; } extension NullableIntX on int? { String get orPlaceholder => this?.toString() ?? '-'; } extension NullableDoubleX on double? { String get orPlaceholder => this?.toString() ?? '-'; } extension StringX on String { /// 首字母大写。 String get capitalize => isEmpty ? this : '${this[0].toUpperCase()}${substring(1)}'; /// 中国大陆手机号校验(对应 iOS Validator.isValidPhone)。 bool get isMobile => RegExp(r'^1[3-9]\d{9}$').hasMatch(this); /// 身份证号校验(对应 iOS Validator.isValidIDCard)。 bool get isIdCard => RegExp(r'^\d{17}[\dXx]$').hasMatch(this); /// Email 简易校验。 bool get isEmail => RegExp(r'^[\w.+-]+@([\w-]+\.)+[\w-]{2,}$').hasMatch(this); /// 脱敏手机号(保留首 3 + 末 4,中间 4 个 *):13800138000 → 138****8000 String get masked { if (length < 7) return this; return '${substring(0, 3)}****${substring(length - 4)}'; } /// 密码强度(0=无 / 1=弱 / 2=中 / 3=强)。 /// 规则:长度 ≥6 +1;含大小写字母 +1;含数字 +1;含特殊符号 +1(最高 3)。 int get passwordStrength { if (length < 6) return 0; var score = 1; if (RegExp('[A-Z]').hasMatch(this) && RegExp('[a-z]').hasMatch(this)) { score++; } if (RegExp(r'\d').hasMatch(this)) score++; if (RegExp(r'[!@#$%^&*(),.?":{}|<>_+\-=\[\]/\\;~`]').hasMatch(this)) { score++; } return score.clamp(0, 3); } }