const { getLayout } = require('../../utils/layout'); // pages/profile/profile.js - 与原网站一致的个人中心 const { api, getImageUrl } = require('../../utils/request'); const { saveScrollPosition, getScrollPosition } = require('../../utils/scroll-pos'); Page({ onResize: function() { this.setData(getLayout()); }, data: { scrollTop: 0, // 我的信息 myNickname: '未登录', myDisplayId: '', myPhone: '-', myGender: '-', myAge: '-', myBirthday: '-', myRegion: '', myLocation: '', myStatus: '设置恋爱信息', myAvatarUrl: '', myInitial: '?', // TA的信息 hasPartner: false, bindingKnown: false, bindingError: false, partnerName: 'TA', partnerDisplayId: '', partnerDetail: '', partnerAvatarUrl: '', partnerInitial: '?', partnerBirthday: '', partnerGenderRaw: '', // 恋爱信息 anniversaryDateText: '点击设置你们的纪念日', loveStoryText: '记录你们的故事', loveStartDate: '', // 编辑资料弹窗 showEditProfileModal: false, editNickname: '', editGender: 'male', editGenderText: '男', editAge: '', editBirthday: '', editRegion: '', editAvatarUrl: '', editAvatarPath: '', editNicknameInitial: '?', // 设置恋爱日期弹窗 showSetDateModal: false, tempLoveDate: '', tempLoveStory: '', // 查看TA资料(只读)弹窗 showEditPartnerModal: false, editPartnerNickname: '', editPartnerGender: 'male', editPartnerGenderText: '男', editPartnerAge: '', editPartnerBirthday: '', editPartnerAvatarUrl: '', editPartnerAvatarPath: '', editPartnerNameInitial: '?', genderOptions: ['男', '女'], // 解除绑定验证 showUnbindVerifyModal: false, unbindQuestion: '', unbindAnswer: 0, unbindUserInput: '', // 解绑状态 unbindStatus: '', unbindIsRequester: false, unbindRequesterName: '', unbindRemaining: 0, // TA详情弹窗 showPartnerDetailModal: false, partnerDetailNickname: '-', partnerDetailGender: '-', partnerDetailAge: '-', partnerDetailBirthday: '-', partnerDetailAvatarUrl: '', partnerNameInitial: '?', // ===== 邀请绑定相关 ===== showInvitePanel: false, inviteTab: 'received', receivedInvites: [], sentInvites: [], inviteTargetId: '', inviteMessage: '', // 分享绑定 showShareBindModal: false, shareInviterId: '', shareInviterName: '', shareDisagree: false }, // 左滑返回机制 touchStartX: 0, touchStartY: 0, onTouchStart: function(e) { this.touchStartX = e.touches[0].clientX; this.touchStartY = e.touches[0].clientY; }, onTouchEnd: function(e) { var dx = this.touchStartX - e.changedTouches[0].clientX; var dy = Math.abs(this.touchStartY - e.changedTouches[0].clientY); // 短距离/垂直滑动不处理(交给按钮tap事件) if (dx < 20 && dy < 20) return; // 只有水平且左滑超过80px才处理 if (Math.abs(dx) > dy && dx > 80) { if (this.data.showEditProfileModal) { this.hideEditProfileModal(); } else if (this.data.showEditPartnerModal) { this.hideEditPartnerModal(); } else { wx.navigateBack(); } } }, _needRefresh: true, onScroll: function(e) { saveScrollPosition('profile', e.detail.scrollTop); }, onLoad: function(options) { this.setData(getLayout()); this._needRefresh = true; this._openBindOnLoad = !!(options && options.bind); this.setData({ userId: wx.getStorageSync('userId'), coupleId: wx.getStorageSync('coupleId'), scrollTop: getScrollPosition('profile') }); this.loadData(); this.loadUnbindStatus(); this.fetchAndSaveLocation(); // 从首页点击头像跳转过来,自动打开编辑 if (options.edit === 'self') { var self = this; setTimeout(function() { self.showEditProfileModal(); }, 500); } else if (options.edit === 'partner') { var self = this; setTimeout(function() { self.showEditPartnerModal(); }, 500); } // 从分享邀请链接进入 if (options && options.inviter) { var self = this; setTimeout(function() { self.handleShareInvite(options.inviter); }, 800); } }, onShow: function() { var uid = wx.getStorageSync('userId'); var cid = wx.getStorageSync('coupleId'); var self = this; var savedTop = getScrollPosition('profile'); this.setData({ scrollTop: savedTop, bindingKnown: false, myLocation: '' }); // 延迟重新设置 scrollTop,解决从子页面 navigateBack 返回后滚动位置丢失的问题 setTimeout(function() { self.setData({ scrollTop: savedTop }); }, 100); this.setData({ userId: uid, coupleId: cid }); this.loadData(); // 如果已绑定情侣,关闭邀请面板 if (cid && this.data.showInvitePanel) { this.setData({ showInvitePanel: false }); if (this._pollTimer) { clearInterval(this._pollTimer); this._pollTimer = null; } } }, onUnload: function() { if (this._pollTimer) { clearInterval(this._pollTimer); this._pollTimer = null; } }, onPullDownRefresh: async function() { await this.loadData(); wx.stopPullDownRefresh(); }, // 比较新旧值,只返回变化的字段(避免全量 setData 导致闪屏) _diffUpdate: function(newData) { var updates = {}; for (var key in newData) { if (this.data[key] !== newData[key]) { updates[key] = newData[key]; } } if (Object.keys(updates).length > 0) { this.setData(updates); } }, loadData: async function() { this.setData({bindingError:false}); var requestId = (this._coupleInfoRequestId || 0) + 1; this._coupleInfoRequestId = requestId; try { // 获取情侣信息 const info = await api.coupleInfo(); this.setData({userId: wx.getStorageSync('userId')}); if (requestId !== this._coupleInfoRequestId) return; // 未绑定情侣时从后端获取用户最新资料 if (info.not_bound) { wx.removeStorageSync('coupleId'); var myInfo = info.partner1 || {}; var genderText = myInfo.gender === 'male' ? '男' : (myInfo.gender === 'female' ? '女' : '-'); var region = myInfo.region || ''; var location = myInfo.location || ''; if (/^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/.test(location)) location = ''; wx.setStorageSync('region', region); this._diffUpdate({ bindingKnown: true, coupleId: null, hasPartner: false, partnerName: 'TA', partnerDisplayId: '', partnerDetail: '', partnerAvatarUrl: '', partnerInitial: '?', partnerBirthday: '', partnerGenderRaw: '', myStatus: '设置恋爱信息', anniversaryDateText: '点击设置你们的纪念日', loveStoryText: '记录你们的故事', loveStartDate: '', tempLoveDate: '', tempLoveStory: '', myNickname: myInfo.nickname || myInfo.username || '未登录', myDisplayId: myInfo.user_id || wx.getStorageSync('displayId') || '', myPhone: myInfo.phone || myInfo.username || '-', myGender: genderText, myGenderRaw: myInfo.gender || '', myAge: myInfo.age > 0 ? myInfo.age + '岁' : '-', myAgeText: myInfo.age > 0 ? myInfo.age : '', myBirthday: myInfo.birthday || '-', myBirthdayText: myInfo.birthday || '', myRegion: region, myLocation: location, myAvatarUrl: getImageUrl(myInfo.avatar), myInitial: (myInfo.nickname || myInfo.username || '?')[0], editNickname: myInfo.nickname || '', editAge: myInfo.age > 0 ? myInfo.age : '', editBirthday: myInfo.birthday || '', editRegion: region, editNicknameInitial: (myInfo.nickname || myInfo.username || '?')[0] }); if (this._openBindOnLoad) { this._openBindOnLoad = false; this.showInvitePanel(); } return; } // 同步情侣ID到本地存储 if (info.id) { wx.setStorageSync('coupleId', info.id); if (this.data.coupleId !== info.id) { this.setData({ coupleId: info.id }); } } const myUid = this.data.userId; const p1 = info.partner1 || {}; const p2 = info.partner2 || {}; const me = p1.id == myUid ? p1 : (p2.id == myUid ? p2 : null); const partner = p1.id == myUid ? p2 : (p2.id == myUid ? p1 : null); // 我的信息 — 只更新变化的字段 if (me) { const genderText = me.gender === 'male' ? '男' : (me.gender === 'female' ? '女' : '-'); const storedDisplayId = wx.getStorageSync('displayId') || ''; var region = me.region || ''; var location = me.location || ''; if (/^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/.test(location)) location = ''; wx.setStorageSync('region', region); this._diffUpdate({ myNickname: me.nickname || me.username || '未登录', myDisplayId: me.user_id || storedDisplayId, myPhone: me.phone || me.username || '-', myGender: genderText, myGenderRaw: me.gender || '', myAge: me.age > 0 ? me.age + '岁' : '-', myAgeText: me.age > 0 ? me.age : '', myBirthday: me.birthday || '-', myBirthdayText: me.birthday || '', myRegion: region, myLocation: location, myAvatarUrl: getImageUrl(me.avatar), myInitial: (me.nickname || me.username || '?')[0], editNickname: me.nickname || '', editAge: me.age > 0 ? me.age : '', editBirthday: me.birthday || '', editRegion: region, editNicknameInitial: (me.nickname || me.username || '?')[0] }); } // TA的信息 — 只更新变化的字段 if (partner) { const genderText = partner.gender === 'male' ? '男' : (partner.gender === 'female' ? '女' : '-'); let details = []; if (genderText !== '-') details.push(genderText); if (partner.age > 0) details.push(partner.age + '岁'); if (partner.birthday) details.push('🎂 ' + partner.birthday); this._diffUpdate({ bindingKnown: true, hasPartner: true, partnerName: partner.nickname || partner.username || 'TA', partnerDisplayId: partner.user_id || '', partnerDetail: details.join(' · ') || 'TA的信息', partnerAvatarUrl: getImageUrl(partner.avatar), partnerInitial: (partner.nickname || partner.username || '?')[0], partnerBirthday: partner.birthday || '', partnerGenderRaw: partner.gender || '', partnerDetailNickname: partner.nickname || partner.username || '-', partnerDetailGender: genderText, partnerDetailAge: partner.age > 0 ? partner.age + '岁' : '-', partnerDetailBirthday: partner.birthday || '-', partnerDetailAvatarUrl: getImageUrl(partner.avatar), partnerNameInitial: (partner.nickname || partner.username || '?')[0] }); } // 恋爱天数和状态 — 只更新变化的字段 let daysCount = 0; if (info.love_start_date) { const start = new Date(info.love_start_date); daysCount = Math.floor((Date.now() - start) / 86400000); const partnerName = partner ? (partner.nickname || partner.username || 'TA') : 'TA'; this._diffUpdate({ anniversaryDateText: info.love_start_date + ' (已设置)', loveStoryText: info.love_story ? (info.love_story.length > 20 ? info.love_story.substring(0, 20) + '...' : info.love_story) : '记录你们的故事', myStatus: '和' + partnerName + '在一起 ' + daysCount + ' 天 💕', loveStartDate: info.love_start_date, tempLoveDate: info.love_start_date || '', tempLoveStory: info.love_story || '' }); } else { this._diffUpdate({ anniversaryDateText: '点击设置你们的纪念日', loveStoryText: info.love_story ? (info.love_story.length > 20 ? info.love_story.substring(0, 20) + '...' : info.love_story) : '记录你们的故事', myStatus: '设置恋爱信息', loveStartDate: '', tempLoveDate: '', tempLoveStory: '' }); } } catch (e) { if (requestId !== this._coupleInfoRequestId) return; console.error(e); this.setData({ bindingKnown: false, bindingError:true }); } }, // 获取定位并保存到数据库(使用模糊定位,getLocation 与 getFuzzyLocation 互斥,统一用模糊定位) fetchAndSaveLocation: function() { var self = this; self._fuzzyLocation(); }, // 模糊定位兜底 _fuzzyLocation: function() { var self = this; if (!wx.getFuzzyLocation) return; wx.getFuzzyLocation({ type: 'gcj02', success: function(res) { self._reportLocation(res.latitude, res.longitude); }, fail: function() {} }); }, // 上报经纬度到后端并更新城市地址显示 _reportLocation: function(lat, lng) { var self = this; if (!lat || !lng) return; // 保留更多小数位,减少坐标截断误差 var location = lat.toFixed(6) + ',' + lng.toFixed(6); api.updateLocation(location).then(function(resp) { // 后端返回的地址;若为空或经纬度(说明逆地理编码失败),一律不采用,绝不显示经纬度 var city = (resp && resp.location) ? resp.location : ''; if (city === '' || /^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/.test(city)) { return; } // 转换成功后展示接口返回的城市地址 if (self.data.myLocation !== city) { self.setData({ myLocation: city }); } }).catch(function() {}); }, // 编辑资料 showEditProfileModal: function() { var d = this.data; var rawGender = d.myGenderRaw || ''; var genderText = rawGender === 'female' ? '女' : '男'; this.setData({ showEditProfileModal: true, editNickname: d.myNickname === '未设置' ? '' : d.myNickname, editGender: rawGender || 'male', editGenderText: genderText, editAge: d.myAgeText ? String(parseInt(d.myAgeText) || '') : '', editBirthday: d.myBirthdayText || '', editRegion: d.myRegion || '', editAvatarUrl: d.myAvatarUrl || '', editNicknameInitial: d.myInitial || '?' }); }, onEditGenderChange: function(e) { var idx = e.detail.value; var texts = ['男', '女']; var vals = ['male', 'female']; this.setData({ editGender: vals[idx], editGenderText: texts[idx] }); }, hideEditProfileModal: function() { this.setData({ showEditProfileModal: false }); }, onEditNicknameInput: function(e) { this.setData({ editNickname: e.detail.value }); }, onEditBirthdayInput: function(e) { var birthday = e.detail.value; var age = ''; if (birthday) { var birthDate = new Date(birthday); var today = new Date(); var calcAge = today.getFullYear() - birthDate.getFullYear(); var m = today.getMonth() - birthDate.getMonth(); if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) { calcAge--; } age = calcAge > 0 ? calcAge : 1; } this.setData({ editBirthday: birthday, editAge: String(age) }); }, chooseAvatar: function() { wx.chooseImage({ count: 1, sizeType: ['compressed'], sourceType: ['album', 'camera'], success: async (res) => { const filePath = res.tempFiles[0].path; this.setData({ editAvatarUrl: filePath }); // 上传头像 try { const data = await api.uploadAvatar(filePath); this.setData({ editAvatarUrl: getImageUrl(data.path), editAvatarPath: data.path }); wx.showToast({ title: '头像上传成功 ✨', icon: 'success' }); } catch (e) { wx.showToast({ title: e.error || '上传失败', icon: 'none' }); } } }); }, saveProfile: async function() { const { editNickname, editGender, editAge, editBirthday, editRegion, editAvatarPath, tempLoveDate, tempLoveStory, coupleId } = this.data; if (!editNickname) { wx.showToast({ title: '请输入昵称', icon: 'none' }); return; } try { await api.updateProfile({ nickname: editNickname, gender: editGender, age: parseInt(editAge) || 0, birthday: editBirthday, region: editRegion, avatar: editAvatarPath }); // 更新本地存储的昵称,确保未绑定情侣时也能正确显示 wx.setStorageSync('nickname', editNickname); if (editAvatarPath) { wx.setStorageSync('avatar', editAvatarPath); } // 如果有恋爱日期且已绑定情侣,也保存 if (tempLoveDate && coupleId) { await api.updateCoupleInfo({ love_start_date: tempLoveDate, love_story: tempLoveStory || '' }); } wx.showToast({ title: '资料更新成功 💕', icon: 'success' }); this.hideEditProfileModal(); this.loadData(); } catch (e) { wx.showToast({ title: e.error || '保存失败', icon: 'none' }); } }, // 设置恋爱日期 showSetDateModal: function() { this.setData({ showSetDateModal: true }); }, hideSetDateModal: function() { this.setData({ showSetDateModal: false }); }, onLoveDateInput: function(e) { this.setData({ tempLoveDate: e.detail.value }); }, onLoveStoryInput: function(e) { this.setData({ tempLoveStory: e.detail.value }); }, // 显示恋爱故事 showCoupleStory: function() { const { tempLoveStory } = this.data; if (!tempLoveStory) { wx.showToast({ title: '还没有恋爱故事,先设置纪念日吧 ✨', icon: 'none' }); this.showSetDateModal(); } else { wx.showModal({ title: '💕 恋爱故事', content: tempLoveStory, showCancel: false }); } }, saveLoveDate: async function() { const { tempLoveDate, tempLoveStory } = this.data; if (!tempLoveDate) { wx.showToast({ title: '请选择日期', icon: 'none' }); return; } try { await api.updateCoupleInfo({ love_start_date: tempLoveDate, love_story: tempLoveStory }); wx.showToast({ title: '纪念日设置成功 💕', icon: 'success' }); this.hideSetDateModal(); this.loadData(); } catch (e) { wx.showToast({ title: e.error || '保存失败', icon: 'none' }); } }, // TA详情 showPartnerDetail: function() { this.setData({ showPartnerDetailModal: true }); }, hidePartnerDetailModal: function() { this.setData({ showPartnerDetailModal: false }); }, // 查看TA资料(只读) showEditPartnerModal: function() { const d = this.data; var rawGender = d.partnerGenderRaw || ''; var genderText = rawGender === 'male' ? '男' : (rawGender === 'female' ? '女' : '未设置'); // 从 partnerDetail 中解析年龄(格式:XX岁) var ageMatch = d.partnerDetail.match(/(\d+)岁/); var partnerAge = ageMatch ? ageMatch[1] : ''; this.setData({ showEditPartnerModal: true, editPartnerNickname: d.partnerName === 'TA' ? '' : d.partnerName, editPartnerGender: rawGender || 'male', editPartnerGenderText: genderText, editPartnerAge: partnerAge, editPartnerBirthday: d.partnerBirthday || '', editPartnerAvatarUrl: d.partnerAvatarUrl || '', editPartnerAvatarPath: '', editPartnerNameInitial: d.partnerInitial || '?' }); }, hideEditPartnerModal: function() { this.setData({ showEditPartnerModal: false }); }, // 加载解绑状态 loadUnbindStatus: function() { var self = this; api.unbindStatus().then(function(res) { if (res && res.status && res.status !== 'none') { self.setData({ unbindStatus: res.status, unbindIsRequester: !!res.is_requester, unbindRequesterName: res.requester_name || '对方', unbindRemaining: res.remaining_seconds || 0 }); } else { self.setData({ unbindStatus: '', unbindIsRequester: false, unbindRequesterName: '' }); } }).catch(function() {}); }, // 解除绑定 — 根据状态显示不同操作 showUnbindVerify: function() { var status = this.data.unbindStatus; var isRequester = this.data.unbindIsRequester; if (status === 'pending') { if (isRequester) { this.doCancelUnbind(); } else { this.doRespondUnbind(); } } else if (status === 'agreed') { wx.showToast({ title: '双方已同意解绑,正在处理中', icon: 'none' }); wx.navigateTo({ url: '/pages/unbind/unbind' }); } else { this.doRequestUnbind(); } }, doRequestUnbind: function() { var self = this; wx.showModal({ title: '💔 解除绑定', content: '发起解绑请求后,对方需要在72小时内确认同意。\n\n对方同意后,所有情侣记录将被永久删除(记忆日、日记、相册、纪念日、情话、歌曲、打卡),仅保留双方个人资料。\n\n你也可以在对方确认前撤销请求。', cancelText: '取消', confirmText: '发起解绑', confirmColor: '#FF4757', success: function(res) { if (res.confirm) { wx.showLoading({ title: '发送请求...' }); api.unbindRequest().then(function() { wx.hideLoading(); wx.showToast({ title: '解绑请求已发送', icon: 'success' }); self.loadUnbindStatus(); wx.navigateTo({ url: '/pages/unbind/unbind' }); }).catch(function(err) { wx.hideLoading(); wx.showToast({ title: err.error || '操作失败', icon: 'none' }); }); } } }); }, doCancelUnbind: function() { var self = this; wx.showModal({ title: '↩️ 撤销解绑', content: '确定要撤销解绑请求吗?对方将不会收到任何通知。', cancelText: '取消', confirmText: '撤销请求', confirmColor: '#FF6B9D', success: function(res) { if (res.confirm) { wx.showLoading({ title: '撤销中...' }); api.unbindCancel().then(function() { wx.hideLoading(); wx.showToast({ title: '已撤销解绑请求', icon: 'success' }); self.loadUnbindStatus(); }).catch(function(err) { wx.hideLoading(); wx.showToast({ title: err.error || '操作失败', icon: 'none' }); }); } } }); }, doRespondUnbind: function() { var self = this; var name = this.data.unbindRequesterName; wx.showActionSheet({ itemList: ['✅ 同意解绑', '❌ 拒绝解绑'], success: function(res) { if (res.tapIndex === 0) { wx.showModal({ title: '⚠️ 确认同意', content: name + ' 发起了解绑请求。\n\n同意后,所有情侣记录将被永久删除(记忆日、日记、相册、歌曲、打卡),仅保留双方个人资料。\n\n此操作不可恢复!', cancelText: '取消', confirmText: '同意解绑', confirmColor: '#FF4757', success: function(r) { if (r.confirm) { wx.showLoading({ title: '处理中...' }); api.unbindRespond({ agree: true }).then(function() { wx.hideLoading(); wx.showToast({ title: '已同意解绑', icon: 'success' }); wx.removeStorageSync('coupleId'); wx.removeStorageSync('partnerId'); wx.removeStorageSync('partnerName'); wx.removeStorageSync('partnerAvatar'); wx.removeStorageSync('petHasPet'); setTimeout(function() { wx.reLaunch({ url: '/pages/index/index' }); }, 1500); }).catch(function(err) { wx.hideLoading(); wx.showToast({ title: err.error || '操作失败', icon: 'none' }); }); } } }); } else if (res.tapIndex === 1) { wx.showModal({ title: '拒绝解绑', content: '确定要拒绝 ' + name + ' 的解绑请求吗?', cancelText: '取消', confirmText: '拒绝', confirmColor: '#FF6B9D', success: function(r) { if (r.confirm) { wx.showLoading({ title: '处理中...' }); api.unbindRespond({ agree: false }).then(function() { wx.hideLoading(); wx.showToast({ title: '已拒绝解绑请求', icon: 'success' }); self.loadUnbindStatus(); }).catch(function(err) { wx.hideLoading(); wx.showToast({ title: err.error || '操作失败', icon: 'none' }); }); } } }); } } }); }, // 空操作(用于 catchtap 阻止冒泡) noop: function() {}, // 退出登录 logout: function() { wx.showModal({ title: '确认退出', content: '确定要退出登录吗?', success: (res) => { if (res.confirm) { api.logout().catch(() => {}); wx.clearStorageSync(); wx.reLaunch({ url: '/pages/index/index' }); } } }); }, // 跳转前保存当前滚动位置 _savePosBeforeLeave: function() { saveScrollPosition('profile', this.data.scrollTop); }, // ===== 邀请绑定 ===== showInvitePanel: function() { var displayId = wx.getStorageSync('displayId') || ''; this.setData({ showInvitePanel: true, inviteTab: 'received', inviteTargetId: '', inviteMessage: '', myDisplayId: displayId }); this.loadInvites(); this.startPollCoupleStatus(); }, hideInvitePanel: function() { this.setData({ showInvitePanel: false }); if (this._pollTimer) { clearInterval(this._pollTimer); this._pollTimer = null; } }, onInviteTargetIdInput: function(e) { this.setData({ inviteTargetId: e.detail.value }); }, onInviteMessageInput: function(e) { this.setData({ inviteMessage: e.detail.value }); }, // 轮询检查情侣关系是否已恢复 startPollCoupleStatus: function() { var self = this; if (self._pollTimer) clearInterval(self._pollTimer); self._pollTimer = setInterval(function() { api.myInvitations().then(function(data) { if (data && data.couple_id) { clearInterval(self._pollTimer); self._pollTimer = null; wx.setStorageSync('coupleId', data.couple_id); wx.showToast({ title: '情侣关系已恢复 💕', icon: 'success' }); setTimeout(function() { self.setData({ showInvitePanel: false }); self.loadData(); }, 1500); } }).catch(function() {}); }, 10000); }, sendInvite: async function() { const { inviteTargetId, inviteMessage } = this.data; if (!inviteTargetId) { wx.showToast({ title: '请输入对方ID', icon: 'none' }); return; } if (inviteTargetId.length < 6) { wx.showToast({ title: 'ID为6位数字', icon: 'none' }); return; } try { wx.showLoading({ title: '发送中...' }); const res = await api.invitePartner({ target_user_id: inviteTargetId, message: inviteMessage }); wx.hideLoading(); wx.showToast({ title: res.msg || '邀请已发送,等待对方同意 💕', icon: 'success' }); this.setData({ inviteTargetId: '', inviteTab: 'sent' }); this.loadInvites(); } catch (err) { wx.hideLoading(); wx.showToast({ title: err.error || '发送失败', icon: 'none' }); } }, loadInvites: async function() { try { const data = await api.myInvitations(); const received = (data.received || []).map(function(item) { item.from_initial = (item.from_nickname || item.from_username || '?')[0]; item.short_date = item.created_at ? item.created_at.substring(0, 16).replace('T', ' ') : ''; return item; }); const sent = (data.sent || []).map(function(item) { item.to_initial = (item.to_nickname || item.to_username || '?')[0]; item.short_date = item.created_at ? item.created_at.substring(0, 16).replace('T', ' ') : ''; return item; }); this.setData({ receivedInvites: received, sentInvites: sent }); if (data.couple_id) { wx.setStorageSync('coupleId', data.couple_id); wx.showToast({ title: '情侣关系已恢复 💕', icon: 'success' }); setTimeout(() => { this.setData({ showInvitePanel: false }); this.loadData(); }, 1500); } } catch (e) { console.error(e); } }, switchInviteTab: function(e) { const tab = e.currentTarget.dataset.tab; this.setData({ inviteTab: tab }); }, acceptInvite: async function(e) { const id = e.currentTarget.dataset.id; try { wx.showLoading({ title: '处理中...' }); const res = await api.respondInvitation({ invitation_id: id, accept: 1 }); wx.hideLoading(); if (res.couple_id) { wx.setStorageSync('coupleId', res.couple_id); wx.showToast({ title: '绑定成功 💕', icon: 'success' }); setTimeout(() => { this.setData({ showInvitePanel: false }); this.loadData(); }, 1000); } } catch (err) { wx.hideLoading(); wx.showToast({ title: err.error || '操作失败', icon: 'none' }); } }, rejectInvite: async function(e) { const id = e.currentTarget.dataset.id; try { wx.showLoading({ title: '处理中...' }); await api.respondInvitation({ invitation_id: id, accept: 0 }); wx.hideLoading(); wx.showToast({ title: '已拒绝', icon: 'success' }); this.loadInvites(); } catch (err) { wx.hideLoading(); wx.showToast({ title: err.error || '操作失败', icon: 'none' }); } }, // ===== 分享绑定 ===== onShareAppMessage: function() { var displayId = wx.getStorageSync('displayId') || this.data.myDisplayId; var nick = wx.getStorageSync('nickname') || '我'; if (!displayId) { wx.showToast({ title: '请先完善资料', icon: 'none' }); return {}; } return { title: nick + ' 邀请你绑定情侣 💕', path: '/pages/profile/profile?inviter=' + displayId, imageUrl: '/images/share.png' }; }, // 从分享链接进入时处理邀请绑定 handleShareInvite: function(inviterId) { if (!inviterId) return; this.setData({ shareInviterId: inviterId, showShareBindModal: true, shareDisagree: false }); }, acceptShareBind: async function() { var self = this; try { wx.showLoading({ title: '处理中...' }); const res = await api.acceptShareInvite({ inviter_id: this.data.shareInviterId }); wx.hideLoading(); if (res.couple_id) { wx.setStorageSync('coupleId', res.couple_id); wx.showToast({ title: '绑定成功 💕', icon: 'success' }); this.setData({ showShareBindModal: false }); setTimeout(() => { this.loadData(); }, 1000); } } catch (err) { wx.hideLoading(); wx.showToast({ title: err.error || '操作失败', icon: 'none' }); } }, rejectShareBind: function() { this.setData({ shareDisagree: true, shareInviterName: 'TA' }); }, hideShareBindModal: function() { this.setData({ showShareBindModal: false }); }, // 页面跳转 manageRelationship: function() { wx.navigateTo({ url: '/pages/unbind/unbind' }); }, goToSettings: function() { this._savePosBeforeLeave(); wx.navigateTo({ url: '/pages/settings/settings' }); }, goHome: function() { this._savePosBeforeLeave(); wx.redirectTo({ url: '/pages/index/index' }); } });