Files
WXProgram/miniprogram/services/userService.ts
2025-10-16 21:32:16 +08:00

486 lines
13 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.

// 用户服务文件
// 用户服务 - 处理用户相关的数据操作
import { UserInfo, EmployeeInfo } from '../types';
import apiService from './apiService';
import { isMockMode } from './apiService';
/**
* 用户服务类
* 提供用户认证、信息管理、权限验证等功能
*/
class UserService {
// 模拟用户数据
private mockUsers: UserInfo[];
/**
* 构造函数,初始化模拟用户数据
*/
constructor() {
this.mockUsers = [
{
id: 1,
role: 'ADMIN'
},
{
id: 2,
role: 'DELIVERY_PERSON'
}
];
}
/**
* 获取用户信息
* @returns 用户信息
*/
async getUserInfo(): Promise<UserInfo> {
if (isMockMode) {
// 模拟数据 - 返回管理员信息
console.log('[MOCK] 获取用户信息');
return {
id: 1,
role: 'ADMIN'
};
}
return apiService.getUserInfo();
}
/**
* 用户退出登录
*/
async logout(): Promise<void> {
if (isMockMode) {
// 模拟登出
console.log('[MOCK] 用户登出');
return;
}
return apiService.logout();
}
/**
* 检查用户是否已登录
* @returns 是否已登录
*/
isLoggedIn(): boolean {
const app = getApp<any>();
return app.globalData.isLoggedIn && !!app.globalData.userInfo;
}
/**
* 获取用户角色
* @returns 用户角色或null
*/
getUserRole(): string | null {
const app = getApp<any>();
return app.globalData.userInfo && app.globalData.userInfo.role || null;
}
/**
* 检查用户是否为管理员
* @returns 是否为管理员
*/
isAdmin(): boolean {
return this.getUserRole() === 'ADMIN';
}
/**
* 检查用户是否为货运人员
* @returns 是否为货运人员
*/
isDeliveryPerson(): boolean {
return this.getUserRole() === 'DELIVERY_PERSON';
}
/**
* 检查位置权限
* @returns 是否拥有位置权限
*/
checkLocationPermission(): Promise<boolean> {
return new Promise((resolve) => {
wx.getSetting({
success: (res) => {
const hasPermission = res.authSetting && res.authSetting['scope.userLocation'];
resolve(!!hasPermission);
},
fail: () => {
resolve(false);
}
});
});
}
/**
* 请求位置权限
* @returns 请求是否成功
*/
requestLocationPermission(): Promise<boolean> {
return new Promise((resolve) => {
wx.authorize({
scope: 'scope.userLocation',
success: () => {
resolve(true);
},
fail: () => {
resolve(false);
}
});
});
}
/**
* 获取全局用户信息
* @returns 全局用户信息或null
*/
getGlobalUserInfo(): UserInfo | null {
const app = getApp<any>();
return app.globalData.userInfo as UserInfo | null;
}
/**
* 执行静默登录流程:微信登录->个人服务器登录->进入基础界面->签到/注册
* @returns 登录结果
*/
async wxLogin(): Promise<{
success: boolean;
userInfo?: UserInfo;
openid?: string;
session_key?: string;
token?: string;
}> {
try {
// 获取微信登录code
console.log('步骤1: 获取微信登录code');
const code = await this.getWxLoginCode();
if (!code) {
console.error('步骤1失败: 获取微信登录code失败');
throw new Error('获取微信登录code失败');
}
console.log('步骤1成功: 获取到微信登录code');
// 调用微信登录API
console.log('步骤2: 调用微信登录API');
const wxLoginResult = await this.ServerLogin(code);
if (wxLoginResult.success) {
console.log('步骤2成功: 微信登录API调用成功');
// 静默登录模式下,不主动获取用户信息
let userInfo = wxLoginResult.userInfo;
return {
success: true,
userInfo,
openid: wxLoginResult.openid,
session_key: wx.getStorageSync('session_key'), //TODO:服务器已经下发
token: wxLoginResult.token
};
} else {
console.error('步骤2失败: 微信登录API返回失败');
return {
success: false,
openid: wxLoginResult.openid
};
}
} catch (error) {
console.error('登录流程异常:', error);
return { success: false };
}
}
/**
* 微信登录成功后调用个人服务器登录消息
* @param code 微信登录授权码
* @returns 登录结果
*/
async ServerLogin(code: string): Promise<{ success: boolean; openid?: string; token?: string; userInfo?: UserInfo }> {
try {
if (isMockMode) {
// 模拟登录成功
console.log('[MOCK] 微信小程序登录');
// 使用模拟用户数据
const userInfo = this.mockUsers[0];
const openid = 'mock-openid-' + Math.random().toString(36).substring(2);
const token = 'mock-token-' + Date.now();
const session_key = 'mock-session-key-' + Math.random().toString(36).substring(2);
// 保存到本地存储
wx.setStorageSync('userInfo', userInfo);
wx.setStorageSync('token', token);
wx.setStorageSync('openid', openid);
wx.setStorageSync('session_key', session_key);
return { success: true, openid, token, userInfo };
}
// 真实API模式
//TODO: 登录成功的基础数据:服务器下发的公共游客可看的数据
const result = await apiService.ServerLogin(code);
// 保存到本地存储
wx.setStorageSync('userInfo', result.user);
wx.setStorageSync('token', result.token);
wx.setStorageSync('openid', result.openid);
wx.setStorageSync('session_key', result.session_key);
// 同时保存到全局数据确保后续API调用能正确获取token
const app = getApp<any>();
app.globalData.token = result.token;
return {
success: true,
openid: result.openid,
token: result.token,
userInfo: result.user
};
} catch (error) {
console.error('微信登录失败:', error);
return { success: false };
}
}
/**
* 获取微信登录code
*/
private async getWxLoginCode(): Promise<string | null> {
return new Promise((resolve) => {
wx.login({
success: (res) => {
if (res.code) {
console.log('成功获取到登录code');
resolve(res.code);
} else {
console.error('获取登录code失败返回值为空');
resolve(null);
}
},
fail: (error) => {
console.error('wx.login调用失败:', error);
resolve(null);
}
});
});
}
/**
* 更新用户信息
* @param userInfo 待更新的用户信息
* @returns 更新后的用户信息
*/
async updateUserInfo(userInfo: Partial<UserInfo>): Promise<UserInfo> {
if (isMockMode) {
// 模拟更新成功
console.log('[MOCK] 更新用户信息');
return {
id: 1,
role: userInfo.role || 'GUEST'
};
}
return apiService.updateUserInfo(userInfo);
}
/**
* 获取用户签到状态
* @returns 用户状态信息
*/
async getUserStatus(): Promise<{ status: 'signed_in' | 'signed_out' | 'registered' | 'unregistered'; lastSignInTime?: string; lastSignOutTime?: string }> {
if (isMockMode) {
// 模拟数据 - 默认返回已注册状态
console.log('[MOCK] 获取用户状态');
return {
status: 'registered'
};
}
try {
// 调用服务器接口获取用户状态
const response = await apiService.getUserStatus();
return response;
} catch (error: any) {
console.error('获取用户状态失败:', error);
// 如果是404错误接口不存在返回null让前端使用本地逻辑
if (error.message && error.message.includes('404')) {
console.log('服务器状态接口不存在,使用本地逻辑');
return null as any; // 返回null表示服务器接口不可用
}
// 其他网络错误时返回默认状态
return {
status: 'registered'
};
}
}
/**
* 用户签到
* @returns 签到结果和更新后的用户信息
*/
async signIn(): Promise<{ success: boolean; employeeInfo: EmployeeInfo; message?: string }> {
const userInfo = this.getGlobalUserInfo();
if (!userInfo || !userInfo.id) {
throw new Error('用户未登录,无法签到');
}
// 检查是否有有效的token防止后端空指针异常
const app = getApp<any>();
if (!app.globalData.token) {
throw new Error('用户认证信息缺失,请重新登录');
}
if (isMockMode) {
// 模拟签到成功,返回员工信息
console.log('[MOCK] 用户签到成功');
const employeeInfo: EmployeeInfo = {
id: userInfo.id,
name: '测试用户',
phone: '13800138000',
role: userInfo.role || 'DELIVERY_PERSON'
};
return {
success: true,
employeeInfo: employeeInfo,
message: '签到成功'
};
}
return apiService.userSignIn(userInfo.id);
}
/**
* 用户注册
* @param registerInfo 注册信息
* @returns 注册结果和员工信息
*/
async register(registerInfo: { name: string; phone: string }): Promise<{ success: boolean; employeeInfo: EmployeeInfo; message?: string }> {
if (isMockMode) {
// 模拟注册成功
console.log('[MOCK] 用户注册成功');
// 确保所有必需字段都有值
const employeeInfo: EmployeeInfo = {
id: Date.now(),
name: registerInfo.name,
phone: registerInfo.phone,
role: 'DELIVERY_PERSON'
};
this.mockUsers.push({
id: employeeInfo.id,
role: employeeInfo.role || 'DELIVERY_PERSON',
name: employeeInfo.name,
phone: employeeInfo.phone
});
return {
success: true,
employeeInfo: employeeInfo,
message: '注册成功'
};
}
return apiService.userRegister(registerInfo);
}
/**
* 获取用户权限列表
* @returns 权限列表
*/
async getUserPermissions(): Promise<string[]> {
if (isMockMode) {
// 模拟权限列表
console.log('[MOCK] 获取用户权限列表');
return [
'order:view',
'order:edit',
'delivery:view',
'delivery:edit',
'warehouse:view',
'warehouse:edit',
'user:view',
'user:edit'
];
}
return apiService.getUserPermissions();
}
/**
* 检查用户是否在线
* @returns 是否在线
*/
async checkUserOnline(): Promise<boolean> {
if (isMockMode) {
// 模拟用户在线
console.log('[MOCK] 检查用户在线状态');
return true;
}
return apiService.checkUserOnline();
}
/**
* 获取用户会话信息
* @returns 会话信息
*/
async getSessionInfo(): Promise<{
userId: number;
sessionId: string;
expiresAt: number;
permissions: string[];
}> {
if (isMockMode) {
// 模拟会话信息
console.log('[MOCK] 获取用户会话信息');
return {
userId: 1,
sessionId: 'mock-session-' + Date.now(),
expiresAt: Date.now() + 86400000, // 24小时后过期
permissions: [
'order:view',
'order:edit',
'delivery:view',
'delivery:edit',
'warehouse:view',
'warehouse:edit',
'user:view',
'user:edit'
]
};
}
return apiService.getSessionInfo();
}
/**
* 刷新用户令牌
* @param oldToken 旧令牌
* @returns 新令牌及过期时间
*/
async refreshToken(oldToken: string): Promise<{ token: string; expiresAt: number }> {
if (isMockMode) {
// 模拟令牌刷新
console.log('[MOCK] 刷新用户令牌');
return {
token: 'mock-refreshed-token-' + Date.now(),
expiresAt: Date.now() + 86400000 // 24小时后过期
};
}
return apiService.refreshToken(oldToken);
}
/**
* 验证用户权限
* @param permission 待验证的权限
* @returns 是否拥有该权限
*/
async verifyPermission(permission: string): Promise<boolean> {
if (isMockMode) {
// 模拟权限验证(管理员拥有所有权限)
console.log('[MOCK] 验证用户权限:', permission);
return true;
}
return apiService.verifyPermission(permission);
}
}
/**
* 用户服务单例实例
* 导出供应用程序全局使用
*/
export default new UserService();