const { withRecordAccess } = require('../../utils/record-access'); const { tryLoginRenewal } = require('../../utils/subscribe'); const { withDataCache } = require('../../utils/page-cache'); const { getLayout } = require('../../utils/layout'); // pages/timeline-detail/timeline-detail.js const { api, getImageUrl } = require('../../utils/request'); const { createSwipeBack } = require('../../utils/util'); // 重复周期映射 var repeatUnitMap = { 'day': '天', 'week': '周', 'month': '月', 'year': '年' }; var weekdayNames = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; // 计算距离今天最近的重复日期 function calcNearestRepeatDate(eventDate, today, interval, unit) { var base = new Date(eventDate); base.setHours(0,0,0,0); if (unit === 'day') { var diff = Math.floor((today - base) / 86400000); var cycles = Math.floor(diff / interval); var nearest = new Date(base.getTime() + cycles * interval * 86400000); nearest.setHours(0,0,0,0); if (nearest > today) { nearest = new Date(nearest.getTime() - interval * 86400000); nearest.setHours(0,0,0,0); } return nearest; } else if (unit === 'week') { var diff = Math.floor((today - base) / 86400000); var cycles = Math.floor(diff / (7 * interval)); var nearest = new Date(base.getTime() + cycles * 7 * interval * 86400000); nearest.setHours(0,0,0,0); if (nearest > today) { nearest = new Date(nearest.getTime() - 7 * interval * 86400000); nearest.setHours(0,0,0,0); } return nearest; } else if (unit === 'month') { var nearest = new Date(base); nearest.setHours(0,0,0,0); while (true) { var next = new Date(nearest); next.setMonth(next.getMonth() + interval); next.setHours(0,0,0,0); if (next > today) break; nearest = next; } return nearest; } else if (unit === 'year') { var nearest = new Date(base); nearest.setHours(0,0,0,0); while (true) { var next = new Date(nearest); next.setFullYear(next.getFullYear() + interval); next.setHours(0,0,0,0); if (next > today) break; nearest = next; } return nearest; } return new Date(eventDate); } Page(withRecordAccess(withDataCache({ onLoginSubscribeTap: function() { return tryLoginRenewal(); }, onResize: function() { this.setData(getLayout()); }, data: { loading: true, loadError: false, item: null, detailId: 0, bgImageUrl: '', daysNumber: '', daysSign: '', weekdayText: '', isAnniversary: true }, onLoad: function(options) { this.setData(getLayout()); var id = options.id; if (id) { this.setData({ detailId: String(id) }); this.loadDetail(String(id)); } var self = this; var swipe = createSwipeBack(function() { wx.navigateBack(); }); this.onTouchStart = swipe.onTouchStart; this.onTouchEnd = swipe.onTouchEnd; }, retryDetail: function() { this.loadDetail(this.data.detailId); }, onShow: function() { this._syncNavigationColor(); if (this.data.detailId) { this.loadDetail(this.data.detailId); } }, onHide: function() { if (wx.setNavigationBarColor) wx.setNavigationBarColor({frontColor:'#000000',backgroundColor:'#FDE4EC'}); }, _syncNavigationColor: function() { if (wx.setNavigationBarColor) wx.setNavigationBarColor({frontColor:this.data.bgImageUrl?'#ffffff':'#000000',backgroundColor:this.data.bgImageUrl?'#000000':'#FDE4EC'}); }, goBack: function() { wx.navigateBack({fail:function(){wx.switchTab({url:'/pages/discover/discover'});}}); }, loadDetail: async function(id) { if (this._pageLoading) return; this._pageLoading = true; this.setData({loading: !this._hasCachedData, loadError:false}); try { var item = await api.timelineDetail(id); var myUid = wx.getStorageSync('userId'); var cid = String(item.created_by) || 0; // 获取情侣信息 try { var info = await api.coupleInfo(); var p1 = info.partner1 || {}; var p2 = info.partner2 || {}; var nameMap = {}; var avatarMap = {}; if (p1.id) { nameMap[p1.id] = p1.nickname || p1.username || 'TA'; avatarMap[p1.id] = getImageUrl(p1.avatar); } if (p2.id) { nameMap[p2.id] = p2.nickname || p2.username || 'TA'; avatarMap[p2.id] = getImageUrl(p2.avatar); } item.creator_name = nameMap[cid] || (cid == myUid ? '我' : 'TA'); item.creator_avatar = avatarMap[cid] || ''; } catch(e) { item.creator_name = cid == myUid ? '我' : 'TA'; item.creator_avatar = ''; } item.creator_initial = (item.creator_name || '?')[0].toUpperCase(); // 计算天数 var today = new Date(); today.setHours(0,0,0,0); var daysNumber = ''; var daysSign = ''; var isAnniversary = true; if (item.event_date) { var ed = new Date(item.event_date.replace(/-/g, '/')); ed.setHours(0,0,0,0); var repeatInterval = parseInt(item.repeat_interval) || 0; var repeatUnit = item.repeat_unit || ''; var diff; if (repeatInterval > 0 && repeatUnit) { var baseDate = calcNearestRepeatDate(ed, today, repeatInterval, repeatUnit); diff = Math.floor((today - baseDate) / 86400000); isAnniversary = diff >= 0; daysSign = isAnniversary ? '+' : '-'; daysNumber = Math.abs(diff); item.repeat_label = repeatUnitMap[repeatUnit] + '重复'; } else { diff = Math.floor((today - ed) / 86400000); isAnniversary = diff >= 0; daysSign = isAnniversary ? '+' : '-'; daysNumber = Math.abs(diff); } } // 星期 var eventDateObj = new Date(item.event_date.replace(/-/g, '/')); var weekdayText = weekdayNames[eventDateObj.getDay()] || ''; item.is_anniversary = isAnniversary; this.setData({ item: item, daysNumber: daysNumber, daysSign: daysSign, weekdayText: weekdayText, isAnniversary: isAnniversary }); // 从API数据加载背景图 this.loadBgImage(); } catch(e) { this.setData({loadError:true}); console.error(e); wx.showToast({ title: (e && (e.error || e.errMsg || e.message)) || '加载失败', icon: 'none' }); } finally { this._pageLoading = false; this.setData({loading:false}); } }, // ===== 背景图片 ===== loadBgImage: function() { var item = this.data.item; if (item && item.bg_image) { var fullUrl = getImageUrl(item.bg_image); this.setData({ bgImageUrl: fullUrl }); } else { this.setData({ bgImageUrl: '' }); } this._syncNavigationColor(); }, // ===== 编辑 ===== goEdit: function() { var item = this.data.item; if (item && item.id) { wx.navigateTo({ url: '/pages/publish/publish?type=timeline&edit=' + item.id }); } }, // ===== 导航 ===== goBack: function() { wx.navigateBack(); }, goHome: function() { wx.switchTab({ url: '/pages/index/index' }); }, goProfile: function() { wx.switchTab({ url: '/pages/profile/profile' }); } }, {"loadDetail": ["timelineDetail", "coupleInfo"]})));