544 lines
16 KiB
TypeScript
544 lines
16 KiB
TypeScript
// 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);
|
||
}
|
||
});
|