✨ 新增功能: - 全局路由守卫模块 (route-guard.js) - 多层次权限验证 (登录状态+Token存在+Token过期检查) - 自动拦截机制 (页面级+跳转级+HTTP级+应用级) - 401响应自动处理和跳转 - 路由守卫测试页面 🔧 技术实现: - checkPageAccess() 全局页面权限检查 - guardedNavigate/guardedSwitchTab 带权限检查的跳转 - handleUnauthorized() HTTP拦截器401处理 - 公开页面配置管理 - 优雅的错误提示和跳转逻辑 📱 页面集成: - App.vue 初始化路由守卫 - profile/workbench 页面添加权限检查 - index 页面优化跳转逻辑 - 新增测试页面验证功能 📚 文档完善: - 移动端路由守卫使用指南 - 详细的变更记录和技术说明 - 最佳实践和注意事项 🎯 核心效果: 用户登录失效或未登录时,访问任何需要权限的页面都自动跳转到登录页,提升安全性和用户体验。
309 lines
7.2 KiB
SCSS
309 lines
7.2 KiB
SCSS
/**
|
|
* 这里是uni-app内置的常用样式变量
|
|
*
|
|
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
|
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
|
*
|
|
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
|
*/
|
|
|
|
// 引入 uview-plus 样式
|
|
@import 'uview-plus/theme.scss';
|
|
|
|
// 引入 uview-plus 图标字体 - 使用阿里CDN
|
|
@font-face {
|
|
font-family: 'uicon-iconfont';
|
|
src: url('https://at.alicdn.com/t/font_2225171_8kdcwk4po24.ttf') format('truetype');
|
|
}
|
|
|
|
/* 原有的Sass变量定义 - 保持向后兼容 */
|
|
$uni-color-primary: rgb(93, 135, 255);
|
|
$uni-color-primary-dark: rgb(73, 115, 235);
|
|
$uni-color-primary-light: rgba(93, 135, 255, 0.1);
|
|
|
|
/* 状态颜色 */
|
|
$uni-color-success: #52c41a;
|
|
$uni-color-warning: #faad14;
|
|
$uni-color-error: #ff4d4f;
|
|
$uni-color-info: #1890ff;
|
|
|
|
/* 文字基本颜色 */
|
|
$uni-text-color: #333333;
|
|
$uni-text-color-inverse: #fff;
|
|
$uni-text-color-secondary: #666666;
|
|
$uni-text-color-grey: #999999;
|
|
$uni-text-color-placeholder: #c0c0c0;
|
|
$uni-text-color-disable: #d9d9d9;
|
|
|
|
/* 背景颜色 */
|
|
$uni-bg-color: #ffffff;
|
|
$uni-bg-color-grey: #f8f9fa;
|
|
$uni-bg-color-hover: #f1f1f1;
|
|
$uni-bg-color-mask: rgba(0, 0, 0, 0.4);
|
|
|
|
/* 边框颜色 */
|
|
$uni-border-color: #e0e0e0;
|
|
|
|
/* 阴影 */
|
|
$uni-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
|
$uni-shadow-hover: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
|
|
/* 文字尺寸 */
|
|
$uni-font-size-sm: 12px;
|
|
$uni-font-size-base: 14px;
|
|
$uni-font-size-lg: 16px;
|
|
$uni-font-size-xl: 18px;
|
|
$uni-font-size-xxl: 20px;
|
|
|
|
/* 图片尺寸 */
|
|
$uni-img-size-sm: 20px;
|
|
$uni-img-size-base: 26px;
|
|
$uni-img-size-lg: 40px;
|
|
|
|
/* Border Radius */
|
|
$uni-border-radius-sm: 6px;
|
|
$uni-border-radius-base: 8px;
|
|
$uni-border-radius-lg: 12px;
|
|
$uni-border-radius-xl: 16px;
|
|
$uni-border-radius-circle: 50%;
|
|
|
|
/* 间距 */
|
|
$uni-spacing-row-sm: 8px;
|
|
$uni-spacing-row-base: 12px;
|
|
$uni-spacing-row-lg: 16px;
|
|
$uni-spacing-row-xl: 20px;
|
|
|
|
$uni-spacing-col-sm: 8px;
|
|
$uni-spacing-col-base: 12px;
|
|
$uni-spacing-col-lg: 16px;
|
|
$uni-spacing-col-xl: 20px;
|
|
|
|
/* 透明度 */
|
|
$uni-opacity-disabled: 0.3;
|
|
|
|
/* 文章场景相关 */
|
|
$uni-color-title: #2c405a;
|
|
$uni-font-size-title: 20px;
|
|
$uni-color-subtitle: #555;
|
|
$uni-font-size-subtitle: 18px;
|
|
$uni-color-paragraph: #3f536e;
|
|
$uni-font-size-paragraph: 15px;
|
|
|
|
/* 动画 */
|
|
$uni-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
$uni-transition-fast: all 0.15s ease-out;
|
|
|
|
/* 主题色彩变量 - CSS变量版本 */
|
|
:root {
|
|
--primary-color: rgb(93, 135, 255);
|
|
--primary-light: rgba(93, 135, 255, 0.1);
|
|
--primary-dark: rgb(73, 115, 235);
|
|
--success-color: #52c41a;
|
|
--warning-color: #faad14;
|
|
--error-color: #ff4d4f;
|
|
--text-primary: #262626;
|
|
--text-secondary: #595959;
|
|
--text-disabled: #bfbfbf;
|
|
--border-color: #f0f0f0;
|
|
--background-color: #f8f9fa;
|
|
--white: #ffffff;
|
|
--shadow-light: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
--shadow-medium: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
--radius-small: 4px;
|
|
--radius-medium: 8px;
|
|
--radius-large: 12px;
|
|
--spacing-xs: 4px;
|
|
--spacing-sm: 8px;
|
|
--spacing-md: 16px;
|
|
--spacing-lg: 24px;
|
|
--spacing-xl: 32px;
|
|
--transition-fast: 0.2s ease;
|
|
--transition-medium: 0.3s ease;
|
|
--font-size-xs: 12px;
|
|
--font-size-sm: 14px;
|
|
--font-size-md: 16px;
|
|
--font-size-lg: 18px;
|
|
--font-size-xl: 20px;
|
|
}
|
|
|
|
/* 全局样式重置 */
|
|
* {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
color: var(--text-primary);
|
|
background-color: var(--background-color);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
page {
|
|
background-color: var(--background-color);
|
|
color: var(--text-primary);
|
|
font-size: var(--font-size-md);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
/* 通用工具类 */
|
|
.flex {
|
|
display: flex;
|
|
}
|
|
|
|
.flex-center {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.flex-between {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.flex-column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.text-center {
|
|
text-align: center;
|
|
}
|
|
|
|
.text-primary {
|
|
color: var(--primary-color);
|
|
}
|
|
|
|
.text-secondary {
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.bg-primary {
|
|
background-color: var(--primary-color);
|
|
}
|
|
|
|
.bg-white {
|
|
background-color: var(--white);
|
|
}
|
|
|
|
.rounded {
|
|
border-radius: var(--radius-medium);
|
|
}
|
|
|
|
.shadow {
|
|
box-shadow: var(--shadow-light);
|
|
}
|
|
|
|
.mt-sm { margin-top: var(--spacing-sm); }
|
|
.mt-md { margin-top: var(--spacing-md); }
|
|
.mt-lg { margin-top: var(--spacing-lg); }
|
|
.mb-sm { margin-bottom: var(--spacing-sm); }
|
|
.mb-md { margin-bottom: var(--spacing-md); }
|
|
.mb-lg { margin-bottom: var(--spacing-lg); }
|
|
.ml-sm { margin-left: var(--spacing-sm); }
|
|
.ml-md { margin-left: var(--spacing-md); }
|
|
.mr-sm { margin-right: var(--spacing-sm); }
|
|
.mr-md { margin-right: var(--spacing-md); }
|
|
|
|
.p-sm { padding: var(--spacing-sm); }
|
|
.p-md { padding: var(--spacing-md); }
|
|
.p-lg { padding: var(--spacing-lg); }
|
|
.px-sm { padding-left: var(--spacing-sm); padding-right: var(--spacing-sm); }
|
|
.px-md { padding-left: var(--spacing-md); padding-right: var(--spacing-md); }
|
|
.py-sm { padding-top: var(--spacing-sm); padding-bottom: var(--spacing-sm); }
|
|
.py-md { padding-top: var(--spacing-md); padding-bottom: var(--spacing-md); }
|
|
|
|
/* 按钮基础样式 */
|
|
.btn {
|
|
padding: var(--spacing-sm) var(--spacing-md);
|
|
border-radius: var(--radius-medium);
|
|
border: none;
|
|
font-size: var(--font-size-md);
|
|
cursor: pointer;
|
|
transition: var(--transition-fast);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-primary {
|
|
background-color: var(--primary-color);
|
|
color: var(--white);
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
background-color: var(--primary-dark);
|
|
}
|
|
|
|
/* 输入框样式 */
|
|
.input {
|
|
padding: var(--spacing-sm) var(--spacing-md);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-medium);
|
|
font-size: var(--font-size-md);
|
|
transition: var(--transition-fast);
|
|
}
|
|
|
|
.input:focus {
|
|
border-color: var(--primary-color);
|
|
outline: none;
|
|
box-shadow: 0 0 0 2px rgba(93, 135, 255, 0.2);
|
|
}
|
|
|
|
/* 卡片样式 */
|
|
.card {
|
|
background: var(--white);
|
|
border-radius: var(--radius-large);
|
|
box-shadow: var(--shadow-light);
|
|
padding: var(--spacing-md);
|
|
margin-bottom: var(--spacing-md);
|
|
}
|
|
|
|
.card-header {
|
|
font-size: var(--font-size-lg);
|
|
font-weight: 600;
|
|
margin-bottom: var(--spacing-md);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
/* 动画类 */
|
|
.fade-in {
|
|
animation: fadeIn var(--transition-medium);
|
|
}
|
|
|
|
.slide-up {
|
|
animation: slideUp var(--transition-medium);
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* 响应式断点 */
|
|
@media (max-width: 768px) {
|
|
.card {
|
|
margin: var(--spacing-sm);
|
|
padding: var(--spacing-sm);
|
|
}
|
|
} |