Files
WXProgram/miniprogram/pages/index/modules/loginModule.ts

485 lines
14 KiB
TypeScript
Raw Normal View History

2025-10-16 21:32:16 +08:00
// 登录模块 - 处理用户登录、授权、用户信息管理
import { showToast } from '../../../utils/helpers';
import { UserInfo } from '../../../types';
import userService from '../../../services/userService';
import locationTrackingService from '../../../services/locationTrackingService';
import { DataModule } from './dataModule';
export class LoginModule {
private dataModule: DataModule;
private pageContext: any;
constructor(pageContext: any, dataModule: DataModule) {
this.pageContext = pageContext;
this.dataModule = dataModule;
}
/**
*
*/
public async processUserInfo(userInfo: UserInfo): Promise<UserInfo> {
// 直接返回用户信息,不进行额外处理
return userInfo;
}
/**
*
*/
public updatePageAfterLogin(userInfo: UserInfo): void {
this.dataModule.updateUserInfo(userInfo);
}
/**
*
*/
public checkLoginStatus(): boolean {
const globalUserInfo = userService.getGlobalUserInfo();
if (globalUserInfo) {
this.dataModule.updateUserInfo(globalUserInfo);
return true;
}
return false;
}
/**
* 退
*/
public async logout(): Promise<void> {
try {
// 停止位置追踪服务
try {
await locationTrackingService.stopTracking();
console.log('位置追踪服务已停止');
} catch (trackingError) {
console.warn('停止位置追踪失败,但不影响退出登录:', trackingError);
}
// 注意这里不调用userService.logout()因为服务器端的logout接口会删除token
// 而用户只是签退不接单不是完全退出应用需要保持token有效
console.log('用户已退出登录本地签退保持token有效');
showToast('已退出登录');
} catch (error) {
console.error('退出登录失败:', error);
}
}
/**
*
*/
public async showManualLoginModal(): Promise<boolean> {
console.log('显示手动登录模态框');
return new Promise((resolve) => {
wx.showModal({
title: '手动登录',
content: '静默登录失败,请手动登录以使用完整功能',
confirmText: '手动登录',
cancelText: '暂不',
success: async (res) => {
if (res.confirm) {
// 用户点击确定,执行手动登录
console.log('用户选择手动登录');
const success = await this.performLogin();
if (!success) {
// 登录失败,再次提供选项
this.handleLoginFailure(resolve);
} else {
resolve(success);
}
} else {
// 用户取消登录,显示关闭小程序选项
console.log('用户选择暂不登录');
this.showCloseAppOption(resolve);
}
}
});
});
}
/**
* - userService的登录方法
*
*/
private async performLogin(): Promise<boolean> {
try {
// 执行微信登录
const result = await userService.wxLogin();
if (result.success && result.userInfo) {
// 登录成功,更新页面状态
this.updatePageAfterLogin(result.userInfo);
console.log('手动登录成功');
return true;
}
console.log('手动登录失败');
return false;
} catch (error) {
console.error('执行登录流程失败:', error);
return false;
}
}
/**
*
*/
public async handleLoginFailure(resolve: (value: boolean) => void) {
console.log('登录失败,显示重试选项');
wx.showModal({
title: '登录失败',
content: '登录遇到问题,是否重试?',
confirmText: '重新登录',
cancelText: '取消并关闭',
success: async (res) => {
if (res.confirm) {
console.log('用户选择重新登录');
const success = await this.performLogin();
if (!success) {
// 再次登录失败,递归调用以避免嵌套过深
this.handleLoginFailure(resolve);
} else {
resolve(success);
}
} else {
console.log('用户选择取消并关闭小程序');
wx.showToast({
title: '即将退出小程序',
icon: 'none',
duration: 1500,
complete: () => {
setTimeout(() => {
// 使用类型断言解决类型问题
(wx as any).exitMiniProgram();
}, 1500);
}
});
resolve(false);
}
}
});
}
/**
*
*/
public showCloseAppOption(resolve: (value: boolean) => void) {
console.log('显示关闭小程序选项');
wx.showModal({
title: '确认退出',
content: '不登录将无法使用完整功能,是否退出小程序?',
confirmText: '退出小程序',
cancelText: '留在页面',
success: (res) => {
if (res.confirm) {
console.log('用户确认退出小程序');
// 使用类型断言解决类型问题
(wx as any).exitMiniProgram();
resolve(false);
} else {
console.log('用户选择留在页面');
resolve(false);
}
}
});
}
2025-10-19 23:38:54 +08:00
/**
* 退
*/
public async handleSignOut(): Promise<boolean> {
try {
// 显示加载中提示
wx.showLoading({
title: '签退中...',
});
// 调用签退接口
const signOutResult = await userService.signOut();
wx.hideLoading();
if (signOutResult.success) {
console.log('签退成功:', signOutResult);
wx.showToast({
title: '签退成功',
icon: 'success',
duration: 2000
});
// 停止位置追踪服务
try {
await locationTrackingService.stopTracking();
console.log('位置追踪服务已停止');
} catch (trackingError) {
console.warn('停止位置追踪失败,但不影响签退:', trackingError);
}
// 设置用户状态为已签退
if (this.pageContext && this.pageContext.setData) {
this.pageContext.setData({
'authStatus.userStatus': 'signed_out'
});
// 更新按钮显示状态
if (this.pageContext.updateButtonDisplayStatus) {
this.pageContext.updateButtonDisplayStatus();
}
}
return true;
} else {
console.warn('签退失败:', signOutResult.message);
wx.showToast({
title: signOutResult.message || '签退失败',
icon: 'none',
duration: 2000
});
return false;
}
} catch (error) {
console.error('签退过程中发生错误:', error);
wx.hideLoading();
wx.showToast({
title: '签退失败,请重试',
icon: 'none',
duration: 2000
});
return false;
}
}
2025-10-16 21:32:16 +08:00
/**
*
*/
public async handleSignIn(): Promise<boolean> {
try {
// 显示加载中提示
wx.showLoading({
title: '签到中...',
});
2025-10-19 13:40:20 +08:00
// 先获取地图位置和当前时间
let initialLocation: { latitude: number; longitude: number; timestamp: number };
try {
const location = await locationTrackingService.getCurrentLocation();
// 使用秒级时间戳除以1000取整
initialLocation = {
latitude: location.latitude,
longitude: location.longitude,
timestamp: Math.floor(Date.now() / 1000)
};
console.log('获取到签到位置数据:', initialLocation);
} catch (error) {
console.error('获取位置失败:', error);
throw new Error('获取位置失败,请检查位置权限设置');
}
// 调用实际的签到接口,传递位置数据
const signInResult = await userService.signIn(initialLocation);
2025-10-16 21:32:16 +08:00
wx.hideLoading();
if (signInResult.success) {
console.log('签到成功:', signInResult);
wx.showToast({
title: '签到成功',
icon: 'success',
duration: 2000
});
// 更新用户信息
if (signInResult.employeeInfo) {
// 将员工信息合并到用户信息中
const app = getApp<any>();
if (app.globalData.userInfo) {
app.globalData.userInfo = {
...app.globalData.userInfo,
name: signInResult.employeeInfo.name,
phone: signInResult.employeeInfo.phone
};
this.updatePageAfterLogin(app.globalData.userInfo);
}
}
// 设置用户状态为已签到
if (this.pageContext && this.pageContext.setData) {
this.pageContext.setData({
'authStatus.userStatus': 'signed_in'
});
// 更新按钮显示状态
if (this.pageContext.updateButtonDisplayStatus) {
this.pageContext.updateButtonDisplayStatus();
}
}
2025-10-19 23:38:54 +08:00
// 启动位置追踪服务WebSocket连接
2025-10-16 21:32:16 +08:00
try {
2025-10-19 23:38:54 +08:00
// 启动位置追踪服务建立WebSocket连接
await locationTrackingService.startTracking();
2025-10-16 21:32:16 +08:00
console.log('位置追踪服务已启动');
} catch (trackingError) {
console.warn('启动位置追踪失败,但不影响签到:', trackingError);
}
return true;
} else {
console.warn('签到失败:', signInResult.message);
wx.showToast({
title: signInResult.message || '签到失败',
icon: 'none',
duration: 2000
});
return false;
}
} catch (error) {
console.error('签到过程中发生错误:', error);
wx.hideLoading();
wx.showToast({
title: '签到失败,请重试',
icon: 'none',
duration: 2000
});
return false;
}
}
/**
*
*/
public async handleAuthLogin(): Promise<boolean> {
try {
const success = await this.showManualLoginModal();
if (success) {
console.log('手动登录成功');
return true;
} else {
console.log('用户取消手动登录');
return false;
}
} catch (error) {
console.error('手动登录过程中发生错误:', error);
return false;
}
}
/**
*
*/
public isTourist(): boolean {
const app = getApp<any>();
// 游客定义:已登录但没有完善基本信息(姓名和电话)的用户
if (app.globalData.isLoggedIn && app.globalData.userInfo) {
const userInfo = app.globalData.userInfo;
return !userInfo.name || !userInfo.phone;
}
return false;
}
/**
*
*/
public shouldShowSignInButton(): boolean {
// 从页面上下文中获取数据
const pageData = this.dataModule.getData();
const authStatus = pageData.authStatus || {};
const userInfo = pageData.userInfo;
// 显示条件已获取微信code、用户状态不是已签到、且用户不是游客已注册用户
const result = (
authStatus.hasWxCode &&
(authStatus.userStatus === 'registered' || authStatus.userStatus === 'signed_out') &&
userInfo !== null &&
userInfo.role !== 'GUEST'
);
return result;
}
/**
*
*/
public shouldShowRegisterButton(): boolean {
// 从页面上下文中获取数据
const pageData = this.dataModule.getData();
const authStatus = pageData.authStatus || {};
const userInfo = pageData.userInfo;
// 显示条件已获取微信code、用户状态为未注册、且用户是游客
const result = (
authStatus.hasWxCode &&
authStatus.userStatus === 'unregistered' &&
userInfo !== null &&
userInfo.role === 'GUEST'
);
2025-10-19 23:38:54 +08:00
// 调试信息已删除
2025-10-16 21:32:16 +08:00
return result;
}
/**
*
*/
public async determineUserStatus(userInfo: any): Promise<'registered' | 'unregistered' | 'signed_in' | 'signed_out'> {
if (!userInfo) return 'signed_out';
try {
// 从服务器获取用户真实状态
const serverStatus = await this.getUserStatusFromServer();
if (serverStatus) {
console.log('从服务器获取的用户状态:', serverStatus);
return serverStatus;
}
// 如果服务器获取失败,使用本地逻辑作为降级方案
console.warn('服务器状态获取失败,使用本地逻辑判断');
const isRegistered = userInfo.name && userInfo.phone;
return isRegistered ? 'registered' : 'unregistered';
} catch (error) {
console.error('获取用户状态失败:', error);
// 网络错误时使用本地逻辑
const isRegistered = userInfo.name && userInfo.phone;
return isRegistered ? 'registered' : 'unregistered';
}
}
/**
*
*/
private async getUserStatusFromServer(): Promise<'registered' | 'unregistered' | 'signed_in' | 'signed_out' | null> {
try {
// 调用服务器接口获取用户状态
const response = await userService.getUserStatus();
// 如果返回null表示服务器接口不存在
if (response === null) {
console.log('服务器状态接口不存在,跳过服务器状态获取');
return null;
}
if (response && response.status) {
// 根据服务器返回的状态映射到前端状态
switch (response.status) {
case 'signed_in':
return 'signed_in';
case 'signed_out':
return 'signed_out';
case 'registered':
return 'registered';
case 'unregistered':
return 'unregistered';
default:
return null;
}
}
return null;
} catch (error) {
console.error('获取服务器状态失败:', error);
return null;
}
}
}