Files
ai_wht_wechat/miniprogram/miniprogram/pages/login/phone-login.ts
2026-01-07 22:55:12 +08:00

544 lines
16 KiB
TypeScript
Raw 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.

// pages/login/phone-login.ts
import { API } from '../../config/api';
import { EmployeeService } from '../../services/employee';
Page({
data: {
phone: '',
code: '',
password: '',
codePlaceholder: '请输入验证码',
codeButtonText: '获取验证码',
canGetCode: false,
canLogin: false,
countdown: 0,
countdownTimer: null as any,
showSuccess: false,
showLoading: false,
agreed: false,
countryCodes: ['+86', '+852', '+853', '+886', '+1', '+44', '+81', '+82'],
countryCodeIndex: 0,
loginType: 'code' // 'code' 或 'password'
},
onLoad() {
console.log('手机号登录页面加载');
},
onUnload() {
if (this.data.countdownTimer) {
clearInterval(this.data.countdownTimer);
}
},
// 区号选择
onCountryCodeChange(e: any) {
this.setData({
countryCodeIndex: e.detail.value
});
},
// 同意协议
onAgreeChange(e: any) {
this.setData({
agreed: e.detail.value.length > 0
});
},
// 跳转到用户协议
goToUserAgreement() {
wx.navigateTo({
url: '/pages/agreement/user-agreement/user-agreement'
});
},
// 跳转到隐私政策
goToPrivacyPolicy() {
wx.navigateTo({
url: '/pages/agreement/privacy-policy/privacy-policy'
});
},
// 返回上一页
goBack() {
wx.navigateBack({
delta: 1,
fail: () => {
wx.navigateTo({
url: '/pages/login/login'
});
}
});
},
// 显示更多菜单
showMore() {
wx.showActionSheet({
itemList: ['关于我们', '联系客服'],
success: (res) => {
if (res.tapIndex === 0) {
wx.showToast({ title: '功能开发中', icon: 'none' });
}
}
});
},
// 显示帮助
showHelp() {
wx.showToast({
title: '功能开发中',
icon: 'none'
});
},
// 手机号输入
onPhoneInput(e: any) {
const phone = e.detail.value;
this.setData({
phone: phone,
canGetCode: phone.length === 11
});
this.checkCanLogin();
},
// 验证码输入
onCodeInput(e: any) {
const code = e.detail.value;
this.setData({
code: code
});
this.checkCanLogin();
},
// 密码输入
onPasswordInput(e: any) {
const password = e.detail.value;
this.setData({
password: password
});
this.checkCanLogin();
},
// 切换登录方式
switchLoginType() {
const newType = this.data.loginType === 'code' ? 'password' : 'code';
this.setData({
loginType: newType,
code: '',
password: ''
});
},
// 检查是否可以登录
checkCanLogin() {
const { phone, code, password, loginType } = this.data;
if (loginType === 'code') {
this.setData({
canLogin: phone.length === 11 && code.length >= 4
});
} else {
this.setData({
canLogin: phone.length === 11 && password.length >= 6
});
}
},
// 获取验证码
async getVerifyCode() {
if (!this.data.agreed) {
wx.showToast({
title: '请先同意用户协议',
icon: 'none',
duration: 2000
});
return;
}
if (!this.data.canGetCode || this.data.countdown > 0) {
return;
}
const { phone } = this.data;
if (phone.length !== 11) {
wx.showToast({
title: '请输入正确的手机号',
icon: 'none',
duration: 2000
});
return;
}
try {
// 调用封装的Service方法发送验证码禁用loading验证码发送应立即响应
const res = await EmployeeService.sendXHSCode(phone, false);
// 兼容 code=0 和 code=200
if (res.code === 200 || res.code === 0) {
// 发送成功
wx.showToast({
title: '验证码已发送',
icon: 'success',
duration: 2000
});
// 开发环境打印验证码
if (res.data && res.data.code) {
console.log('验证码:', res.data.code);
}
// 开始倒计时
this.startCountdown();
} else {
// 发送失败
wx.showToast({
title: res.message || '发送失败,请稍后重试',
icon: 'none',
duration: 2000
});
}
} catch (err) {
console.error('发送验证码失败:', err);
wx.showToast({
title: '网络错误,请稍后重试',
icon: 'none',
duration: 2000
});
}
},
// 开始倒计时
startCountdown() {
let countdown = 180;
this.setData({
countdown: countdown,
codeButtonText: `${countdown}秒后重新获取`,
canGetCode: false
});
const timer = setInterval(() => {
countdown--;
if (countdown <= 0) {
clearInterval(timer);
this.setData({
countdown: 0,
codeButtonText: '获取验证码',
canGetCode: this.data.phone.length === 11,
countdownTimer: null
});
} else {
this.setData({
countdown: countdown,
codeButtonText: `${countdown}秒后重新获取`
});
}
}, 1000);
this.setData({
countdownTimer: timer
});
},
// 处理登录
handleLogin() {
if (!this.data.agreed) {
wx.showToast({
title: '请先同意用户协议',
icon: 'none',
duration: 2000
});
return;
}
if (!this.data.canLogin) {
return;
}
const { phone, code, password, loginType } = this.data;
// 显示加载提示
wx.showLoading({
title: '登录中...',
mask: true
});
// 调用后端API进行登录验证
if (loginType === 'code') {
// 验证码登录
wx.request({
url: `${API.baseURL}/api/login/xhs-phone-code`,
method: 'POST',
data: {
phone: phone,
code: code
},
success: async (res: any) => {
wx.hideLoading();
if (res.statusCode === 200 && res.data.code === 200) {
// 登录成功
const { token, employee } = res.data.data;
// 保存token和用户信息
wx.setStorageSync('token', token);
wx.setStorageSync('userInfo', employee);
wx.setStorageSync('employeeInfo', employee);
wx.setStorageSync('username', employee.name);
// 登录成功后立即获取并缓存绑定状态
try {
wx.request({
url: `${API.baseURL}/api/employee/profile`,
method: 'GET',
header: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
success: (profileResponse: any) => {
const profileData = profileResponse.data;
if (profileData.code === 200 && profileData.data) {
const userInfo = profileData.data;
const isBound = userInfo.is_bound_xhs === 1;
const hasCookie = userInfo.has_xhs_cookie === true;
// 更新本地绑定状态缓存
const bindings = wx.getStorageSync('socialBindings') || {};
if (isBound) {
bindings.xiaohongshu = {
phone: userInfo.xhs_phone,
xhs_account: userInfo.xhs_account,
bindTime: userInfo.bound_at || new Date().getTime(),
cookieExpired: !hasCookie
};
} else {
delete bindings.xiaohongshu;
}
wx.setStorageSync('socialBindings', bindings);
console.log('[验证码登录] 已缓存绑定状态:', bindings);
// 检查是否需要跳转到绑定页面
if (!isBound) {
// 新用户,未绑定小红书,跳转到绑定页面
this.setData({
showSuccess: true,
loginLoading: false
});
setTimeout(() => {
this.setData({ showSuccess: false });
wx.showModal({
title: '欢迎使用',
content: '首次登录需要绑定小红书账号,即将跳转到绑定页面',
showCancel: false,
confirmText: '去绑定',
success: (modalRes) => {
if (modalRes.confirm) {
wx.navigateTo({
url: '/pages/profile/platform-bind/platform-bind'
});
}
}
});
}, 1500);
} else {
// 老用户,已绑定,跳转到首页
this.setData({
showSuccess: true,
loginLoading: false
});
setTimeout(() => {
this.setData({ showSuccess: false });
wx.reLaunch({
url: '/pages/home/home'
});
}, 1500);
}
} else {
// 获取绑定状态失败,默认跳转首页
this.loginSuccessToHome();
}
},
fail: (profileError) => {
console.error('[验证码登录] 获取绑定状态失败:', profileError);
// 获取失败,默认跳转首页
this.loginSuccessToHome();
}
});
} catch (profileError) {
console.error('[验证码登录] 获取绑定状态异常:', profileError);
// 异常情况,默认跳转首页
this.loginSuccessToHome();
}
} else {
// 登录失败
wx.showToast({
title: res.data.message || '登录失败',
icon: 'none',
duration: 2000
});
}
},
fail: (err) => {
wx.hideLoading();
this.setData({ loginLoading: false });
console.error('验证码登录请求失败:', err);
wx.showToast({
title: '网络错误,请稍后重试',
icon: 'none',
duration: 2000
});
}
});
} else {
// 密码登录
wx.request({
url: `${API.baseURL}/api/login/phone-password`,
method: 'POST',
data: {
phone: phone,
password: password
},
success: async (res: any) => {
wx.hideLoading();
if (res.statusCode === 200 && res.data.code === 200) {
// 登录成功
const { token, employee } = res.data.data;
// 保存token和用户信息
wx.setStorageSync('token', token);
wx.setStorageSync('userInfo', employee);
wx.setStorageSync('employeeInfo', employee);
wx.setStorageSync('username', employee.name);
// 登录成功后立即获取并缓存绑定状态
try {
wx.request({
url: `${API.baseURL}/api/employee/profile`,
method: 'GET',
header: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
success: (profileResponse: any) => {
const profileData = profileResponse.data;
if (profileData.code === 200 && profileData.data) {
const userInfo = profileData.data;
const isBound = userInfo.is_bound_xhs === 1;
const hasCookie = userInfo.has_xhs_cookie === true;
// 更新本地绑定状态缓存
const bindings = wx.getStorageSync('socialBindings') || {};
if (isBound) {
bindings.xiaohongshu = {
phone: userInfo.xhs_phone,
xhs_account: userInfo.xhs_account,
bindTime: userInfo.bound_at || new Date().getTime(),
cookieExpired: !hasCookie
};
} else {
delete bindings.xiaohongshu;
}
wx.setStorageSync('socialBindings', bindings);
console.log('[密码登录] 已缓存绑定状态:', bindings);
// 检查是否需要跳转到绑定页面
if (!isBound) {
// 新用户,未绑定小红书,跳转到绑定页面
this.setData({
showSuccess: true,
loginLoading: false
});
setTimeout(() => {
this.setData({ showSuccess: false });
wx.showModal({
title: '欢迎使用',
content: '首次登录需要绑定小红书账号,即将跳转到绑定页面',
showCancel: false,
confirmText: '去绑定',
success: (modalRes) => {
if (modalRes.confirm) {
wx.navigateTo({
url: '/pages/profile/platform-bind/platform-bind'
});
}
}
});
}, 1500);
} else {
// 老用户,已绑定,跳转到首页
this.setData({
showSuccess: true,
loginLoading: false
});
setTimeout(() => {
this.setData({ showSuccess: false });
wx.reLaunch({
url: '/pages/home/home'
});
}, 1500);
}
} else {
// 获取绑定状态失败,默认跳转首页
this.loginSuccessToHome();
}
},
fail: (profileError) => {
console.error('[密码登录] 获取绑定状态失败:', profileError);
// 获取失败,默认跳转首页
this.loginSuccessToHome();
}
});
} catch (profileError) {
console.error('[密码登录] 获取绑定状态异常:', profileError);
// 异常情况,默认跳转首页
this.loginSuccessToHome();
}
} else {
// 登录失败
wx.showToast({
title: res.data.message || '登录失败',
icon: 'none',
duration: 2000
});
}
},
fail: (err) => {
wx.hideLoading();
this.setData({ loginLoading: false });
console.error('登录请求失败:', err);
wx.showToast({
title: '网络错误,请稍后重试',
icon: 'none',
duration: 2000
});
}
});
}
},
// 登录成功后跳转首页(备用方法)
loginSuccessToHome() {
this.setData({
showSuccess: true,
loginLoading: false
});
setTimeout(() => {
this.setData({ showSuccess: false });
wx.reLaunch({
url: '/pages/home/home'
});
}, 1500);
}
});