帝国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);

}

});

相关推荐
+VX:Fegn08951 天前
计算机毕业设计|基于springboot + vue物流配送中心信息化管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·小程序·课程设计
说私域1 天前
B站内容生态下的私域流量运营创新:基于AI智能名片链动2+1模式与S2B2C商城小程序的融合实践
人工智能·小程序·流量运营
计算机毕设指导61 天前
基于微信小程序的钓鱼论坛系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
qq_12498707531 天前
基于微信小程序的宠物交易平台的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·微信小程序·小程序·毕业设计·计算机毕业设计
kyh10033811201 天前
第二个微信小游戏《汉字碰碰消》上线啦!
微信·微信小程序·微信小游戏·去水印微信小程序·养了个羊
计算机毕设指导61 天前
基于微信小程序的精致护肤购物系统【源码文末联系】
java·spring boot·微信小程序·小程序·tomcat·maven·intellij-idea
myzshare2 天前
实战分享:我是如何用SSM框架开发出一个完整项目的
java·mysql·spring cloud·微信小程序
sheji34162 天前
【开题答辩全过程】以 基于微信小程序的在线学习系统为例,包含答辩的问题和答案
学习·微信小程序·小程序
头发还在的女程序员2 天前
小剧场短剧影视小程序源码分享,搭建自己的短剧小程序
人工智能·小程序·短剧·影视·微剧
是江迪呀2 天前
小程序上线半年我赚了多少钱?
微信小程序·产品·创业