You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

678 lines
21 KiB

// pages/profile/index.js
Page({
data: {
userInfo: {},
userType: '',
userTags: [],
needPhoneAuth: false // 是否需要重新授权手机号
},
onLoad() {
this.loadUserInfo()
},
onShow() {
this.loadUserInfo()
// 更新自定义tabBar状态
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({
selected: 3
});
}
// 更新全局tab状态
const app = getApp();
app.updateCurrentTab('profile');
},
// 加载用户信息
loadUserInfo() {
console.log('开始加载用户信息')
const app = getApp()
// 从本地存储获取用户信息
const localUserInfo = wx.getStorageSync('userInfo') || {}
if (app.globalData.userInfo) {
this.setData({ userInfo: app.globalData.userInfo })
} else {
app.globalData.userInfo = localUserInfo
this.setData({
userInfo: localUserInfo,
needPhoneAuth: !localUserInfo.phoneNumber
})
}
// 加载用户类型和标签
const userId = wx.getStorageSync('userId')
const openid = wx.getStorageSync('openid')
console.log('加载用户信息 - userId:', userId, 'openid:', openid ? '已获取' : '未获取')
if (userId && openid) {
// 从服务器获取最新的用户信息,确保身份由数据库决定
this.refreshUserInfoFromServer(openid, userId)
// 确保users存储结构存在
let users = wx.getStorageSync('users')
if (!users) {
users = {}
wx.setStorageSync('users', users)
}
if (!users[userId]) {
users[userId] = { type: '' }
wx.setStorageSync('users', users)
}
// 先显示本地存储的用户类型,但会被服务器返回的最新值覆盖
const user = users[userId]
const currentType = this.formatUserType(user.type)
this.setData({ userType: currentType })
console.log('加载用户信息 - 当前本地存储的用户类型:', currentType)
// 先使用本地存储的用户类型更新标签,后续会被服务器返回的最新值覆盖
this.updateUserTags(userId, user.type)
}
},
// 更新用户标签
updateUserTags(userId, userType) {
// 确保tags存储结构存在
let tags = wx.getStorageSync('tags')
if (!tags) {
tags = {}
wx.setStorageSync('tags', tags)
}
if (!tags[userId]) {
tags[userId] = []
wx.setStorageSync('tags', tags)
}
const userTags = tags[userId] || []
console.log('加载用户信息 - 原始标签:', userTags)
// 使用indexOf替代includes以解决Babel兼容性问题
let firstCategoryTag = []
// 查找第一个偏好品类标签
for (let i = 0; i < userTags.length; i++) {
if (userTags[i].indexOf('偏好品类') !== -1) {
firstCategoryTag = [userTags[i]]
break
}
}
// 合并保留的标签
let filteredTags = [...firstCategoryTag]
// 始终根据当前用户类型显示对应的身份标签
if (userType && userType !== '') {
let identityLabel = 'identity:not_set'
switch (userType) {
case 'buyer': identityLabel = 'identity:buyer'; break
case 'seller': identityLabel = 'identity:seller'; break
case 'both': identityLabel = 'identity:buyer+seller'; break
}
filteredTags.push(identityLabel)
console.log('加载用户信息 - 根据当前用户类型显示身份标签:', identityLabel)
}
console.log('加载用户信息 - 过滤后的标签:', filteredTags)
this.setData({ userTags: filteredTags })
},
// 从服务器刷新用户信息并同步身份数据
refreshUserInfoFromServer(openid, userId) {
const API = require('../../utils/api.js')
API.getUserInfo(openid).then(res => {
console.log('从服务器获取用户信息成功:', res)
if (res.success && res.data) {
const serverUserInfo = res.data
// 更新本地用户信息
const app = getApp()
const updatedUserInfo = {
...app.globalData.userInfo,
...serverUserInfo
}
app.globalData.userInfo = updatedUserInfo
wx.setStorageSync('userInfo', updatedUserInfo)
this.setData({ userInfo: updatedUserInfo })
// 同步更新用户身份信息(当前身份由数据库决定)
if (serverUserInfo.type) {
this.syncUserTypeFromServer(userId, serverUserInfo.type)
}
console.log('用户信息已更新,昵称:', updatedUserInfo.nickName, '手机号:', updatedUserInfo.phoneNumber, '身份:', serverUserInfo.type)
}
}).catch(err => {
console.error('从服务器获取用户信息失败:', err)
// 如果getUserInfo失败,尝试使用validateUserLogin作为备选
API.validateUserLogin().then(res => {
console.log('使用validateUserLogin获取用户信息成功:', res)
if (res.success && res.data) {
const serverUserInfo = res.data
// 更新本地用户信息
const app = getApp()
const updatedUserInfo = {
...app.globalData.userInfo,
...serverUserInfo
}
app.globalData.userInfo = updatedUserInfo
wx.setStorageSync('userInfo', updatedUserInfo)
this.setData({ userInfo: updatedUserInfo })
// 同步更新用户身份信息(当前身份由数据库决定)
if (serverUserInfo.type) {
this.syncUserTypeFromServer(userId, serverUserInfo.type)
}
console.log('用户信息已更新(备选方案):', updatedUserInfo)
}
}).catch(validateErr => {
console.error('从服务器获取用户信息失败(包括备选方案):', validateErr)
// 如果服务器请求失败,继续使用本地缓存的信息
})
})
},
// 从服务器同步用户身份信息
syncUserTypeFromServer(userId, serverType) {
if (!userId || !serverType) {
console.error('同步用户身份信息失败: 参数不完整')
return
}
console.log('从服务器同步用户身份信息:', { userId, serverType })
// 更新本地存储的用户身份
let users = wx.getStorageSync('users') || {}
if (!users[userId]) {
users[userId] = {}
}
// 只有当服务器返回的身份与本地不同时才更新
if (users[userId].type !== serverType) {
users[userId].type = serverType
wx.setStorageSync('users', users)
// 更新全局用户类型
const app = getApp()
app.globalData.userType = serverType
// 更新页面显示的用户类型
this.setData({
userType: this.formatUserType(serverType)
})
console.log('用户身份已从服务器同步:', serverType)
} else {
console.log('用户身份与服务器一致,无需更新:', serverType)
}
// 更新用户标签
this.updateUserTags(userId, serverType)
},
// 格式化用户类型显示 - 直接返回数据库中的type字段值
formatUserType(type) {
return type || 'not_set'
},
// 设置为买家
setAsBuyer() {
this.switchUserType('buyer', 'buyer')
},
// 设置为卖家
setAsSeller() {
this.switchUserType('seller', 'seller')
},
// 切换用户类型的通用方法
switchUserType(newType, typeName) {
const userId = wx.getStorageSync('userId')
const openid = wx.getStorageSync('openid')
if (!userId || !openid) {
wx.navigateTo({ url: '/pages/index/index' })
return
}
// 显示操作中的提示
wx.showLoading({ title: 'Switching...' })
// 引入API服务
const API = require('../../utils/api.js')
// 使用API更新用户类型,确保与服务器同步
API.updateUserType(newType).then(res => {
console.log('用户类型更新成功:', res)
// 更新页面显示
const app = getApp()
this.setData({
userType: this.formatUserType(app.globalData.userType)
})
// 更新用户标签
this.updateUserTags(userId, app.globalData.userType)
wx.showToast({
title: `Switched to ${typeName}`,
icon: 'success',
duration: 2000
})
}).catch(err => {
console.error('用户类型更新失败:', err)
wx.showToast({
title: 'Failed to switch, please retry',
icon: 'none',
duration: 2000
})
}).finally(() => {
wx.hideLoading()
})
},
// 上传用户类型到服务器
uploadUserTypeToServer(openid, userId, userInfo, type) {
// 引入API服务
const API = require('../../utils/api.js')
// 构造上传数据
const uploadData = {
userId: userId,
openid: openid,
...userInfo,
type: type,
timestamp: Date.now()
}
// 调用API上传用户信息
API.uploadUserInfo(uploadData).then(res => {
console.log('用户类型更新成功:', res)
}).catch(err => {
console.error('用户类型更新失败:', err)
wx.showToast({
title: '身份更新失败,请重试',
icon: 'none',
duration: 2000
})
})
},
// 处理手机号授权结果
onPhoneNumberResult(e) {
console.log('手机号授权结果:', e)
// 首先检查用户是否拒绝授权
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
console.log('用户拒绝授权手机号')
wx.showToast({
title: '您已拒绝授权,操作已取消',
icon: 'none'
})
// 直接返回,取消所有后续操作
return
}
// 用户同意授权,继续执行后续操作
// 检查是否有openid,如果没有则先登录
const openid = wx.getStorageSync('openid')
if (!openid) {
console.log('未登录,执行登录流程')
// 显示登录loading提示
wx.showLoading({ title: '登录中...' })
// 调用微信登录接口
wx.login({
success: loginRes => {
if (loginRes.code) {
// 引入API服务
const API = require('../../utils/api.js')
// 获取openid
API.getOpenid(loginRes.code)
.then(openidRes => {
wx.hideLoading()
console.log('获取openid响应:', openidRes)
// 增强版响应处理逻辑,支持多种返回格式
let openid = null;
let userId = null;
let sessionKey = null;
// 优先从data字段获取数据
if (openidRes && openidRes.data && typeof openidRes.data === 'object') {
openid = openidRes.data.openid || openidRes.data.OpenID || null;
userId = openidRes.data.userId || openidRes.data.userid || null;
sessionKey = openidRes.data.session_key || openidRes.data.sessionKey || null;
}
// 如果data为空或不存在,尝试从响应对象直接获取
if (!openid && openidRes && typeof openidRes === 'object') {
console.warn('服务器返回格式可能不符合预期,data字段为空或不存在,但尝试从根对象提取信息:', openidRes);
openid = openidRes.openid || openidRes.OpenID || null;
userId = openidRes.userId || openidRes.userid || null;
sessionKey = openidRes.session_key || openidRes.sessionKey || null;
}
// 检查服务器状态信息
const isSuccess = openidRes && (openidRes.success === true || openidRes.code === 200);
if (openid) {
// 存储openid和session_key
wx.setStorageSync('openid', openid)
if (sessionKey) {
wx.setStorageSync('sessionKey', sessionKey)
}
// 如果有userId,也存储起来
if (userId) {
wx.setStorageSync('userId', userId)
}
console.log('获取openid成功并存储:', openid)
// 登录成功,显示提示并重新加载页面
wx.showToast({
title: '登录成功',
icon: 'none'
})
// 在登录成功后重新加载页面
wx.reLaunch({
url: '/pages/profile/index'
})
} else {
console.error('获取openid失败,响应数据:', openidRes)
wx.showToast({
title: '登录失败,请重试',
icon: 'none'
})
}
})
.catch(err => {
wx.hideLoading()
console.error('获取openid失败:', err)
wx.showToast({
title: '登录失败,请重试',
icon: 'none'
})
})
} else {
wx.hideLoading()
console.error('微信登录失败:', loginRes)
wx.showToast({
title: '登录失败,请重试',
icon: 'none'
})
}
},
fail: err => {
wx.hideLoading()
console.error('wx.login失败:', err)
wx.showToast({
title: '获取登录状态失败,操作已取消',
icon: 'none'
})
}
})
return
}
// 已登录且用户同意授权,获取加密数据
const phoneData = e.detail
wx.showLoading({ title: '获取手机号中...' })
// 引入API服务
const API = require('../../utils/api.js')
// 上传到服务器解密
API.uploadPhoneNumberData(phoneData)
.then(res => {
wx.hideLoading()
if (res.success) {
console.log('获取手机号结果:', res)
// 检查是否有手机号冲突
const hasPhoneConflict = res.phoneNumberConflict || false
const isNewPhone = res.isNewPhone || true
const phoneNumber = res.phoneNumber || null
// 如果有手机号冲突,直接提示用户
if (hasPhoneConflict) {
wx.showToast({
title: '手机号已被其他账号绑定,请更换账号后重试',
icon: 'none',
duration: 3000
})
} else if (phoneNumber) {
// 保存手机号到用户信息
const app = getApp()
const userInfo = app.globalData.userInfo || wx.getStorageSync('userInfo') || {}
userInfo.phoneNumber = phoneNumber
// 更新本地和全局用户信息
app.globalData.userInfo = userInfo
wx.setStorageSync('userInfo', userInfo)
// 获取userId
const userId = wx.getStorageSync('userId')
const users = wx.getStorageSync('users') || {}
const currentUserType = users[userId] && users[userId].type ? users[userId].type : ''
// 同时更新服务器用户信息
this.uploadUserInfoToServer(userInfo, userId, currentUserType)
// 更新页面状态
this.setData({
needPhoneAuth: false
})
// 重新加载用户信息以更新UI
this.loadUserInfo()
wx.showToast({
title: '手机号绑定成功',
icon: 'success'
})
} else {
console.error('获取手机号失败:', res)
wx.showToast({
title: '获取手机号失败',
icon: 'none'
})
}
}
})
.catch(err => {
wx.hideLoading()
console.error('获取手机号失败:', err)
wx.showToast({
title: '获取手机号失败',
icon: 'none'
})
})
},
// 上传用户信息到服务器
uploadUserInfoToServer(userInfo, userId, type) {
// 返回Promise以便调用者可以进行错误处理
return new Promise((resolve, reject) => {
try {
// 引入API服务
const API = require('../../utils/api.js')
// 获取openid
const openid = wx.getStorageSync('openid')
// 验证必要参数
if (!userId || !openid) {
const error = new Error('缺少必要的用户信息');
console.error('用户信息上传失败:', error);
reject(error);
return;
}
// 构造上传数据(包含所有必要字段,包括phoneNumber)
const uploadData = {
userId: userId,
openid: openid,
nickName: userInfo.nickName,
phoneNumber: userInfo.phoneNumber, // 添加phoneNumber字段,满足服务器要求
type: type,
timestamp: Date.now()
}
// 调用API上传用户信息
API.uploadUserInfo(uploadData).then(res => {
console.log('用户信息上传成功:', res)
resolve(res);
}).catch(err => {
console.error('用户信息上传失败:', err)
reject(err);
})
} catch (error) {
console.error('上传用户信息时发生异常:', error);
reject(error);
}
});
},
// 修改用户名称
onEditNickName() {
const currentName = this.data.userInfo.nickName || '未登录';
wx.showModal({
title: '修改用户名称',
editable: true,
placeholderText: '请输入新的名称最多10个字符',
confirmText: '确认',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
// 移除首尾空格并过滤多余空格
let newName = res.content.trim();
newName = newName.replace(/\s+/g, ' ');
// 验证昵称不能为空
if (!newName) {
wx.showToast({
title: '名称不能为空',
icon: 'none',
duration: 2000
});
return;
}
// 验证昵称长度
if (newName.length > 10) {
wx.showToast({
title: '名称长度不能超过10个字符',
icon: 'none',
duration: 2000
});
return;
}
// 检查名称是否变化
if (newName === currentName) {
wx.showToast({
title: '名称未变化',
icon: 'none',
duration: 2000
});
return;
}
// 显示加载提示
wx.showLoading({
title: '正在更新...',
mask: true
});
// 更新用户信息
this.updateNickName(newName).finally(() => {
// 无论成功失败,都隐藏加载提示
wx.hideLoading();
});
}
}
});
},
// 更新用户名称
updateNickName(newName) {
return new Promise((resolve, reject) => {
try {
// 更新本地和全局用户信息
const app = getApp();
const updatedUserInfo = {
...this.data.userInfo,
nickName: newName
};
// 保存到本地存储和全局状态
app.globalData.userInfo = updatedUserInfo;
wx.setStorageSync('userInfo', updatedUserInfo);
// 更新页面显示
this.setData({
userInfo: updatedUserInfo
});
// 更新服务器信息
const userId = wx.getStorageSync('userId');
const currentUserType = this.data.userType;
// 如果有用户ID,则上传到服务器
if (userId) {
// 使用Promise链处理上传
this.uploadUserInfoToServer(updatedUserInfo, userId, currentUserType)
.then(() => {
wx.showToast({
title: '名称修改成功',
icon: 'success',
duration: 2000
});
resolve();
})
.catch((err) => {
console.error('服务器同步失败,但本地已更新:', err);
// 即使服务器同步失败,本地也已成功更新
wx.showToast({
title: '本地更新成功,服务器同步稍后进行',
icon: 'none',
duration: 3000
});
resolve(); // 即使服务器失败,也视为成功,因为本地已经更新
});
} else {
// 没有用户ID,只更新本地
console.warn('没有用户ID,仅更新本地用户名称');
wx.showToast({
title: '名称修改成功',
icon: 'success',
duration: 2000
});
resolve();
}
} catch (error) {
console.error('更新用户名称失败:', error);
wx.showToast({
title: '更新失败,请稍后重试',
icon: 'none',
duration: 2000
});
reject(error);
}
});
},
})