Files
past-go/weapp/pages/index/index.js
T

350 lines
14 KiB
JavaScript

let lastLocationReport = 0;
let locationReportUser = null;
const { withDataCache } = require('../../utils/page-cache');
const { getLayout } = require('../../utils/layout');
// pages/index/index.js
const { api, getImageUrl } = require('../../utils/request');
const { diaryEntry } = require('../../utils/journal');
const { saveScrollPosition, resetScrollOnTabShow } = require('../../utils/scroll-pos');
Page(withDataCache({
onResize: function() { this.setData(getLayout()); },
data: {
userId: null,
coupleId: null,
partnerName: '和TA',
loveStartDate: '',
daysCount: '?',
daysLabel: '已注册',
datePrefix: '注册于',
partner1AvatarUrl: '',
partner2AvatarUrl: '',
partner1Initial: '',
partner2Initial: '',
partner1Birthday: '',
partner2Birthday: '',
partner1Name: '?',
partner2Name: '?',
partner1Location: '',
partner2Location: '',
coupleDistance: '',
stats: {
timeline: 0, album: 0, diary: 0,
songs: 0, checkin: 0, pet: 0
},
bgImage: '',
scrollTop: 0,
refreshing: false,
relationshipKnown: false, homeError: false, statsLoading: true, statsError: false, recentDiary: [], recentAlbums: [], upcomingMemory: null
},
onLoad: function() {
this.setData(getLayout());
this.setData({
userId: wx.getStorageSync('userId'),
coupleId: wx.getStorageSync('coupleId'),
scrollTop: 0
});
this.loadBg();
this.loadData();
},
onShow: function() {
resetScrollOnTabShow(this, 'index');
const tabBar = this.getTabBar && this.getTabBar();
if (tabBar) tabBar.syncActive();
var prevCoupleId = this.data.coupleId;
var curCoupleId = wx.getStorageSync('coupleId');
this.setData({
userId: wx.getStorageSync('userId'),
coupleId: curCoupleId
});
// 检查是否已被解绑(之前有 coupleId 但被清除了)
if (prevCoupleId && !curCoupleId) {
wx.reLaunch({ url: '/pages/index/index' });
return;
}
this.loadBg();
this.loadData();
this.fetchIpLocation();
},
// 保存滚动位置
onScroll: function(e) {
this._scrollTop = e.detail.scrollTop;
saveScrollPosition('index', e.detail.scrollTop);
},
_loadingData: false,
_daysSince: function(dateStr) {
if (!dateStr) return '?';
var parts = dateStr.substring(0, 10).split('-').map(Number);
if (parts.length !== 3 || parts.some(isNaN) || parts[0] < 1970 ||
parts[1] < 1 || parts[1] > 12 || parts[2] < 1 || parts[2] > 31) return '?';
var start = new Date(parts[0], parts[1] - 1, parts[2]);
if (start.getFullYear() !== parts[0] || start.getMonth() !== parts[1] - 1 ||
start.getDate() !== parts[2]) return '?';
var now = new Date();
var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
return Math.max(0, Math.round((today - start) / 86400000));
},
loadData: async function() {
var self = this;
// 防止并发重复加载
if (this._loadingData) return;
this._loadingData = true;
this.setData({ homeError: false });
try {
const info = await api.coupleInfo();
this.setData({userId: wx.getStorageSync('userId')});
this.setData({ relationshipKnown: true });
// 未绑定情侣时显示用户注册时间和默认信息
if (info.not_bound) {
wx.removeStorageSync('coupleId');
var p1 = info.partner1 || {};
let daysCount = '?';
let loveStartDate = '';
if (info.love_start_date) {
daysCount = this._daysSince(info.love_start_date);
var parts = info.love_start_date.split('-');
loveStartDate = parseInt(parts[0]) + '年' + parseInt(parts[1]) + '月' + parseInt(parts[2]) + '日';
}
this.setData({
coupleId: null,
partner1AvatarUrl: getImageUrl(p1.avatar),
partner1Name: p1.nickname || '未命名',
partner1Initial: (p1.nickname || '未命名')[0],
partner1Birthday: '',
partner1Location: p1.location || '',
partner2AvatarUrl: '',
partner2Name: '未绑定',
partner2Initial: '?',
partner2Birthday: '',
partner2Location: '',
daysCount: daysCount,
daysLabel: '已注册',
datePrefix: '注册于',
loveStartDate: loveStartDate,
coupleDistance: '',
stats: { timeline: 0, album: 0, diary: 0, songs: 0, checkin: 0, pet: 0 }
});
await this.loadStats();
return;
}
// 同步情侣ID:红包/邀请创建后分享人刷新即可识别
if (info.id) {
var prevCid = wx.getStorageSync('coupleId');
if (prevCid != info.id) {
wx.setStorageSync('coupleId', info.id);
}
}
const myUid = this.data.userId;
var p1 = info.partner1 || {};
var p2 = info.partner2 || {};
if (p2.id == myUid) {
var tmp = p1; p1 = p2; p2 = tmp;
}
let daysCount = '?';
let loveStartDate = '';
var togetherStart = info.love_start_date || (info.created_at || '').substring(0, 10);
if (togetherStart) {
daysCount = this._daysSince(togetherStart);
var parts = togetherStart.split('-');
loveStartDate = parseInt(parts[0]) + '年' + parseInt(parts[1]) + '月' + parseInt(parts[2]) + '日';
}
function getBirthdayText(birthday) {
if (!birthday) return '';
var t = new Date(); t.setHours(0,0,0,0);
var p = birthday.split('-');
if (p.length !== 3) return '';
var nb = new Date(t.getFullYear(), parseInt(p[1])-1, parseInt(p[2]));
if (nb < t) nb.setFullYear(nb.getFullYear()+1);
var c = Math.ceil((nb - t) / 86400000);
if (c === 0) return '今天!';
if (c === 1) return '1天';
if (!Number.isFinite(c)) return '';
return c + '天';
}
// 双方相距距离(后端基于双方经纬度用 Haversine 公式计算,单位:公里)
var coupleDistance = '';
if (info.distance !== null && info.distance !== undefined && info.distance !== '') {
var d = parseFloat(info.distance);
if (!isNaN(d)) {
coupleDistance = d < 1
? '相距 ' + Math.round(d * 1000) + ' 米'
: '相距 ' + d.toFixed(1) + ' 公里';
}
}
var dn = {
coupleId: info.id,
daysCount: daysCount,
daysLabel: '我们在一起',
datePrefix: '始于',
loveStartDate: loveStartDate,
partner1AvatarUrl: getImageUrl(p1.avatar),
partner2AvatarUrl: getImageUrl(p2.avatar),
partner1Name: p1.nickname || p1.username || '?',
partner2Name: p2.nickname || p2.username || '?',
partner1Initial: (p1.nickname || p1.username || '?')[0],
partner2Initial: (p2.nickname || p2.username || '?')[0],
partner1Birthday: getBirthdayText(p1.birthday),
partner2Birthday: getBirthdayText(p2.birthday),
partner1Location: (p1.location && !/^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/.test(p1.location)) ? p1.location : '',
partner2Location: (p2.location && !/^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/.test(p2.location)) ? p2.location : '',
coupleDistance: coupleDistance
};
this.setData(dn);
await this.loadStats();
} catch (e) {
this.setData({ homeError: true, relationshipKnown: !!this._hasCachedData, statsLoading: false, statsError: true });
console.error(e);
} finally {
this._loadingData = false;
}
},
loadStats: async function() {
this.setData({ statsLoading: !this._hasCachedData, statsError: false });
try {
const [timeline, album, diary, songs, checkin, pet] = await Promise.all([
api.timelineList(), api.albumList(), api.diaryList(),
api.songsList(), api.checkinList(),
this.data.coupleId ? api.petInfo() : Promise.resolve({ has_pet: false })
]);
var photoCount = 0;
if (Array.isArray(album)) {
for (var i = 0; i < album.length; i++) {
photoCount += parseInt(album[i].photo_count || 0);
}
}
var petLevel = 0;
if (pet && pet.has_pet && pet.pet) {
petLevel = parseInt(pet.pet.level || 0);
}
var recentDiary = ((diary && diary.items) || []).slice(0, 1).map(diaryEntry);
var today = new Date(); today.setHours(0,0,0,0);
var future = (Array.isArray(timeline) ? timeline : []).filter(function(item) { return item.event_date && new Date(item.event_date.replace(/-/g, '/')) >= today; }).sort(function(a,b) { return a.event_date.localeCompare(b.event_date); });
var next = future[0];
this.setData({
recentDiary: recentDiary,
recentAlbums: (Array.isArray(album) ? album : []).filter(function(item) { return !!item.cover; }).slice(0,3).map(function(item) { return { id:item.id, title:item.title || '我们的相册', cover:getImageUrl(item.cover) }; }),
upcomingMemory: next ? { title: next.title || '下一个记忆日', date: next.event_date, dateMonth: next.event_date.slice(5,7), dateDay: next.event_date.slice(8,10), days: Math.ceil((new Date(next.event_date.replace(/-/g, '/')) - today) / 86400000) } : null,
stats: {
timeline: Array.isArray(timeline) ? timeline.length : 0,
album: photoCount,
diary: (diary && diary.total) ? diary.total : 0,
songs: Array.isArray(songs) ? songs.length : 0,
checkin: (checkin && checkin.checkin_log_total !== undefined) ? checkin.checkin_log_total : ((checkin && checkin.items) ? checkin.items.length : (Array.isArray(checkin) ? checkin.length : 0)),
pet: petLevel
}
});
} catch (e) { console.error(e); this.setData({ statsError: true }); } finally { this.setData({ statsLoading: false }); }
},
// 获取本机经纬度并上报后端解析地址(后端按距离判断是否重新解析,超过5km才更新),并刷新首页双方地址显示
fetchIpLocation: function() {
const locationUser = wx.getStorageSync('userId');
if (locationReportUser === locationUser && Date.now() - lastLocationReport < 300000) return;
locationReportUser = locationUser;
lastLocationReport = Date.now();
var self = this;
var report = function(lat, lng) {
var data = {};
if (lat && lng) { data.lat = lat; data.lng = lng; }
api.updateIpLocation(data).then(function(resp) {
if (resp && resp.location) {
self.loadData();
}
}).catch(function() { lastLocationReport = 0; });
};
// 优先用模糊定位获取经纬度(getFuzzyLocation 与 getLocation 互斥,统一用模糊定位)
if (wx.getFuzzyLocation) {
wx.getFuzzyLocation({
type: 'gcj02',
success: function(res) {
report(res.latitude, res.longitude);
},
fail: function() {
report(0, 0);
}
});
} else {
report(0, 0);
}
},
// 背景图以接口返回为准
loadBg: function() {
var self = this;
return api.getBgConfig().then(function(cfg) {
self.setData({ bgImage: cfg && cfg.image ? getImageUrl(cfg.image) : '' });
}).catch(function(e){ console.warn('loadBg error:', e && (e.error || e._statusCode || e)); });
},
// 跳转前保存当前滚动位置
_savePosBeforeLeave: function() {
saveScrollPosition('index', this._scrollTop == null ? this.data.scrollTop : this._scrollTop);
},
// 页面跳转
goToDiary: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/diary/diary' }); },
goToProfile: function() { this._savePosBeforeLeave(); wx.switchTab({ url: '/pages/profile/profile' }); },
goToTimeline: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/timeline/timeline' }); },
goToAlbum: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/albums/albums' }); },
goToSongs: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/lovewords/lovewords' }); },
goToCheckin: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/punch/punch' }); },
goToPet: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/pet/pet' }); },
goToPeriod: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/period/period' }); },
bindPartner: function() { getApp().globalData.openProfileBind = true; wx.switchTab({ url: '/pages/profile/profile' }); },
openJournalEntry: function(e) { wx.navigateTo({ url: '/pages/diary_detail/diary_detail?id=' + e.currentTarget.dataset.id }); },
writeDiary: function() { wx.navigateTo({ url: '/pages/publish/publish?type=diary' }); },
openAlbumPreview: function(e) { wx.navigateTo({ url: '/pages/album/album?album_id=' + e.currentTarget.dataset.id }); },
openRecentDiary: function(e) { wx.navigateTo({ url: '/pages/diary_detail/diary_detail?id=' + e.currentTarget.dataset.id }); },
showMore: function() {
wx.switchTab({ url: '/pages/discover/discover' });
},
onPullDownRefresh: async function() {
await this.loadData();
this.loadBg();
wx.stopPullDownRefresh();
},
onRefresh: async function() {
this.setData({ refreshing: true });
try {
await this.loadData();
this.loadBg();
} catch (e) {
console.error('下拉刷新失败', e);
} finally {
this.setData({ refreshing: false });
}
},
// 分享到好友
onShareAppMessage: function() {
return {
title: '让所有的爱有迹可循',
path: '/pages/index/index',
imageUrl: '/images/share.png'
};
},
// 分享到朋友圈
onShareTimeline: function() {
return {
title: '让所有的爱有迹可循',
query: '',
imageUrl: '/images/share.png'
};
}
}, {"loadData": ["coupleInfo", "timelineList", "albumList", "diaryList", "songsList", "checkinList", "petInfo", "getBgConfig"]}));