// lib/avatar.js —— 用户头像解析(博客/论坛/评论等各处共用) // // 优先级(用户确认): // 1. RainWeb 自己上传的头像(users.avatar 以 /uploads/ 开头) // 2. QQ 头像(users.qq 字段 → https://q1.qlogo.cn/g?b=qq&nk=&s=640) // 3. QQ 邮箱前缀(users.qq_from_email —— SQL 内 CASE 提取的数字前缀,见 routes/forum.js、routes/blog.js) // 4. @qq.com 邮箱匹配(users.email 本体,仅本地直查场景可用) // 5. RainID 获取的头像(users.avatar 里的 http(s) URL) // 6. 均无 → 空串(前端显示默认头像) function resolveAvatar(user) { if (!user) return ''; if (user.avatar && String(user.avatar).startsWith('/uploads/')) return user.avatar; // QQ 头像:users.qq 字段 → qq_from_email(SQL 提取)→ @qq.com 邮箱前缀 let qq = String(user.qq || '').trim(); if (!qq && user.qq_from_email) qq = String(user.qq_from_email).trim(); if (!qq && user.email) { const m = String(user.email).toLowerCase().match(/^(\d{5,12})@qq\.com$/); if (m) qq = m[1]; } if (qq) return 'https://q1.qlogo.cn/g?b=qq&nk=' + qq + '&s=640'; if (user.avatar && /^https?:/i.test(user.avatar)) return user.avatar; return ''; } // 兼容缺行(匿名作者/已注销用户等 author_id 为空的行) function authorAvatar(authorRow) { return resolveAvatar(authorRow || {}); } module.exports = { resolveAvatar, authorAvatar };