680 lines
26 KiB
TypeScript
680 lines
26 KiB
TypeScript
// profile.ts (Copied from previous index.ts)
|
||
import { config } from '../../config';
|
||
import { remoteConfig } from '../../utils/remoteConfig';
|
||
|
||
// 获取应用实例
|
||
const app = getApp<IAppOption>()
|
||
|
||
Component({
|
||
data: {
|
||
motto: 'Hello World',
|
||
loginHint: config.loginHint,
|
||
userInfo: {
|
||
avatarUrl: config.defaultAvatarUrl,
|
||
nickName: '',
|
||
gender: 0, // 0:未知, 1:男, 2:女
|
||
country: '',
|
||
province: '',
|
||
city: '',
|
||
language: ''
|
||
},
|
||
openid: '',
|
||
unionid: '',
|
||
phoneNumber: '',
|
||
playerid: '',
|
||
verificationCode: '',
|
||
hasUserInfo: false,
|
||
authMode: config.authMode || 'oa', // 'oa' | 'mp'
|
||
isTestEnabled: config.testConfig && config.testConfig.enable,
|
||
canIUseGetUserProfile: wx.canIUse('getUserProfile'),
|
||
canIUseNicknameComp: wx.canIUse('input.type.nickname'),
|
||
},
|
||
pageLifetimes: {
|
||
show() {
|
||
// 检查是否有从公众号授权回来的数据
|
||
const oaUserInfo = wx.getStorageSync('oa_user_info');
|
||
if (oaUserInfo) {
|
||
console.log('检测到公众号授权数据:', oaUserInfo);
|
||
this.setData({
|
||
"userInfo.nickName": oaUserInfo.nickName,
|
||
"userInfo.avatarUrl": oaUserInfo.avatarUrl,
|
||
"userInfo.gender": oaUserInfo.gender,
|
||
"userInfo.country": oaUserInfo.country,
|
||
"userInfo.province": oaUserInfo.province,
|
||
"userInfo.city": oaUserInfo.city,
|
||
"userInfo.language": oaUserInfo.language,
|
||
// 如果公众号也返回了 unionid,可以更新
|
||
unionid: oaUserInfo.unionid || this.data.unionid
|
||
});
|
||
// 清除缓存,避免重复读取
|
||
wx.removeStorageSync('oa_user_info');
|
||
|
||
// 如果已经有手机号,说明是“先手机后头像”的流程,直接保存并进入
|
||
if (this.data.phoneNumber) {
|
||
this.saveUserInfoToBackend();
|
||
} else {
|
||
// 授权回来后,尝试登录游戏服务器获取信息
|
||
this.loginToServer();
|
||
}
|
||
}
|
||
}
|
||
},
|
||
lifetimes: {
|
||
attached() {
|
||
// 检查本地登录态
|
||
this.checkLocalSession();
|
||
}
|
||
},
|
||
methods: {
|
||
// 检查本地 Session
|
||
checkLocalSession() {
|
||
const session = wx.getStorageSync('USER_SESSION');
|
||
const now = Date.now();
|
||
// 默认 24 小时过期
|
||
const expirationHours = config.loginExpirationHours || 24;
|
||
const expirationTime = expirationHours * 60 * 60 * 1000;
|
||
|
||
if (session && session.timestamp && (now - session.timestamp < expirationTime)) {
|
||
console.log('恢复本地登录态');
|
||
this.setData({
|
||
userInfo: session.userInfo,
|
||
openid: session.openid,
|
||
unionid: session.unionid,
|
||
phoneNumber: session.phoneNumber,
|
||
playerid: session.playerid,
|
||
// 始终保持 hasUserInfo 为 false,以显示用户信息和操作按钮
|
||
hasUserInfo: false
|
||
});
|
||
|
||
// 恢复后,尝试静默刷新服务端状态(不阻塞 UI)
|
||
this.loginToServer();
|
||
} else {
|
||
console.log('本地登录态不存在或已过期');
|
||
wx.removeStorageSync('USER_SESSION');
|
||
// 页面加载时自动静默登录获取 OpenID,但不自动登录游戏服务器,等待用户点击登录按钮授权
|
||
this.performSilentLogin(false);
|
||
}
|
||
},
|
||
|
||
// 弹出设置菜单
|
||
onSettingsTap() {
|
||
wx.showActionSheet({
|
||
itemList: ['注销账号'],
|
||
itemColor: '#FF0000', // 红色显示注销
|
||
success: (res) => {
|
||
if (res.tapIndex === 0) {
|
||
this.handleLogout();
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
// 处理注销
|
||
handleLogout() {
|
||
wx.showModal({
|
||
title: '提示',
|
||
content: '确定要注销当前账号吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// 1. 清除本地存储
|
||
wx.removeStorageSync('USER_SESSION'); // 清除持久化会话
|
||
wx.removeStorageSync('oa_user_info'); // 清除可能的 OA 授权信息
|
||
|
||
// 2. 重置页面数据
|
||
this.setData({
|
||
userInfo: {
|
||
avatarUrl: config.defaultAvatarUrl,
|
||
nickName: '',
|
||
gender: 0,
|
||
country: '',
|
||
province: '',
|
||
city: '',
|
||
language: ''
|
||
},
|
||
openid: '',
|
||
unionid: '',
|
||
phoneNumber: '',
|
||
playerid: '',
|
||
verificationCode: '',
|
||
// 重置其他相关状态...
|
||
});
|
||
|
||
wx.showToast({
|
||
title: '已注销',
|
||
icon: 'success'
|
||
});
|
||
|
||
// 3. 重新执行静默登录以获取基础 OpenID (保持未登录状态)
|
||
this.performSilentLogin(false);
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
// 选择头像 (小程序原生)
|
||
onChooseAvatar(e: any) {
|
||
const { avatarUrl } = e.detail;
|
||
this.setData({
|
||
"userInfo.avatarUrl": avatarUrl
|
||
});
|
||
},
|
||
|
||
// 填写昵称 (小程序原生)
|
||
onNicknameChange(e: any) {
|
||
const nickName = e.detail.value;
|
||
this.setData({
|
||
"userInfo.nickName": nickName
|
||
});
|
||
},
|
||
|
||
// 跳转到公众号授权页面
|
||
goOfficialAccountAuth() {
|
||
// 如果是 mp 模式,或者测试模式下配置了 Mock UnionID,则跳过公众号授权,直接尝试登录
|
||
if (config.authMode === 'mp' || (config.testConfig && config.testConfig.enable && config.testConfig.mockUnionId)) {
|
||
console.log('跳过公众号授权 (模式: ' + config.authMode + ', 测试: ' + (config.testConfig && config.testConfig.enable) + ')');
|
||
this.loginToServer();
|
||
return;
|
||
}
|
||
|
||
wx.navigateTo({
|
||
url: '/pages/webview/webview'
|
||
});
|
||
},
|
||
// 事件处理函数
|
||
bindViewTap() {
|
||
wx.navigateTo({
|
||
url: '../logs/logs',
|
||
})
|
||
},
|
||
|
||
// 静默登录逻辑
|
||
performSilentLogin(autoLoginGameServer: boolean = true) {
|
||
wx.login({
|
||
success: (loginRes) => {
|
||
if (loginRes.code) {
|
||
console.log('静默登录 code:', loginRes.code);
|
||
|
||
// 请求本地后端
|
||
wx.request({
|
||
url: `${config.baseUrl}/api/login`,
|
||
method: 'POST',
|
||
data: { code: loginRes.code },
|
||
success: (res: any) => {
|
||
if (res.data.error) {
|
||
console.error('静默登录失败:', res.data.error);
|
||
return;
|
||
}
|
||
|
||
this.setData({
|
||
openid: res.data.openid,
|
||
unionid: res.data.unionid || '未获取到UnionID'
|
||
});
|
||
console.log('OpenID 静默获取成功',res.data);
|
||
|
||
// 获取到 openid/unionid 后,尝试登录游戏服务器获取玩家信息
|
||
if (autoLoginGameServer) {
|
||
this.loginToServer();
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
console.error('静默登录连接失败:', err);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
// 登录游戏服务器
|
||
loginToServer() {
|
||
// 检查远程配置是否就绪
|
||
if (!remoteConfig.isReady()) {
|
||
console.log('RemoteConfig not ready, waiting...');
|
||
wx.showLoading({ title: '加载配置中...', mask: true });
|
||
|
||
let hasHandled = false;
|
||
remoteConfig.onUpdate(() => {
|
||
if (!hasHandled && remoteConfig.isReady()) {
|
||
hasHandled = true;
|
||
wx.hideLoading();
|
||
this.loginToServer();
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
|
||
const { openid, unionid, userInfo } = this.data;
|
||
if (!openid) return;
|
||
|
||
// --- 测试配置注入 ---
|
||
let finalUnionId = unionid;
|
||
if (config.testConfig && config.testConfig.enable && config.testConfig.mockUnionId) {
|
||
console.log('[Test] Using Mock UnionID in loginToServer:', config.testConfig.mockUnionId);
|
||
finalUnionId = config.testConfig.mockUnionId;
|
||
}
|
||
// -------------------
|
||
|
||
// 获取版本号
|
||
const { agentid, gameid, channelid, marketid } = config.remoteConfig;
|
||
const version = remoteConfig.getParaValue("game_version", agentid, gameid, channelid, marketid);
|
||
console.log("game_version",version);
|
||
wx.request({
|
||
url: `${config.baseUrl}/api/playerLogin`,
|
||
method: 'POST',
|
||
data: {
|
||
openid,
|
||
unionid: finalUnionId,
|
||
nickName: userInfo.nickName,
|
||
avatarUrl: userInfo.avatarUrl,
|
||
gender: userInfo.gender,
|
||
province: userInfo.province,
|
||
city: userInfo.city,
|
||
version: version || 1 // 默认版本号 1
|
||
},
|
||
success: (res: any) => {
|
||
this.handleLoginSuccess(res);
|
||
},
|
||
fail: (err) => {
|
||
console.error('游戏服务器登录失败:', err);
|
||
wx.showToast({ title: '连接服务器失败', icon: 'none' });
|
||
}
|
||
});
|
||
},
|
||
|
||
// 测试登录(带手机号和验证码)
|
||
testLoginWithPhone() {
|
||
const { openid, unionid, userInfo, phoneNumber, verificationCode } = this.data;
|
||
if (!openid) {
|
||
wx.showToast({ title: '未获取OpenID', icon: 'none' });
|
||
return;
|
||
}
|
||
if (!phoneNumber) {
|
||
wx.showToast({ title: '未获取手机号', icon: 'none' });
|
||
return;
|
||
}
|
||
if (!verificationCode) {
|
||
wx.showToast({ title: '未生成随机数', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
// --- 测试配置注入 ---
|
||
let finalUnionId = unionid;
|
||
if (config.testConfig && config.testConfig.enable && config.testConfig.mockUnionId) {
|
||
finalUnionId = config.testConfig.mockUnionId;
|
||
}
|
||
// -------------------
|
||
|
||
const { agentid, gameid, channelid, marketid } = config.remoteConfig;
|
||
const version = remoteConfig.getParaValue("game_version", agentid, gameid, channelid, marketid);
|
||
|
||
wx.showLoading({ title: '测试登录中...' });
|
||
wx.request({
|
||
url: `${config.baseUrl}/api/playerLogin`,
|
||
method: 'POST',
|
||
// data: {
|
||
// openid,
|
||
// unionid: finalUnionId,
|
||
// nickName: userInfo.nickName,
|
||
// avatarUrl: userInfo.avatarUrl,
|
||
// gender: userInfo.gender,
|
||
// province: userInfo.province,
|
||
// city: userInfo.city,
|
||
// version: version || 1,
|
||
// phoneNumber: phoneNumber,
|
||
// verificationCode: verificationCode
|
||
// },
|
||
data: {
|
||
openid:"onJdG10JeHtS0Dbz8FtdVv7aeVB6",
|
||
unionid: "oLVKis6bj3_l8qspMybG60KV2GN6",
|
||
nickName: "testname",
|
||
avatarUrl: "testavatarurl",
|
||
gender: 3,
|
||
province: "testprovince",
|
||
city: "testcity",
|
||
version: version || 1,
|
||
phoneNumber: phoneNumber,
|
||
verificationCode: 11111,
|
||
telphoneAuto:true,
|
||
playerid:710873
|
||
},
|
||
success: (res: any) => {
|
||
wx.hideLoading();
|
||
console.log('测试登录返回:', res.data);
|
||
this.handleLoginSuccess(res);
|
||
wx.showToast({ title: '测试登录请求已发送', icon: 'none' });
|
||
},
|
||
fail: (err) => {
|
||
wx.hideLoading();
|
||
console.error('测试登录失败:', err);
|
||
wx.showToast({ title: '测试登录失败', icon: 'none' });
|
||
}
|
||
});
|
||
},
|
||
|
||
handleLoginSuccess(res: any) {
|
||
console.log('游戏服务器登录返回:', res.data);
|
||
// res.data 是 wxserver 返回的 { success, message, data }
|
||
// res.data.data 是游戏服务器返回的原始包 { rpc, data }
|
||
const packet = res.data;
|
||
|
||
if (packet) {
|
||
// 1. 处理异常 RPC (show_message, kick_server)
|
||
if (packet.rpc === 'show_message' || packet.rpc === 'kick_server') {
|
||
const msg = (packet.data && packet.data.msg) || '未知错误';
|
||
wx.showToast({
|
||
title: msg,
|
||
icon: 'none',
|
||
duration: 3000
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 2. 处理业务错误
|
||
if (packet.data && packet.data.error) {
|
||
wx.showToast({
|
||
title: packet.data.error,
|
||
icon: 'none',
|
||
duration: 3000
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 3. 处理登录成功
|
||
const gameData = packet.data;
|
||
if (gameData && (gameData.playerid || gameData.state === 0)) {
|
||
// 兼容不同的字段名
|
||
const serverNickName = gameData.nickname || gameData.nickName;
|
||
const serverAvatarUrl = gameData.avatar || gameData.headimg || gameData.headimgurl || gameData.avatarUrl;
|
||
const serverGender = gameData.sex || gameData.gender;
|
||
|
||
const newUserInfo = {
|
||
...this.data.userInfo,
|
||
nickName: serverNickName || this.data.userInfo.nickName,
|
||
avatarUrl: serverAvatarUrl || this.data.userInfo.avatarUrl,
|
||
gender: serverGender !== undefined ? serverGender : this.data.userInfo.gender
|
||
};
|
||
|
||
this.setData({
|
||
userInfo: newUserInfo,
|
||
playerid: gameData.playerid || '',
|
||
phoneNumber: gameData.tel || ''
|
||
});
|
||
|
||
// 更新本地缓存
|
||
wx.setStorageSync('USER_SESSION', {
|
||
timestamp: Date.now(),
|
||
userInfo: newUserInfo,
|
||
openid: this.data.openid,
|
||
unionid: this.data.unionid,
|
||
phoneNumber: gameData.tel || '',
|
||
playerid: gameData.playerid || ''
|
||
});
|
||
}
|
||
}
|
||
},
|
||
|
||
// 获取验证码
|
||
getVerificationCode() {
|
||
// if (this.data.isCountingDown) return;
|
||
|
||
const { phoneNumber } = this.data;
|
||
if (!phoneNumber) {
|
||
wx.showToast({ title: '请先绑定手机号', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
wx.showLoading({ title: '获取中...' });
|
||
wx.request({
|
||
url: `${config.baseUrl}/api/getPhoneCode`,
|
||
method: 'POST',
|
||
data: { phonenum: phoneNumber },
|
||
success: (res: any) => {
|
||
wx.hideLoading();
|
||
console.log('验证码返回:', res.data);
|
||
const smmcode = res.data && res.data.data && res.data.data.smmcode;
|
||
if (smmcode) {
|
||
this.setData({ verificationCode: smmcode });
|
||
wx.showToast({ title: '获取成功', icon: 'success' });
|
||
} else {
|
||
wx.showToast({ title: '获取失败', icon: 'none' });
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
wx.hideLoading();
|
||
console.error('获取验证码请求失败:', err);
|
||
wx.showToast({ title: '网络错误', icon: 'none' });
|
||
}
|
||
});
|
||
},
|
||
|
||
// 复制验证码
|
||
copyVerificationCode() {
|
||
const { verificationCode } = this.data;
|
||
if (!verificationCode) return;
|
||
|
||
wx.setClipboardData({
|
||
data: String(verificationCode),
|
||
success: () => {
|
||
wx.showToast({ title: '复制成功', icon: 'success' });
|
||
}
|
||
});
|
||
},
|
||
|
||
getPhoneNumber(e: any) {
|
||
// const { avatarUrl, nickName } = this.data.userInfo;
|
||
const { openid } = this.data;
|
||
|
||
// 1. 检查 OpenID 是否已获取
|
||
if (!openid) {
|
||
wx.showToast({ title: '正在初始化...', icon: 'none' });
|
||
// 尝试重新登录
|
||
this.performSilentLogin();
|
||
return;
|
||
}
|
||
|
||
// 2. 获取手机号
|
||
if (e.detail.errMsg === "getPhoneNumber:ok" || e.detail.errMsg.includes("ok")) {
|
||
|
||
// --- 测试配置:Mock 手机号 ---
|
||
// 原因:微信小程序获取手机号接口收费。在测试阶段,如果配置了 mockPhoneNumber,
|
||
// 则直接使用模拟数据,跳过后端请求,从而避免产生费用。
|
||
if (config.testConfig && config.testConfig.enable && config.testConfig.mockPhoneNumber) {
|
||
console.log('[Test] Using Mock PhoneNumber directly:', config.testConfig.mockPhoneNumber);
|
||
this.handlePhoneNumberSuccess(config.testConfig.mockPhoneNumber);
|
||
return;
|
||
}
|
||
// ---------------------------
|
||
|
||
const code = e.detail.code; // 动态令牌
|
||
|
||
wx.showLoading({ title: '获取手机号...' });
|
||
|
||
// 请求本地后端获取手机号
|
||
wx.request({
|
||
url: `${config.baseUrl}/api/getPhoneNumber`,
|
||
method: 'POST',
|
||
data: { code: code },
|
||
success: (res: any) => {
|
||
wx.hideLoading();
|
||
console.log('后端返回:', res.data);
|
||
|
||
if (res.data.phoneNumber) {
|
||
this.handlePhoneNumberSuccess(res.data.phoneNumber);
|
||
} else {
|
||
wx.showToast({ title: '获取失败: ' + (res.data.error || '未知错误'), icon: 'none' });
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
wx.hideLoading();
|
||
console.error('请求后端接口失败:', err);
|
||
wx.showToast({ title: '连接服务器失败', icon: 'none' });
|
||
}
|
||
});
|
||
|
||
} else {
|
||
console.error(e.detail);
|
||
wx.showModal({
|
||
title: '获取失败',
|
||
content: '用户拒绝授权或账号无权限。',
|
||
showCancel: false
|
||
})
|
||
}
|
||
},
|
||
|
||
// 抽离处理手机号成功的逻辑
|
||
handlePhoneNumberSuccess(phoneNumber: string) {
|
||
this.setData({
|
||
phoneNumber: phoneNumber
|
||
});
|
||
|
||
// 3. 检查是否需要同步头像或获取真实UnionID
|
||
// 如果没有昵称、头像是默认的,或者没有有效的UnionID,自动跳转去同步
|
||
const hasValidUnionId = this.data.unionid && this.data.unionid !== '未获取到UnionID';
|
||
// 在 mp 模式下,我们不强制检查 unionid,因为 chooseAvatar 不会返回 unionid
|
||
// 但如果用户需要 unionid,可能需要其他方式。这里主要关注头像昵称。
|
||
const isInfoMissing = !this.data.userInfo.nickName ||
|
||
this.data.userInfo.avatarUrl === config.defaultAvatarUrl ||
|
||
(this.data.authMode === 'oa' && !hasValidUnionId);
|
||
|
||
if (isInfoMissing) {
|
||
if (this.data.authMode === 'oa') {
|
||
wx.showToast({ title: '正在同步完善信息...', icon: 'none', duration: 1500 });
|
||
setTimeout(() => {
|
||
this.goOfficialAccountAuth();
|
||
}, 1500);
|
||
} else {
|
||
// mp 模式,提示用户手动填写
|
||
wx.showToast({ title: '请完善头像和昵称', icon: 'none' });
|
||
}
|
||
} else {
|
||
// 已经有头像了,直接保存
|
||
this.saveUserInfoToBackend();
|
||
wx.showToast({ title: '登录成功' });
|
||
}
|
||
},
|
||
|
||
saveUserInfoToBackend() {
|
||
const { userInfo, openid, unionid, phoneNumber } = this.data;
|
||
|
||
// --- 测试配置注入 ---
|
||
let finalUnionId = unionid;
|
||
let finalPhoneNumber = phoneNumber;
|
||
|
||
if (config.testConfig && config.testConfig.enable) {
|
||
if (config.testConfig.mockUnionId) {
|
||
console.log('[Test] Using Mock UnionID:', config.testConfig.mockUnionId);
|
||
finalUnionId = config.testConfig.mockUnionId;
|
||
}
|
||
if (config.testConfig.mockPhoneNumber) {
|
||
console.log('[Test] Using Mock PhoneNumber:', config.testConfig.mockPhoneNumber);
|
||
finalPhoneNumber = config.testConfig.mockPhoneNumber;
|
||
}
|
||
}
|
||
// -------------------
|
||
|
||
const save = (finalAvatarUrl: string) => {
|
||
wx.request({
|
||
url: `${config.baseUrl}/api/saveUserInfo`,
|
||
method: 'POST',
|
||
data: {
|
||
...userInfo, // 包含 nickName, gender, country, province, city, language 等所有字段
|
||
avatarUrl: finalAvatarUrl, // 覆盖可能为临时路径的 avatarUrl
|
||
openid,
|
||
unionid: finalUnionId,
|
||
phoneNumber: finalPhoneNumber
|
||
},
|
||
success: (res: any) => {
|
||
console.log('用户信息保存成功:', res.data);
|
||
|
||
const serverData = res.data;
|
||
|
||
// 如果游戏服务器明确返回 result: -1 (例如手机号已存在),则阻止跳转
|
||
// wxserver 返回结构: { success: boolean, message: string, data: { data: { result: number, msg: string } } }
|
||
// 兼容直接返回的情况
|
||
const gamePacket = serverData.data;
|
||
const gameResult = (gamePacket && gamePacket.data && gamePacket.data.result !== undefined) ? gamePacket.data.result : ((gamePacket && gamePacket.result !== undefined) ? gamePacket.result : serverData.result);
|
||
|
||
if (serverData.success === false || gameResult === -1) {
|
||
// 优先显示 serverData.data.message,其次是 msg
|
||
const errorMsg = serverData.message || (gamePacket && gamePacket.data && gamePacket.data.msg) || (gamePacket && gamePacket.msg) || '操作失败';
|
||
wx.showToast({
|
||
title: errorMsg,
|
||
icon: 'none',
|
||
duration: 4000
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 优先取游戏服务器返回的 msg (在 data.data.msg 中),其次取 wxserver 的 message
|
||
const displayMsg = (gamePacket && gamePacket.data && gamePacket.data.msg) || (gamePacket && gamePacket.msg) || serverData.message;
|
||
|
||
if (displayMsg) {
|
||
wx.showToast({
|
||
title: displayMsg,
|
||
icon: 'none',
|
||
duration: 5000
|
||
});
|
||
}
|
||
|
||
// 保存到本地缓存
|
||
wx.setStorageSync('USER_SESSION', {
|
||
timestamp: Date.now(),
|
||
userInfo: this.data.userInfo,
|
||
openid: this.data.openid,
|
||
unionid: this.data.unionid,
|
||
phoneNumber: this.data.phoneNumber,
|
||
playerid: this.data.playerid
|
||
});
|
||
},
|
||
fail: (err) => {
|
||
console.error('保存用户信息失败:', err);
|
||
}
|
||
});
|
||
};
|
||
|
||
// 检查是否需要上传头像 (如果是临时路径)
|
||
// 只有在开启了上传配置,且头像是临时路径时才上传
|
||
const shouldUpload = config.enableAvatarUpload &&
|
||
userInfo.avatarUrl &&
|
||
(userInfo.avatarUrl.startsWith('http://tmp') || userInfo.avatarUrl.startsWith('wxfile://'));
|
||
|
||
if (shouldUpload) {
|
||
wx.showLoading({ title: '上传头像中...' });
|
||
wx.uploadFile({
|
||
url: `${config.baseUrl}/api/upload`,
|
||
filePath: userInfo.avatarUrl,
|
||
name: 'file',
|
||
formData: {
|
||
unionid: finalUnionId || openid // 优先使用 unionid,如果没有则使用 openid
|
||
},
|
||
success: (res) => {
|
||
wx.hideLoading();
|
||
try {
|
||
const data = JSON.parse(res.data);
|
||
if (data.url) {
|
||
console.log('头像上传成功:', data.url);
|
||
save(data.url);
|
||
} else {
|
||
console.error('头像上传响应异常:', data);
|
||
// 降级处理:上传失败也尝试保存,虽然头像链接可能无效
|
||
save(userInfo.avatarUrl);
|
||
}
|
||
} catch (e) {
|
||
console.error('解析上传响应失败:', e);
|
||
save(userInfo.avatarUrl);
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
wx.hideLoading();
|
||
console.error('头像上传失败:', err);
|
||
save(userInfo.avatarUrl);
|
||
}
|
||
});
|
||
} else {
|
||
// 已经是网络链接或默认头像,直接保存
|
||
save(userInfo.avatarUrl);
|
||
}
|
||
},
|
||
},
|
||
})
|