export function formatDateTime(value: string | null | undefined) { if (!value) { return '暂无' } const date = new Date(value) if (Number.isNaN(date.getTime())) { return value } return new Intl.DateTimeFormat('zh-CN', { dateStyle: 'medium', timeStyle: 'short', }).format(date) } export function formatPostType(value: string | null | undefined) { switch (value) { case 'article': return '文章' case 'note': return '笔记' case 'page': return '页面' case 'snippet': return '片段' default: return value || '文章' } } export function formatCommentScope(value: string | null | undefined) { switch (value) { case 'paragraph': return '段落' case 'article': return '全文' default: return value || '全文' } } export function formatPostStatus(value: string | null | undefined) { switch (value) { case 'draft': return '草稿' case 'published': return '已发布' case 'scheduled': return '定时发布' case 'expired': return '已下线' case 'offline': return '离线' default: return value || '已发布' } } export function formatPostVisibility(value: string | null | undefined) { switch (value) { case 'unlisted': return '不公开' case 'private': return '私有' case 'public': return '公开' default: return value || '公开' } } function matchBrowserVersion(userAgent: string, marker: RegExp) { const matched = userAgent.match(marker) return matched?.[1] ?? null } export function formatBrowserName(userAgent: string | null | undefined) { if (!userAgent) { return '未知浏览器' } const ua = userAgent.toLowerCase() if (ua.includes('edg/')) { const version = matchBrowserVersion(userAgent, /edg\/([\d.]+)/i) return version ? `Edge ${version}` : 'Edge' } if (ua.includes('opr/') || ua.includes('opera')) { const version = matchBrowserVersion(userAgent, /(?:opr|opera)\/([\d.]+)/i) return version ? `Opera ${version}` : 'Opera' } if (ua.includes('firefox/')) { const version = matchBrowserVersion(userAgent, /firefox\/([\d.]+)/i) return version ? `Firefox ${version}` : 'Firefox' } if (ua.includes('chrome/') && !ua.includes('chromium/')) { const version = matchBrowserVersion(userAgent, /chrome\/([\d.]+)/i) return version ? `Chrome ${version}` : 'Chrome' } if (ua.includes('safari/') && !ua.includes('chrome/')) { const version = matchBrowserVersion(userAgent, /version\/([\d.]+)/i) return version ? `Safari ${version}` : 'Safari' } return '其他浏览器' } export function formatFriendLinkStatus(value: string | null | undefined) { switch (value) { case 'approved': return '已通过' case 'rejected': return '已拒绝' case 'pending': return '待审核' default: return value || '待审核' } } export function formatReviewType(value: string | null | undefined) { switch (value) { case 'book': return '图书' case 'movie': return '电影' case 'game': return '游戏' case 'anime': return '动画' case 'music': return '音乐' default: return value || '未分类' } } export function formatReviewStatus(value: string | null | undefined) { switch (value) { case 'published': return '已发布' case 'draft': return '草稿' case 'archived': return '已归档' case 'completed': return '已完成' case 'in-progress': return '进行中' default: return value || '未知状态' } } export function emptyToNull(value: string) { const trimmed = value.trim() return trimmed ? trimmed : null } export function linesToList(value: string) { return value .split('\n') .map((item) => item.trim()) .filter(Boolean) } export function csvToList(value: string) { return value .split(',') .map((item) => item.trim()) .filter(Boolean) } export function postTagsToList(value: unknown) { if (!Array.isArray(value)) { return [] } return value .map((item) => (typeof item === 'string' ? item.trim() : '')) .filter(Boolean) } export function reviewTagsToList(value: string | null | undefined) { if (!value) { return [] } try { const parsed = JSON.parse(value) as unknown if (Array.isArray(parsed)) { return parsed .map((item) => (typeof item === 'string' ? item.trim() : '')) .filter(Boolean) } } catch { return csvToList(value) } return [] }