/// 取字符串的第一个字符。 /// /// 用 `runes` 而不是 `substring(0, 1)`:中文与 emoji 不会被截成半个字符。 /// 侧栏折叠后的短标签、卡片左上角的字母图标都依赖这条规则, /// 放在这里保证三处(logo、导航、卡片)表现一致。 String firstChar(String text, {String fallback = '·'}) { if (text.isEmpty) { return fallback; } return String.fromCharCode(text.runes.first); } /// 字符数(不是字节数)。 /// /// 和后端 `util::char_count` 的口径一致:先去掉首尾空白,再数字符。 /// 中文一个字算一个,所以「最多 60 个字符」用 `runes.length` 而不是 `length`。 int charCount(String text) => text.trim().runes.length;