Support personal records and persistent smoking visibility. Add upload quota preflight, file cleanup, privacy entry, image caching and revision-based page refresh across the backend, admin and mini program.
198 lines
7.2 KiB
JavaScript
198 lines
7.2 KiB
JavaScript
const { tryLoginRenewal } = require('../../utils/subscribe');
|
|
const { itemsOf, startList, applyList, failList, finishList, withListPagination } = require('../../utils/list-pagination');
|
|
const { withDataCache } = require('../../utils/page-cache');
|
|
const { getLayout } = require('../../utils/layout');
|
|
// pages/timeline/timeline.js
|
|
const { api, getImageUrl } = require('../../utils/request');
|
|
|
|
// 重复周期映射
|
|
var repeatUnitMap = { 'day': '天', 'week': '周', 'month': '月', 'year': '年' };
|
|
|
|
// 计算距离今天最近的重复日期(返回 Date 对象,已归零)
|
|
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(withDataCache(withListPagination({
|
|
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
|
onResize: function() { this.setData(getLayout()); },
|
|
data: { loading: true, loadError: false,
|
|
list: []
|
|
},
|
|
|
|
onLoad: function() {
|
|
this.setData(getLayout());
|
|
this.loadData();
|
|
},
|
|
onShow: function() {
|
|
this.loadData();
|
|
},
|
|
|
|
onPullDownRefresh: async function() {
|
|
await this.loadData();
|
|
wx.stopPullDownRefresh();
|
|
},
|
|
|
|
onShareAppMessage: function() {
|
|
return { title: '让所有的爱有迹可循', path: '/pages/timeline/timeline', imageUrl: '/images/share.png' };
|
|
},
|
|
onShareTimeline: function() {
|
|
return { title: '让所有的爱有迹可循', imageUrl: '/images/share.png' };
|
|
},
|
|
|
|
loadData: async function(page) {
|
|
const ticket = startList(this, page);
|
|
if (!ticket) return;
|
|
try {
|
|
const list = await api.timelineList({page:ticket.page,page_size:20});
|
|
const myUid = wx.getStorageSync('userId');
|
|
var nameMap = {};
|
|
var avatarMap = {};
|
|
try {
|
|
const info = await api.coupleInfo();
|
|
var p1 = info.partner1 || {};
|
|
var p2 = info.partner2 || {};
|
|
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); }
|
|
} catch (e) {}
|
|
|
|
var today = new Date(); today.setHours(0,0,0,0);
|
|
var items = itemsOf(list).map(function(item, idx) {
|
|
var cid = String(item.created_by) || 0;
|
|
item.creator_name = nameMap[cid] || (cid == myUid ? '我' : 'TA');
|
|
item.creator_avatar = avatarMap[cid] || '';
|
|
item.creator_initial = (item.creator_name || '?')[0].toUpperCase();
|
|
item.side = ((ticket.page-1)*20+idx) % 2 === 0 ? 'left' : 'right';
|
|
item.bg_image_url = item.bg_image ? getImageUrl(item.bg_image) : '';
|
|
|
|
// 计算纪念日/倒数日(支持重复事件)
|
|
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 || '';
|
|
|
|
// 计算实际用来对比的基准日期
|
|
if (repeatInterval > 0 && repeatUnit) {
|
|
// 重复事件:以今天的日期为基准,计算最近一次重复的日期
|
|
var baseDate = calcNearestRepeatDate(ed, today, repeatInterval, repeatUnit);
|
|
var diff = Math.floor((today - baseDate) / 86400000);
|
|
if (diff >= 0) {
|
|
item.is_anniversary = true;
|
|
item.days_text = '已过去 ' + diff + ' 天';
|
|
item.date_tag = '纪念日';
|
|
item.repeat_label = repeatUnitMap[repeatUnit] + '重复';
|
|
} else {
|
|
item.is_anniversary = false;
|
|
item.days_text = '还有 ' + Math.abs(diff) + ' 天';
|
|
item.date_tag = '倒数日';
|
|
item.repeat_label = repeatUnitMap[repeatUnit] + '重复';
|
|
}
|
|
} else {
|
|
// 非重复事件:直接用事件日期计算
|
|
var diff = Math.floor((today - ed) / 86400000);
|
|
if (diff >= 0) {
|
|
item.is_anniversary = true;
|
|
item.days_text = '已过去 ' + diff + ' 天';
|
|
item.date_tag = '纪念日';
|
|
} else {
|
|
item.is_anniversary = false;
|
|
item.days_text = '还有 ' + Math.abs(diff) + ' 天';
|
|
item.date_tag = '倒数日';
|
|
}
|
|
}
|
|
} else {
|
|
item.is_anniversary = true;
|
|
item.days_text = '';
|
|
}
|
|
return item;
|
|
});
|
|
applyList(this, ticket, list, items, 'list');
|
|
} catch (e) {
|
|
failList(this,ticket);
|
|
console.error(e);
|
|
wx.showToast({ title: (e && (e.error || e.errMsg || e.message)) || '加载失败', icon: 'none' });
|
|
}
|
|
finally { finishList(this,ticket); }
|
|
},
|
|
|
|
|
|
deleteTimeline: async function(e) {
|
|
var id = e.currentTarget.dataset.id;
|
|
wx.showModal({
|
|
title: '确认删除',
|
|
content: '确定要删除这条记录吗?',
|
|
success: async function(res) {
|
|
if (res.confirm) {
|
|
try {
|
|
await api.timelineDelete({ id: id });
|
|
wx.showToast({ title: '已删除', icon: 'success' });
|
|
// need to re-get this context
|
|
var pages = getCurrentPages();
|
|
var page = pages[pages.length - 1];
|
|
page.loadData();
|
|
} catch (err) {
|
|
wx.showToast({ title: err.error || '删除失败', icon: 'none' });
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}, goToPublish: function() { wx.navigateTo({ url: '/pages/publish/publish?type=timeline' }); },
|
|
|
|
goToDetail: function(e) {
|
|
var id = e.currentTarget.dataset.id;
|
|
if (id) {
|
|
wx.navigateTo({ url: '/pages/timeline-detail/timeline-detail?id=' + id });
|
|
}
|
|
},
|
|
|
|
goHome: function() { wx.switchTab({ url: '/pages/index/index' }); },
|
|
goBack: function() { wx.navigateBack(); },
|
|
goProfile: function() { wx.switchTab({ url: '/pages/profile/profile' }); }
|
|
}, 'loadData'), {"loadData": ["timelineList", "coupleInfo"]}));
|