324 lines
9.3 KiB
JavaScript
324 lines
9.3 KiB
JavaScript
const { request, getBaseUrl } = require('../../utils_new/request');
|
||
const util = require('../../utils/util');
|
||
|
||
Page({
|
||
data: {
|
||
statusBarHeight: 20,
|
||
navBarHeight: 44,
|
||
totalNavHeight: 64,
|
||
defaultAvatar: '/images/default-avatar.svg',
|
||
loading: true,
|
||
saving: false,
|
||
uploading: false,
|
||
genderRange: ['男', '女'],
|
||
ageRanges: ['18-24岁', '25-35岁', '36-45岁', '46-55岁', '56岁以上'],
|
||
isProfileCompleted: false,
|
||
originalAvatar: '',
|
||
avatarUploadTemp: '',
|
||
form: {
|
||
nickname: '',
|
||
avatar: '',
|
||
gender: 0, // 1: 男, 2: 女
|
||
age_range: '',
|
||
region: '',
|
||
phone: '' // 增加手机号显示
|
||
}
|
||
},
|
||
onLoad() {
|
||
const sys = wx.getSystemInfoSync();
|
||
const menu = wx.getMenuButtonBoundingClientRect();
|
||
const statusBarHeight = sys.statusBarHeight || 20;
|
||
const navBarHeight = menu.height + (menu.top - statusBarHeight) * 2;
|
||
this.setData({
|
||
statusBarHeight,
|
||
navBarHeight,
|
||
totalNavHeight: statusBarHeight + navBarHeight
|
||
});
|
||
this.load();
|
||
},
|
||
onBack() {
|
||
wx.navigateBack({ delta: 1 });
|
||
},
|
||
async load() {
|
||
this.setData({ loading: true });
|
||
try {
|
||
let profileData = {
|
||
nickname: '',
|
||
avatar: '',
|
||
gender: 0,
|
||
age_range: '',
|
||
region: '',
|
||
phone: ''
|
||
};
|
||
let isProfileCompleted = false;
|
||
|
||
try {
|
||
const res = await request({ url: '/api/users/profile', method: 'GET' });
|
||
if (res.data && res.data.code === 0) {
|
||
const data = res.data.data;
|
||
profileData = {
|
||
nickname: data.nickname || '',
|
||
avatar: util.getFullImageUrl(data.avatar) || '',
|
||
gender: Number(data.gender || 0),
|
||
age_range: data.ageRange || data.age_range || '',
|
||
region: data.region || '',
|
||
phone: data.phone || ''
|
||
};
|
||
isProfileCompleted = !!data.profile_completed;
|
||
}
|
||
} catch (err) {
|
||
console.log('API load failed');
|
||
}
|
||
|
||
this.setData({
|
||
form: profileData,
|
||
isProfileCompleted,
|
||
originalAvatar: profileData.avatar || ''
|
||
});
|
||
} finally {
|
||
this.setData({ loading: false });
|
||
}
|
||
},
|
||
|
||
// 格式化图片地址,处理相对路径
|
||
formatImageUrl(url) {
|
||
return util.getFullImageUrl(url);
|
||
},
|
||
|
||
// 将完整URL转回相对路径
|
||
getRelativeUrl(url) {
|
||
if (!url) return '';
|
||
if (url.startsWith('wxfile://') || url.startsWith('data:')) return '';
|
||
const baseUrl = getBaseUrl();
|
||
if (url.startsWith(baseUrl)) {
|
||
return url.replace(baseUrl, '');
|
||
}
|
||
try {
|
||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||
const parsed = new URL(url);
|
||
const path = `${parsed.pathname}${parsed.search || ''}`;
|
||
return path;
|
||
}
|
||
} catch (_) {}
|
||
return url;
|
||
},
|
||
|
||
onChooseAvatar(e) {
|
||
if (e.detail.errMsg && e.detail.errMsg.indexOf('fail') !== -1) {
|
||
console.error('头像选择失败:', e.detail.errMsg);
|
||
// 如果是开发者工具的 Bug,提示用户重启
|
||
if (e.detail.errMsg.indexOf('not found') !== -1) {
|
||
wx.showModal({
|
||
title: '上传提示',
|
||
content: '微信开发者工具临时文件异常,请尝试重新点击或重启开发者工具。',
|
||
showCancel: false
|
||
});
|
||
}
|
||
return;
|
||
}
|
||
|
||
const { avatarUrl } = e.detail;
|
||
if (!avatarUrl) return;
|
||
|
||
// 微信头像临时路径先显示,再上传
|
||
this.setData({
|
||
'form.avatar': avatarUrl,
|
||
avatarUploadTemp: avatarUrl
|
||
});
|
||
this.uploadAvatar(avatarUrl);
|
||
},
|
||
|
||
onNicknameInput(e) {
|
||
this.setData({
|
||
'form.nickname': e.detail.value
|
||
});
|
||
},
|
||
|
||
onNicknameBlur(e) {
|
||
this.setData({
|
||
'form.nickname': e.detail.value
|
||
});
|
||
},
|
||
|
||
onGenderChange(e) {
|
||
const idx = Number(e.detail.value);
|
||
const gender = idx + 1; // 0 -> 1 (男), 1 -> 2 (女)
|
||
this.setData({
|
||
'form.gender': gender
|
||
});
|
||
},
|
||
|
||
onAgeRange(e) {
|
||
const idx = Number(e.detail.value);
|
||
const age_range = this.data.ageRanges[idx] || '';
|
||
this.setData({
|
||
'form.age_range': age_range
|
||
});
|
||
},
|
||
|
||
onRegion(e) {
|
||
const regionArray = e.detail.value || [];
|
||
const region = regionArray.join(' ');
|
||
this.setData({
|
||
'form.region': region,
|
||
'form.regionArray': regionArray
|
||
});
|
||
},
|
||
|
||
uploadAvatar(filePath) {
|
||
this.setData({ uploading: true });
|
||
const token = wx.getStorageSync('auth_token') || '';
|
||
const baseUrl = getBaseUrl();
|
||
|
||
// 获取设备ID
|
||
const deviceId = wx.getStorageSync('deviceId') || wx.getStorageSync('user_id') || 'unknown';
|
||
|
||
wx.uploadFile({
|
||
url: `${baseUrl}/api/upload`,
|
||
filePath,
|
||
name: 'file',
|
||
formData: { folder: 'avatars' },
|
||
header: {
|
||
'x-device-id': deviceId,
|
||
...(token ? { Authorization: `Bearer ${token}` } : {})
|
||
},
|
||
success: (res) => {
|
||
try {
|
||
const body = JSON.parse(res.data || '{}');
|
||
if (body.code === 0 && body.data?.url) {
|
||
const fullUrl = this.formatImageUrl(body.data.url);
|
||
this.setData({ 'form.avatar': fullUrl, avatarUploadTemp: '' });
|
||
wx.showToast({ title: '头像上传成功', icon: 'success' });
|
||
} else {
|
||
wx.showToast({ title: body.message || '上传失败', icon: 'none' });
|
||
this.setData({
|
||
'form.avatar': this.data.originalAvatar || '',
|
||
avatarUploadTemp: ''
|
||
});
|
||
}
|
||
} catch (e) {
|
||
wx.showToast({ title: '解析返回失败', icon: 'none' });
|
||
this.setData({
|
||
'form.avatar': this.data.originalAvatar || '',
|
||
avatarUploadTemp: ''
|
||
});
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
console.error('upload failed', err);
|
||
wx.showToast({ title: '网络上传失败', icon: 'none' });
|
||
this.setData({
|
||
'form.avatar': this.data.originalAvatar || '',
|
||
avatarUploadTemp: ''
|
||
});
|
||
},
|
||
complete: () => {
|
||
this.setData({ uploading: false });
|
||
}
|
||
});
|
||
},
|
||
|
||
onAvatarError() {
|
||
this.setData({
|
||
'form.avatar': this.data.defaultAvatar
|
||
});
|
||
},
|
||
|
||
async save() {
|
||
if (this.data.saving) return;
|
||
if (this.data.uploading) {
|
||
wx.showToast({ title: '头像上传中,请稍候', icon: 'none' });
|
||
return;
|
||
}
|
||
const form = this.data.form;
|
||
|
||
const avatar = String(form.avatar || '').trim();
|
||
if (avatar.startsWith('wxfile://') || avatar.startsWith('data:')) {
|
||
wx.showToast({ title: '头像尚未上传成功,请重新上传', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
// 验证完整信息
|
||
if (!form.avatar || form.avatar === this.data.defaultAvatar) {
|
||
wx.showToast({ title: '请设置头像', icon: 'none' });
|
||
return;
|
||
}
|
||
if (!String(form.nickname || '').trim()) {
|
||
wx.showToast({ title: '请输入昵称', icon: 'none' });
|
||
return;
|
||
}
|
||
if (form.gender !== 1 && form.gender !== 2) {
|
||
wx.showToast({ title: '请选择性别', icon: 'none' });
|
||
return;
|
||
}
|
||
if (!form.age_range) {
|
||
wx.showToast({ title: '请选择年龄段', icon: 'none' });
|
||
return;
|
||
}
|
||
if (!form.region) {
|
||
wx.showToast({ title: '请选择所在地区', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
this.setData({ saving: true });
|
||
try {
|
||
const payload = {
|
||
nickname: String(form.nickname || '').trim(),
|
||
avatar: this.getRelativeUrl(form.avatar),
|
||
gender: Number(form.gender),
|
||
age_range: form.age_range,
|
||
ageRange: form.age_range,
|
||
region: form.region,
|
||
regionArray: Array.isArray(form.regionArray) ? form.regionArray : undefined
|
||
};
|
||
const res = await request({
|
||
url: '/api/users/profile',
|
||
method: 'PUT',
|
||
data: payload
|
||
});
|
||
const body = res.data || {};
|
||
const ok =
|
||
(typeof body.code === 'number' && body.code === 0) ||
|
||
(typeof body.success === 'boolean' && body.success === true);
|
||
if (!ok) throw new Error(body.message || body.error || '保存失败');
|
||
|
||
try {
|
||
const rewardRes = await request({
|
||
url: '/api/love-points/profile-complete',
|
||
method: 'POST',
|
||
data: {}
|
||
});
|
||
const rewardData = rewardRes.data || {};
|
||
const innerData = rewardData.data || {};
|
||
|
||
if (rewardData.success && (innerData.earned > 0 || innerData.alreadyClaimed)) {
|
||
if (innerData.earned > 0) {
|
||
wx.showToast({ title: rewardData.message || `获得 ${innerData.earned} 爱心值`, icon: 'success' });
|
||
} else {
|
||
wx.showToast({ title: '保存成功', icon: 'success' });
|
||
}
|
||
this.setData({ isProfileCompleted: true });
|
||
} else {
|
||
wx.showToast({ title: '保存成功', icon: 'success' });
|
||
}
|
||
} catch (_) {
|
||
wx.showToast({ title: '保存成功', icon: 'success' });
|
||
}
|
||
|
||
// CRITICAL: Refresh global user info to ensure avatar consistency
|
||
const app = getApp();
|
||
if (app && app.refreshUserInfo) {
|
||
app.refreshUserInfo();
|
||
}
|
||
|
||
this.setData({ originalAvatar: form.avatar || '' });
|
||
|
||
setTimeout(() => wx.navigateBack({ delta: 1 }), 500);
|
||
} catch (e) {
|
||
wx.showToast({ title: e.message || '保存失败', icon: 'none' });
|
||
} finally {
|
||
this.setData({ saving: false });
|
||
}
|
||
}
|
||
});
|