帝国cms 微信小程序的登录逻辑
// pages/member/login.js
Page({
/**
* 页面的初始数据
*/
data: {
isLoading: false,
returnUrl: '', // 存储返回的URL
needRegister: false,
showLoginBtn: false, // 控制登录按钮显示
showAgreementModal: false, // 控制协议弹窗显示
userInfo: {
avatar: '',
nickname: ''
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// 保存redirect参数(兼容旧版returnUrl)
const redirectUrl = options.redirect || options.returnUrl;
if (redirectUrl) {
this.setData({
returnUrl: decodeURIComponent(redirectUrl),
options: options // 保存所有选项参数
});
}
this.checkLoginStatus();
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
this.checkLoginStatus(); // 页面展示时重新检查登录状态
},
// 检查登录状态
checkLoginStatus() {
const token = wx.getStorageSync('token');
if (!token) {
console.log('用户未登录,显示登录页面');
this.setData({ showLoginBtn: true });
return;
}
// 先检查本地过期时间
const tokenExpire = wx.getStorageSync('tokenExpire');
if (tokenExpire > Date.now()) {
console.log('用户已登录,跳转到会员中心');
wx.redirectTo({
url: '/pages/index/index'
});
return;
}
// 本地token过期,调用接口验证
this.verifyTokenExpiry(token);
},
// 调用接口验证token是否过期
verifyTokenExpiry(token) {
wx.request({
url: 'https://www.ailu520.com/ecmsapi/index.php?mod=user&act=logintime',
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: { token },
success: (res) => {
if (res.data && res.data.code === 1) {
// token仍然有效,更新过期时间
const expireTime = Date.now() + 7 * 24 * 60 * 60 * 1000; // 7天有效期
wx.setStorageSync('tokenExpire', expireTime);
wx.redirectTo({
url: '/pages/index/index'
});
} else {
// token已过期,显示登录按钮
wx.removeStorageSync('token');
wx.removeStorageSync('tokenExpire');
this.setData({ showLoginBtn: true });
}
},
fail: () => {
// 网络错误,保守处理:显示登录按钮
this.setData({ showLoginBtn: true });
}
});
},
// 显示协议弹窗
showAgreementModal() {
this.setData({ showAgreementModal: true });
},
// 用户同意协议
handleAgree() {
this.setData({ showAgreementModal: false });
// 继续执行登录流程
this.doLogin();
},
// 用户拒绝协议
handleDisagree() {
this.setData({ showAgreementModal: false });
},
// 实际执行登录的方法
doLogin() {
this.setData({ isLoading: true });
wx.getUserProfile({
desc: '用于完善会员资料',
success: (profileRes) => {
// 获取用户信息成功后,开始微信登录流程
this.handleLogin(profileRes.userInfo);
},
fail: (err) => {
this.setData({ isLoading: false });
wx.showToast({
title: '获取用户信息失败',
icon: 'none'
});
console.error('获取用户信息失败:', err);
}
});
},
// 获取用户信息授权(点击触发)
handleUserProfile() {
// 先显示协议弹窗
this.showAgreementModal();
},
// 处理登录逻辑
handleLogin(userInfo) {
this.setData({ isLoading: true });
wx.login({
success: (res) => {
if (!res.code) {
this.handleLoginError('获取登录code失败', 'wxLogin');
return;
}
// 第一步:获取 openid 和 session_key
wx.request({
url: 'url=wxopenid',
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: {
wxCode: res.code
},
success: (openidRes) => {
console.log('获取 openid 成功', openidRes.data);
if (openidRes.data.code === 1) {
const { openid, unionid, session_key } = openidRes.data.data;
// 保存openid到本地存储,供后续使用
wx.setStorageSync('openid', openid);
// 第二步:发送用户信息登录
wx.request({
url: 'url=wxlogin',
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: {
wxopenid: openid,
unionid: unionid,
session_key: session_key,
nickname: userInfo.nickName,
avatar: userInfo.avatarUrl
},
success: (loginRes) => {
console.log('登录接口返回数据', loginRes.data);
if (loginRes.data && loginRes.data.code === 1) {
// 登录成功
const expireTime = Date.now() + 30 * 24 * 60 * 60 * 1000; // 30天有效期
wx.setStorageSync('token', loginRes.data.data.token);
wx.setStorageSync('tokenExpire', expireTime);
wx.setStorageSync('userInfo', loginRes.data.data);
this.setData({ isLoading: false });
wx.showToast({
title: '登录成功',
icon: 'success',
success: () => {
// 登录成功后跳转到returnUrl或首页
setTimeout(() => {
let targetUrl = this.data.returnUrl || '/pages/index/index';
if (targetUrl.startsWith('/')) {
// 解码URL参数
try {
targetUrl = decodeURIComponent(targetUrl);
} catch (e) {
console.warn('URL解码失败:', e);
}
// 检查是否有额外参数需要添加
const showComment = this.data.options?.showComment;
if (showComment && !targetUrl.includes('showComment=')) {
targetUrl += targetUrl.includes('?') ? '&' : '?';
targetUrl += 'showComment=true';
}
wx.redirectTo({
url: targetUrl
});
} else {
// 防止XSS攻击,只允许跳转小程序内部页面
wx.redirectTo({
url: '/pages/index/index'
});
}
}, 1500);
}
});
} else if (loginRes.data && loginRes.data.code === 0) {
// 用户不存在,触发注册流程
this.handleRegister(openid, unionid, session_key, userInfo);
} else {
this.handleLoginError(loginRes.data?.message || '登录失败', 'wxlogin');
}
},
fail: (err) => {
this.handleLoginError(`登录失败: ${err.errMsg || '网络请求异常'}`, 'wxlogin');
}
});
} else {
this.handleLoginError(openidRes.data?.message || '获取openid失败', 'wxopenid');
}
},
fail: (err) => {
this.handleLoginError(`获取openid失败: ${err.errMsg || '网络请求异常'}`, 'wxopenid');
}
});
},
fail: (err) => {
this.handleLoginError(`微信登录失败: ${err.errMsg || '未知错误'}`, 'wxLogin');
}
});
},
// 处理注册流程
handleRegister(openid, unionid, session_key, userInfo) {
// 设置用户信息到data中,供注册使用
this.setData({
needRegister: true,
'userInfo.nickname': userInfo.nickName || '',
'userInfo.avatar': userInfo.avatarUrl || this.data.userInfo.avatar
});
// 保存注册所需信息
this.registerInfo = {
openid: openid,
unionid: unionid,
session_key: session_key,
username: this.data.userInfo.nickname // 使用当前输入的昵称值
};
wx.showToast({
title: '请完善个人资料',
icon: 'none'
});
this.setData({ isLoading: false });
},
// 处理用户选择头像
onChooseAvatar(e) {
const { avatarUrl } = e.detail;
console.log('用户选择的头像:', avatarUrl);
// 检查是否有头像URL
if (!avatarUrl) {
wx.showToast({
title: '获取头像失败',
icon: 'none'
});
return;
}
// 先在界面上显示选择的头像
this.setData({
'userInfo.avatar': avatarUrl
});
// 判断是否是微信头像(通常以特定域名开头)
const isWechatAvatar = avatarUrl.indexOf('https://thirdwx.qlogo.cn/') !== -1;
if (isWechatAvatar) {
// 如果是微信头像,直接使用,不需要上传
console.log('使用微信头像,无需上传:', avatarUrl);
return;
}
// 如果不是微信头像,则需要上传到API接口
// 显示加载状态
wx.showLoading({
title: '处理头像中...',
mask: true
});
// 先下载临时文件到本地
wx.getImageInfo({
src: avatarUrl,
success: (imageInfo) => {
console.log('获取图片信息成功:', imageInfo);
// 使用获取到的本地路径上传
wx.uploadFile({
url: 'https://www.ailu520.com/ecmsapi/index.php?mod=user&act=uploaduserpic',
filePath: imageInfo.path,
name: 'file',
success: (res) => {
try {
const data = JSON.parse(res.data);
console.log('头像上传结果', data);
if (data.code === 1 && data.data && data.data.location) {
// 上传成功,使用返回的URL
const avatarUrl = data.data.location;
console.log('头像上传成功,URL:', avatarUrl);
this.setData({
'userInfo.avatar': avatarUrl
});
} else {
wx.showToast({
title: '头像上传失败',
icon: 'none'
});
console.error('头像上传失败:', data);
}
} catch (error) {
console.error('解析上传结果失败:', error, res.data);
wx.showToast({
title: '头像上传失败',
icon: 'none'
});
}
},
fail: (err) => {
console.error('头像上传请求失败:', err);
wx.showToast({
title: '头像上传失败',
icon: 'none'
});
},
complete: () => {
wx.hideLoading();
}
});
},
fail: (err) => {
console.error('获取图片信息失败:', err);
wx.hideLoading();
wx.showToast({
title: '处理头像失败',
icon: 'none'
});
}
});
},
// 昵称输入变化
onNicknameChange(e) {
if (e.currentTarget.dataset.type === 'nickname') {
this.setData({
'userInfo.nickname': e.detail.value
});
if (this.registerInfo) {
this.registerInfo.username = e.detail.value;
}
}
},
// 获取手机号
getPhoneNumber(e) {
if (!e.detail.code) {
wx.showToast({
title: '获取手机号失败',
icon: 'none'
});
return;
}
if (!this.registerInfo) {
wx.showToast({
title: '注册信息不完整',
icon: 'none'
});
return;
}
if (!this.data.userInfo.nickname) {
wx.showToast({
title: '请输入昵称',
icon: 'none'
});
return;
}
this.setData({ isLoading: true });
// 获取手机号
wx.request({
url: 'url=getphone',
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: {
code: e.detail.code,
openid: this.registerInfo.openid
},
success: (res) => {
if (res.data && res.data.code === 1 && res.data.data && res.data.data.phone) {
// 获取手机号成功,执行注册
this.doRegister(res.data.data.phone);
} else {
this.setData({ isLoading: false });
wx.showToast({
title: res.data?.message || '获取手机号失败',
icon: 'none'
});
}
},
fail: (err) => {
this.setData({ isLoading: false });
wx.showToast({
title: '获取手机号失败',
icon: 'none'
});
console.error('获取手机号失败:', err);
}
});
},
// 执行注册
doRegister(phone) {
if (!this.registerInfo || !this.data.userInfo.avatar || !this.data.userInfo.nickname) {
wx.showToast({
title: '请完善个人资料',
icon: 'none'
});
this.setData({ isLoading: false });
return;
}
wx.showLoading({
title: '正在注册',
mask: true
});
// 调用注册API
wx.request({
url: 'url=wreg',
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: {
username: this.data.userInfo.nickname,
wxopenid: this.registerInfo.openid,
unionid: this.registerInfo.unionid,
userpic: this.data.userInfo.avatar,
session_key: this.registerInfo.session_key,
phone: phone
},
success: (res) => {
wx.hideLoading();
if (res.data && res.data.code === 1) {
// 注册成功,保存token和用户信息(保持与登录一致的数据结构)
const expireTime = Date.now() + 30 * 24 * 60 * 60 * 1000; // 30天有效期
wx.setStorageSync('token', res.data.data.token);
wx.setStorageSync('tokenExpire', expireTime);
// 构建与登录保存一致的userInfo结构
const userInfo = {
userid: res.data.data.userid, // 统一使用userid作为字段名
openid: res.data.data.openid,
unionid: res.data.data.unionid,
nickname: this.data.userInfo.nickname,
avatar: this.data.userInfo.avatar,
phone: res.data.data.phone,
level: res.data.data.level || '普通会员',
// 其他与登录保存一致的字段...
};
wx.setStorageSync('userInfo', userInfo);
this.setData({ isLoading: false });
wx.showToast({
title: '注册成功',
icon: 'success',
success: () => {
// 注册成功后跳转到会员中心
setTimeout(() => {
wx.redirectTo({
url: '/pages/index/index'
});
}, 1500);
}
});
} else {
// 注册失败
this.setData({ isLoading: false });
wx.showToast({
title: res.data?.message || '注册失败',
icon: 'none'
});
}
},
fail: (err) => {
wx.hideLoading();
this.setData({ isLoading: false });
wx.showToast({
title: '注册失败,请重试',
icon: 'none'
});
console.error('注册请求失败:', err);
}
});
},
// 统一处理登录错误
handleLoginError(message, type) {
this.setData({ isLoading: false });
let detail = message;
if (type === 'wxlogin') {
detail += '\n请检查网络或稍后再试';
}
wx.showModal({
title: '提示',
content: detail,
confirmText: '重试',
cancelText: '取消',
success: (modalRes) => {
if (modalRes.confirm) {
setTimeout(() => {
this.handleUserProfile();
}, 1000);
}
}
});
console.error(`[登录错误][${type}]`, message);
}
});