✨ 新增功能: - 全局路由守卫模块 (route-guard.js) - 多层次权限验证 (登录状态+Token存在+Token过期检查) - 自动拦截机制 (页面级+跳转级+HTTP级+应用级) - 401响应自动处理和跳转 - 路由守卫测试页面 🔧 技术实现: - checkPageAccess() 全局页面权限检查 - guardedNavigate/guardedSwitchTab 带权限检查的跳转 - handleUnauthorized() HTTP拦截器401处理 - 公开页面配置管理 - 优雅的错误提示和跳转逻辑 📱 页面集成: - App.vue 初始化路由守卫 - profile/workbench 页面添加权限检查 - index 页面优化跳转逻辑 - 新增测试页面验证功能 📚 文档完善: - 移动端路由守卫使用指南 - 详细的变更记录和技术说明 - 最佳实践和注意事项 🎯 核心效果: 用户登录失效或未登录时,访问任何需要权限的页面都自动跳转到登录页,提升安全性和用户体验。
316 lines
8.0 KiB
JavaScript
316 lines
8.0 KiB
JavaScript
/**
|
|
* 用户管理工具
|
|
* 处理用户信息、权限、状态等相关功能
|
|
*/
|
|
|
|
import { userStorage } from './request';
|
|
|
|
/**
|
|
* 用户信息管理
|
|
*/
|
|
export const userManager = {
|
|
/**
|
|
* 获取当前用户信息
|
|
*/
|
|
getCurrentUser() {
|
|
const userInfo = userStorage.getUserInfo();
|
|
if (!userInfo || !userInfo.user) {
|
|
return null;
|
|
}
|
|
|
|
const user = userInfo.user;
|
|
const permissions = userInfo.permissions || [];
|
|
const roles = userInfo.roles || [];
|
|
|
|
return {
|
|
// 基本信息
|
|
userId: user.userId,
|
|
userName: user.userName,
|
|
nickName: user.nickName || user.userName,
|
|
email: user.email,
|
|
phoneNumber: user.phoneNumber,
|
|
sex: user.sex,
|
|
avatar: user.avatar,
|
|
|
|
// 部门信息
|
|
deptId: user.deptId,
|
|
deptName: user.dept?.deptName || '',
|
|
|
|
// 状态信息
|
|
status: user.status,
|
|
createTime: user.createTime,
|
|
loginDate: user.loginDate,
|
|
|
|
// 权限信息
|
|
permissions,
|
|
roles,
|
|
|
|
// 扩展信息
|
|
remark: user.remark,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* 检查用户是否拥有指定权限
|
|
* @param {string} permission 权限标识
|
|
*/
|
|
hasPermission(permission) {
|
|
if (!permission) return true;
|
|
|
|
const userInfo = this.getCurrentUser();
|
|
if (!userInfo || !userInfo.permissions) {
|
|
return false;
|
|
}
|
|
|
|
return userInfo.permissions.includes(permission);
|
|
},
|
|
|
|
/**
|
|
* 检查用户是否拥有指定角色
|
|
* @param {string} role 角色标识
|
|
*/
|
|
hasRole(role) {
|
|
if (!role) return true;
|
|
|
|
const userInfo = this.getCurrentUser();
|
|
if (!userInfo || !userInfo.roles) {
|
|
return false;
|
|
}
|
|
|
|
return userInfo.roles.some((r) => r.roleKey === role);
|
|
},
|
|
|
|
/**
|
|
* 检查用户是否为管理员
|
|
*/
|
|
isAdmin() {
|
|
return this.hasRole('admin') || this.hasRole('super_admin');
|
|
},
|
|
|
|
/**
|
|
* 获取用户显示名称
|
|
*/
|
|
getDisplayName() {
|
|
const user = this.getCurrentUser();
|
|
if (!user) return '未登录';
|
|
|
|
return user.nickName || user.userName || '用户';
|
|
},
|
|
|
|
/**
|
|
* 获取用户头像URL
|
|
* @param {string} defaultAvatar 默认头像URL
|
|
*/
|
|
getAvatarUrl(defaultAvatar = '/static/default-avatar.png') {
|
|
const user = this.getCurrentUser();
|
|
if (!user || !user.avatar) {
|
|
return defaultAvatar;
|
|
}
|
|
|
|
// 如果是完整URL,直接返回
|
|
if (user.avatar.startsWith('http')) {
|
|
return user.avatar;
|
|
}
|
|
|
|
// 拼接基础URL
|
|
const baseURL =
|
|
process.env.NODE_ENV === 'development'
|
|
? 'http://localhost:8080'
|
|
: 'https://your-api-domain.com';
|
|
|
|
return baseURL + user.avatar;
|
|
},
|
|
|
|
/**
|
|
* 更新用户本地信息
|
|
* @param {object} userData 用户数据
|
|
*/
|
|
updateUserInfo(userData) {
|
|
try {
|
|
const currentInfo = userStorage.getUserInfo();
|
|
if (currentInfo) {
|
|
const updatedInfo = {
|
|
...currentInfo,
|
|
user: {
|
|
...currentInfo.user,
|
|
...userData,
|
|
},
|
|
};
|
|
uni.setStorageSync('userInfo', JSON.stringify(updatedInfo));
|
|
console.log('用户信息已更新');
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
console.error('更新用户信息失败:', e);
|
|
}
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* 格式化用户信息用于显示
|
|
*/
|
|
formatUserForDisplay() {
|
|
const user = this.getCurrentUser();
|
|
if (!user) return null;
|
|
|
|
return {
|
|
name: this.getDisplayName(),
|
|
avatar: this.getAvatarUrl(),
|
|
department: user.deptName || '未分配部门',
|
|
phone: user.phoneNumber || '未设置',
|
|
email: user.email || '未设置',
|
|
status: user.status === '0' ? '正常' : '停用',
|
|
isAdmin: this.isAdmin(),
|
|
lastLoginTime: user.loginDate ? new Date(user.loginDate).toLocaleString() : '首次登录',
|
|
};
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 权限检查指令工具
|
|
*/
|
|
export const permissionUtils = {
|
|
/**
|
|
* 检查页面访问权限
|
|
* @param {string} pagePath 页面路径
|
|
*/
|
|
checkPagePermission(pagePath) {
|
|
// 公开页面,无需权限检查
|
|
const publicPages = ['/pages/login/index', '/pages/index/index', '/pages/profile/index'];
|
|
|
|
if (publicPages.includes(pagePath)) {
|
|
return true;
|
|
}
|
|
|
|
// 检查是否已登录
|
|
if (!userStorage.isLoggedIn()) {
|
|
return false;
|
|
}
|
|
|
|
// 这里可以根据具体业务需求添加页面权限检查逻辑
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* 权限控制的页面跳转
|
|
* @param {string} url 目标页面URL
|
|
* @param {string} permission 所需权限
|
|
*/
|
|
navigateWithPermission(url, permission = null) {
|
|
// 检查登录状态
|
|
if (!userStorage.isLoggedIn()) {
|
|
uni.showToast({
|
|
title: '请先登录',
|
|
icon: 'none',
|
|
});
|
|
uni.reLaunch({
|
|
url: '/pages/login/index',
|
|
});
|
|
return false;
|
|
}
|
|
|
|
// 检查权限
|
|
if (permission && !userManager.hasPermission(permission)) {
|
|
uni.showToast({
|
|
title: '权限不足',
|
|
icon: 'none',
|
|
});
|
|
return false;
|
|
}
|
|
|
|
// 执行跳转
|
|
uni.navigateTo({
|
|
url,
|
|
fail: () => {
|
|
uni.showToast({
|
|
title: '页面跳转失败',
|
|
icon: 'none',
|
|
});
|
|
},
|
|
});
|
|
|
|
return true;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 用户状态管理
|
|
*/
|
|
export const userState = {
|
|
/**
|
|
* 检查Token是否即将过期(提前5分钟提醒)
|
|
*/
|
|
checkTokenExpiration() {
|
|
try {
|
|
const token = userStorage.getToken();
|
|
if (!token) return false;
|
|
|
|
// 这里可以解析JWT token获取过期时间
|
|
// 简化处理:检查登录时间是否超过2小时
|
|
const userInfo = userStorage.getUserInfo();
|
|
if (userInfo && userInfo.loginTime) {
|
|
const loginTime = new Date(userInfo.loginTime).getTime();
|
|
const now = Date.now();
|
|
const twoHours = 2 * 60 * 60 * 1000; // 2小时
|
|
|
|
return now - loginTime > twoHours;
|
|
}
|
|
} catch (e) {
|
|
console.error('检查Token过期时间失败:', e);
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* 刷新Token
|
|
*/
|
|
async refreshToken() {
|
|
try {
|
|
// 这里调用刷新Token的API
|
|
// const result = await api.refreshToken();
|
|
// if (result.code === 200) {
|
|
// uni.setStorageSync('access_token', result.data.access_token);
|
|
// return true;
|
|
// }
|
|
console.log('Token刷新功能待实现');
|
|
} catch (e) {
|
|
console.error('刷新Token失败:', e);
|
|
}
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* 自动登录检查
|
|
*/
|
|
autoLoginCheck() {
|
|
if (!userStorage.isLoggedIn()) {
|
|
return false;
|
|
}
|
|
|
|
// 检查Token是否过期
|
|
if (this.checkTokenExpiration()) {
|
|
uni.showModal({
|
|
title: '登录过期',
|
|
content: '您的登录已过期,请重新登录',
|
|
showCancel: false,
|
|
success: () => {
|
|
userStorage.clearLoginInfo();
|
|
uni.reLaunch({
|
|
url: '/pages/login/index',
|
|
});
|
|
},
|
|
});
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
};
|
|
|
|
export default {
|
|
userManager,
|
|
permissionUtils,
|
|
userState,
|
|
};
|