| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- import '../config/app_config.dart';
- /// 与 Web `pickAvatarFromRecord` 对齐:头像 URL 可能在多字段或嵌套对象中。
- String? pickAvatarUrlFromRecord(Map<String, dynamic>? raw) {
- if (raw == null) {
- return null;
- }
- const directKeys = [
- 'avatar',
- 'headImg',
- 'head_img',
- 'headPortrait',
- 'head_portrait',
- 'portrait',
- 'photo',
- 'photoUrl',
- 'photo_url',
- 'faceUrl',
- 'face_url',
- 'icon',
- 'userAvatar',
- 'user_avatar',
- 'avatarUrl',
- 'avatarURL',
- 'logo',
- ];
- for (final k in directKeys) {
- final v = raw[k];
- if (v != null) {
- final s = v.toString().trim();
- if (s.isNotEmpty && s != 'null' && s != 'undefined') {
- return s;
- }
- }
- }
- const nestedKeys = [
- 'data',
- 'member',
- 'user',
- 'account',
- 'result',
- 'userInfo',
- 'user_info',
- ];
- for (final nk in nestedKeys) {
- final nested = raw[nk];
- if (nested is Map) {
- final found = pickAvatarUrlFromRecord(
- Map<String, dynamic>.from(nested),
- );
- if (found != null) {
- return found;
- }
- }
- }
- return null;
- }
- /// 将站内相对头像路径解析为可用绝对 URL(与 Web 外链 OSS 同源策略下的展示前提一致)。
- String? normalizeAvatarHttpUrl(String? raw) {
- if (raw == null) {
- return null;
- }
- final s = raw.trim();
- if (s.isEmpty || s == 'null' || s == 'undefined') {
- return null;
- }
- final lower = s.toLowerCase();
- if (lower.startsWith('http://') || lower.startsWith('https://')) {
- return s;
- }
- if (s.startsWith('//')) {
- return 'https:$s';
- }
- try {
- final baseUri = Uri.parse(AppConfig.effectiveApiBaseUrl);
- return baseUri.resolve(s).toString();
- } catch (_) {
- return s;
- }
- }
- /// pick + normalize,供界面与列表模型直接使用。
- String? resolvedAvatarUrlFromRecord(Map<String, dynamic>? raw) {
- return normalizeAvatarHttpUrl(pickAvatarUrlFromRecord(raw));
- }
|