init: initial commit
This commit is contained in:
@@ -0,0 +1,932 @@
|
||||
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' }); }
|
||||
});
|
||||
Reference in New Issue
Block a user