/** * 格式化日期为 YYYY-MM-DD */ function formatDate(date) { const d = date ? new Date(date) : new Date() const y = d.getFullYear() const m = String(d.getMonth() + 1).padStart(2, '0') const day = String(d.getDate()).padStart(2, '0') return `${y}-${m}-${day}` } /** * 格式化日期为 YYYY-MM */ function formatMonth(date) { const d = date ? new Date(date) : new Date() return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}` } /** * 获取相对时间描述(几分钟前、几小时前、几天前) */ function timeAgo(dateStr) { if (!dateStr) return '' const now = Date.now() const t = new Date(dateStr).getTime() const diff = Math.floor((now - t) / 1000) if (diff < 60) return '刚刚' if (diff < 3600) return Math.floor(diff / 60) + '分钟前' if (diff < 86400) return Math.floor(diff / 3600) + '小时前' if (diff < 2592000) return Math.floor(diff / 86400) + '天前' return formatDate(dateStr) } /** * 打卡分类中文标签 */ const CATEGORY_LABEL = { study: '学习成长', health: '健康生活', habit: '习惯自律', hobby: '兴趣爱好', goal: '目标任务', } const CYCLE_LABEL = { daily: '每日', weekly: '每周', every_other_day: '隔日', custom: '自定义', } /** * 获取分类中文名 */ function getCategoryLabel(cat) { return CATEGORY_LABEL[cat] || cat } /** * 获取周期中文名 */ function getCycleLabel(cycle) { return CYCLE_LABEL[cycle] || cycle } /** * 隐私级别中文名 */ function getPrivacyLabel(level) { const map = { 1: '公开', 2: '仅好友可见', 3: '仅自己可见' } return map[level] || '未知' } /** * 积分显示(带 + 号) */ function formatPoints(p) { if (p === undefined || p === null) return '--' return p > 0 ? '+' + p : String(p) } module.exports = { formatDate, formatMonth, timeAgo, getCategoryLabel, getCycleLabel, getPrivacyLabel, formatPoints, CATEGORY_LABEL, CYCLE_LABEL, }