更新最新代码
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/checkin-detail/checkin-detail.js
|
||||
const { api, getImageUrl, API_BASE, uploadFileCompat } = require('../../utils/request');
|
||||
const { createSwipeBack } = require('../../utils/util');
|
||||
const { requestSubscribeAfterAction } = require('../../utils/subscribe');
|
||||
const COOLDOWN = 5000;
|
||||
Page(withDataCache({
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false, item: null, logs: [], logsPage: 1, logsTotal: 0, logsHasMore: false, logsLoading: false, logsError: false, freqLabel: '', typeLabel: '', myStreak: 0, partnerStreak: 0, showCheckModal: false, checkPhoto: '', checkNote: '', lastActionTime: 0, detailId: 0, myAvatar: '', partnerAvatar: '', myName: '我', partnerName: 'TA' },
|
||||
|
||||
onLoad: function(options) {
|
||||
this.setData(getLayout());
|
||||
var id = options.id;
|
||||
if (id) {
|
||||
this.setData({ detailId: parseInt(id) });
|
||||
this.loadCoupleInfo();
|
||||
this.loadDetail(parseInt(id));
|
||||
}
|
||||
var self = this;
|
||||
var swipe = createSwipeBack(function() { wx.navigateBack(); });
|
||||
this.onTouchStart = swipe.onTouchStart;
|
||||
this.onTouchEnd = swipe.onTouchEnd;
|
||||
},
|
||||
|
||||
noop: function() {},
|
||||
retryDetail: function() { this.loadDetail(this.data.detailId); },
|
||||
onShow: function() {
|
||||
if (this.data.detailId) {
|
||||
this.loadCoupleInfo();
|
||||
this.loadDetail(this.data.detailId);
|
||||
}
|
||||
},
|
||||
|
||||
// 从接口加载情侣头像和名称
|
||||
loadCoupleInfo: function() {
|
||||
var self = this;
|
||||
return api.coupleInfo().then(function(info) {
|
||||
self._applyCoupleInfo(info);
|
||||
}).catch(function(e) { console.error(e); });
|
||||
},
|
||||
|
||||
_applyCoupleInfo: function(info) {
|
||||
if (!info) return;
|
||||
var myUid = wx.getStorageSync('userId');
|
||||
var p1 = info.partner1 || {}, p2 = info.partner2 || {};
|
||||
var me = (p1.id == myUid) ? p1 : p2;
|
||||
var partner = (p1.id == myUid) ? p2 : p1;
|
||||
this.setData({
|
||||
myAvatar: getImageUrl(me.avatar || ''),
|
||||
partnerAvatar: getImageUrl(partner.avatar || ''),
|
||||
myName: me.nickname || '我',
|
||||
partnerName: partner.nickname || 'TA'
|
||||
});
|
||||
},
|
||||
|
||||
loadDetail: async function(id) {
|
||||
if (this._pageLoading) return;
|
||||
this._pageLoading = true;
|
||||
this._logsGeneration = (this._logsGeneration || 0) + 1;
|
||||
this.setData({ logsLoading: false, logsError: false });
|
||||
this.setData({loading: !this._hasCachedData, loadError:false});
|
||||
try {
|
||||
var data = await api.checkinDetail(id, { page: 1, page_size: 20 });
|
||||
var item = data.item || {};
|
||||
var myUid = wx.getStorageSync('userId');
|
||||
var freqLabels = { daily: '每天', weekly: '每周', monthly: '每月', once: '一次', unlimited: '不限' };
|
||||
var typeLabels = { both: '双方', first: '第一视角', her: '她打卡' };
|
||||
var freqLabel = freqLabels[item.frequency] || '每天';
|
||||
var typeLabel = typeLabels[item.type] || '双方';
|
||||
// 创建人头像URL
|
||||
item.creator_avatar_url = item.creator_avatar ? getImageUrl(item.creator_avatar) : '';
|
||||
// 使用本次页面加载的情侣信息
|
||||
var myAvatar = this.data.myAvatar;
|
||||
var partnerAvatar = this.data.partnerAvatar;
|
||||
var myName = this.data.myName;
|
||||
var partnerName = this.data.partnerName;
|
||||
var logs = this.formatLogs(data.logs || []);
|
||||
// 根据打卡权限类型映射统计数据
|
||||
var isCreator = (myUid == item.created_by);
|
||||
var showMyStats = (item.type == 'both') || (item.type == 'first');
|
||||
var showPartnerStats = (item.type == 'both') || (item.type == 'her');
|
||||
var checkinerIsMe = (item.type == 'first' && isCreator) || (item.type == 'her' && !isCreator);
|
||||
var displayAvatar = (item.type == 'both' || checkinerIsMe) ? myAvatar : partnerAvatar;
|
||||
var displayName = (item.type == 'both' || checkinerIsMe) ? myName : partnerName;
|
||||
var checkinToday = checkinerIsMe ? (data.my_today || 0) : (data.partner_today || 0);
|
||||
var checkinWeek = checkinerIsMe ? (data.my_week || 0) : (data.partner_week || 0);
|
||||
var checkinMonth = checkinerIsMe ? (data.my_month || 0) : (data.partner_month || 0);
|
||||
var checkinYear = checkinerIsMe ? (data.my_year || 0) : (data.partner_year || 0);
|
||||
var checkinStreak = checkinerIsMe ? (item.my_streak || 0) : (item.partner_streak || 0);
|
||||
var pageData = {
|
||||
item: item,
|
||||
logs: logs,
|
||||
logsPage: 1, logsTotal: Number(data.total) || logs.length,
|
||||
logsHasMore: data.has_more === true, logsError: false,
|
||||
freqLabel: freqLabel,
|
||||
typeLabel: typeLabel,
|
||||
myStreak: (item.type == 'both') ? (item.my_streak || 0) : checkinStreak,
|
||||
partnerStreak: (item.type == 'both') ? (item.partner_streak || 0) : 0,
|
||||
showMyStats: showMyStats,
|
||||
showPartnerStats: showPartnerStats,
|
||||
myToday: (item.type == 'both') ? (data.my_today || 0) : checkinToday,
|
||||
myWeek: (item.type == 'both') ? (data.my_week || 0) : checkinWeek,
|
||||
myMonth: (item.type == 'both') ? (data.my_month || 0) : checkinMonth,
|
||||
myYear: (item.type == 'both') ? (data.my_year || 0) : checkinYear,
|
||||
partnerToday: (item.type == 'both') ? (data.partner_today || 0) : 0,
|
||||
partnerWeek: (item.type == 'both') ? (data.partner_week || 0) : 0,
|
||||
partnerMonth: (item.type == 'both') ? (data.partner_month || 0) : 0,
|
||||
partnerYear: (item.type == 'both') ? (data.partner_year || 0) : 0,
|
||||
myAvatar: displayAvatar,
|
||||
myName: displayName,
|
||||
partnerAvatar: partnerAvatar,
|
||||
partnerName: partnerName
|
||||
};
|
||||
this.setData(pageData);
|
||||
} catch(e) {
|
||||
this.setData({loadError:true}); console.error(e); }
|
||||
finally { this._pageLoading = false; this.setData({loading:false}); }
|
||||
},
|
||||
|
||||
formatLogs: function(logs) {
|
||||
return logs.map(function(log) {
|
||||
return Object.assign({}, log, {
|
||||
time: log.created_at ? log.created_at.substring(0, 16).replace('T', ' ') : '',
|
||||
photoUrl: log.photo ? getImageUrl(log.photo) : ''
|
||||
});
|
||||
});
|
||||
},
|
||||
loadMoreLogs: async function() {
|
||||
if (this._pageLoading || this.data.loading || this.data.loadError || this.data.logsLoading || !this.data.logsHasMore) return;
|
||||
var generation = this._logsGeneration;
|
||||
var page = this.data.logsPage + 1;
|
||||
this.setData({ logsLoading: true, logsError: false });
|
||||
try {
|
||||
var data = await api.checkinDetail(this.data.detailId, { page: page, page_size: 20 });
|
||||
if (generation !== this._logsGeneration) return;
|
||||
var seen = new Set(this.data.logs.map(function(log) { return String(log.id); }));
|
||||
var added = this.formatLogs(data.logs || []).filter(function(log) {
|
||||
var id = String(log.id);
|
||||
if (seen.has(id)) return false;
|
||||
seen.add(id); return true;
|
||||
});
|
||||
this.setData({ logs: this.data.logs.concat(added), logsPage: page,
|
||||
logsTotal: Number(data.total) || 0, logsHasMore: data.has_more === true });
|
||||
} catch (e) {
|
||||
if (generation === this._logsGeneration) this.setData({ logsError: true });
|
||||
} finally {
|
||||
if (generation === this._logsGeneration) this.setData({ logsLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
// ===== 打卡操作 =====
|
||||
showCheckinModal: function() {
|
||||
var now = Date.now();
|
||||
if (now - this.data.lastActionTime < COOLDOWN) {
|
||||
wx.showToast({ title: '操作太快,请稍后', icon: 'none' }); return;
|
||||
}
|
||||
this.data.lastActionTime = now;
|
||||
this.setData({ showCheckModal: true, checkPhoto: '', checkNote: '' });
|
||||
},
|
||||
|
||||
onCheckNoteInput: function(e) { this.setData({ checkNote: e.detail.value }); },
|
||||
|
||||
chooseCheckPhoto: function() {
|
||||
var self = this;
|
||||
wx.chooseImage({
|
||||
count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'],
|
||||
success: function(res) { self.setData({ checkPhoto: res.tempFilePaths[0] }); }
|
||||
});
|
||||
},
|
||||
|
||||
submitCheck: async function() {
|
||||
var item = this.data.item;
|
||||
if (!item || this._submittingCheck) return;
|
||||
this._submittingCheck = true;
|
||||
|
||||
try {
|
||||
// 为本人接收TA的提醒补充授权。
|
||||
await requestSubscribeAfterAction('checkin');
|
||||
var photoPath = '';
|
||||
if (this.data.checkPhoto) {
|
||||
wx.showLoading({ title: '上传中...' });
|
||||
try {
|
||||
var upResult = await uploadFileCompat({
|
||||
url: API_BASE + '/upload',
|
||||
filePath: this.data.checkPhoto,
|
||||
name: 'file',
|
||||
formData: { sub_dir: 'checkins' }
|
||||
});
|
||||
photoPath = upResult.path || '';
|
||||
} catch(e) {
|
||||
// 内容安全违规:抛出错误中断打卡并提示用户
|
||||
if (e && e.error) {
|
||||
throw e;
|
||||
}
|
||||
photoPath = '';
|
||||
}
|
||||
wx.hideLoading();
|
||||
}
|
||||
var res = await api.checkinDo({ id: item.id, photo: photoPath, note: this.data.checkNote });
|
||||
this.setData({ showCheckModal: false });
|
||||
var toast = '打卡成功 ✅';
|
||||
if (item.type === 'both' && item.partner_done_today !== true && !res.both_done) {
|
||||
toast = '已打卡,等待对方';
|
||||
}
|
||||
wx.showToast({ title: toast, icon: 'success' });
|
||||
// 刷新详情数据
|
||||
this.loadDetail(item.id);
|
||||
} catch(e) { wx.hideLoading(); wx.showToast({ title: e.error || '打卡失败', icon: 'none' }); }
|
||||
finally { this._submittingCheck = false; }
|
||||
},
|
||||
|
||||
hideCheckModal: function() { this.setData({ showCheckModal: false }); },
|
||||
|
||||
// ===== 图片预览 =====
|
||||
previewPhoto: function(e) {
|
||||
var url = e.currentTarget.dataset.url;
|
||||
if (url) {
|
||||
wx.previewImage({ urls: [url], current: url });
|
||||
}
|
||||
},
|
||||
|
||||
goBack: function() { wx.navigateBack(); },
|
||||
goHome: function() { wx.switchTab({ url: '/pages/index/index' }); },
|
||||
goProfile: function() { wx.switchTab({ url: '/pages/profile/profile' }); }
|
||||
}, {"loadDetail": ["checkinDetail", "coupleInfo"]}));
|
||||
Reference in New Issue
Block a user