first commit
This commit is contained in:
486
miniprogram/services/userService.ts
Normal file
486
miniprogram/services/userService.ts
Normal file
@@ -0,0 +1,486 @@
|
||||
// 用户服务文件
|
||||
|
||||
// 用户服务 - 处理用户相关的数据操作
|
||||
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();
|
Reference in New Issue
Block a user