ai-c/pages/edit-profile/edit-profile.js
2026-02-02 18:21:32 +08:00

324 lines
9.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 });
}
}
});