195 lines
7.9 KiB
JavaScript
195 lines
7.9 KiB
JavaScript
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: [], 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.setData({loading: !this._hasCachedData, loadError:false});
|
|
try {
|
|
var data = await api.checkinDetail(id);
|
|
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 = (data.logs || []).map(function(l) {
|
|
l.time = l.created_at ? l.created_at.substring(0, 16).replace('T', ' ') : '';
|
|
l.photoUrl = l.photo ? getImageUrl(l.photo) : '';
|
|
return l;
|
|
});
|
|
// 根据打卡权限类型映射统计数据
|
|
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,
|
|
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}); }
|
|
},
|
|
|
|
// ===== 打卡操作 =====
|
|
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) return;
|
|
|
|
// ★ 在用户点击手势上下文中提前请求订阅消息(符合微信规范)
|
|
requestSubscribeAfterAction('checkin');
|
|
|
|
try {
|
|
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.showToast({ title: e.error || '打卡失败', icon: 'none' }); }
|
|
},
|
|
|
|
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"]}));
|