/// 金额展示与计算工具 /// /// 统一入口的意义:后端返回 double,可能出现 null / NaN / Infinity, /// 直接 toStringAsFixed 会抛异常或显示 "NaN",所以全部走这里兜底。 library; /// 金额展示:固定两位小数,非法值回退 '0.00' String formatAmount(double? value) { if (value == null || !value.isFinite) return '0.00'; return value.toStringAsFixed(2); } /// 带符号金额:支出 '-¥12.00',收入 '+¥12.00' /// /// 是否支出必须由调用方显式传入(用 bill.type 判断), /// 不要用金额正负判断——后端返回的 amount 恒为正数。 String formatSignedAmount(double? amount, {required bool isExpense}) { final text = formatAmount(amount?.abs()); return isExpense ? '-¥$text' : '+¥$text'; } /// 占比(0~100)。分母 <= 0 或非法时返回 0,避免除零与 NaN double percentOf(double part, double total) { if (!part.isFinite || !total.isFinite || total <= 0) return 0; final pct = part / total * 100; return pct.clamp(0, 100); }