Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-csf-front
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
yuzhenWang
yd-csf-front
Commits
04757222
Commit
04757222
authored
Sep 02, 2025
by
yuzhenWang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加跳转逻辑
parent
9a317de9
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
318 additions
and
277 deletions
+318
-277
.env.development
+1
-1
.env.production
+2
-3
.env.staging
+2
-3
index.html
+3
-4
package.json
+1
-1
public/csfLogo.png
+0
-0
src/assets/logo/csfLogo.png
+0
-0
src/assets/styles/variables.module.scss
+28
-26
src/layout/components/Navbar.vue
+49
-29
src/layout/components/Sidebar/Logo.vue
+4
-4
src/permission.js
+38
-20
src/store/modules/permission.js
+68
-66
src/store/modules/user.js
+108
-94
src/views/index.vue
+14
-26
No files found.
.env.development
View file @
04757222
# 页面标题
VITE_APP_TITLE =
若依管理系统
VITE_APP_TITLE =
CSF-CORE
# 开发环境配置
VITE_APP_ENV = 'development'
...
...
.env.production
View file @
04757222
# 页面标题
VITE_APP_TITLE =
若依管理系统
VITE_APP_TITLE =
CSF-CORE
# 生产环境配置
VITE_APP_ENV = 'production'
...
...
@@ -8,4 +8,4 @@ VITE_APP_ENV = 'production'
VITE_APP_BASE_API = '/prod-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
\ No newline at end of file
VITE_BUILD_COMPRESS = gzip
.env.staging
View file @
04757222
# 页面标题
VITE_APP_TITLE =
若依管理系统
VITE_APP_TITLE =
CSF-CORE
# 生产环境配置
VITE_APP_ENV = 'staging'
...
...
@@ -8,4 +8,4 @@ VITE_APP_ENV = 'staging'
VITE_APP_BASE_API = '/stage-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
\ No newline at end of file
VITE_BUILD_COMPRESS = gzip
index.html
View file @
04757222
...
...
@@ -6,8 +6,8 @@
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
>
<meta
name=
"renderer"
content=
"webkit"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
>
<link
rel=
"icon"
href=
"/
favicon.ico
"
>
<title>
若依管理系统
</title>
<link
rel=
"icon"
href=
"/
csfLogo.png
"
>
<title>
CSF-CORE
</title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style>
html
,
...
...
@@ -212,4 +212,4 @@
<script
type=
"module"
src=
"/src/main.js"
></script>
</body>
</html>
\ No newline at end of file
</html>
package.json
View file @
04757222
{
"name"
:
"
ruoyi
"
,
"version"
:
"3.9.0"
,
"description"
:
"
若依管理系统
"
,
"description"
:
"
CSF-CORE
"
,
"author"
:
"若依"
,
"license"
:
"
MIT
"
,
"type"
:
"module"
,
...
...
public/csfLogo.png
0 → 100644
View file @
04757222
21.6 KB
src/assets/logo/csfLogo.png
0 → 100644
View file @
04757222
21.6 KB
src/assets/styles/variables.module.scss
View file @
04757222
// base color
$blue
:
#324157
;
$light-blue
:
#333c46
;
$red
:
#
C
03639
;
$pink
:
#
E65D6E
;
$green
:
#30
B08F
;
$tiffany
:
#4
AB7BD
;
$yellow
:
#
FEC
171
;
$panGreen
:
#30
B08F
;
$red
:
#
c
03639
;
$pink
:
#
e65d6e
;
$green
:
#30
b08f
;
$tiffany
:
#4
ab7bd
;
$yellow
:
#
fec
171
;
$panGreen
:
#30
b08f
;
// 默认主题变量
$menuText
:
#bfcbd9
;
$menuText
:
#bfcbd9
;
//原来的颜色
// $menuText: #333;
$menuActiveText
:
#409eff
;
$menuBg
:
#304156
;
$menuBg
:
#304156
;
//原来的颜色
// $menuBg: #fff;
$menuHover
:
#263445
;
// 浅色主题theme-light
$menuLightBg
:
#ffffff
;
$menuLightHover
:
#f0f1f5
;
$menuLightText
:
#303133
;
$menuLightActiveText
:
#409
EFF
;
$menuLightActiveText
:
#409
eff
;
// 基础变量
$base-sidebar-width
:
200px
;
...
...
@@ -32,10 +34,10 @@ $base-sub-menu-background: #1f2d3d;
$base-sub-menu-hover
:
#001528
;
// 组件变量
$--color-primary
:
#409
EFF
;
$--color-success
:
#67
C23A
;
$--color-warning
:
#
E6A23C
;
$--color-danger
:
#
F56C6C
;
$--color-primary
:
#409
eff
;
$--color-success
:
#67
c23a
;
$--color-warning
:
#
e6a23c
;
$--color-danger
:
#
f56c6c
;
$--color-info
:
#909399
;
:export
{
...
...
@@ -71,13 +73,12 @@ $--color-info: #909399;
--sidebar-bg
:
#{
$menuBg
}
;
--sidebar-text
:
#{
$menuText
}
;
--menu-hover
:
#{
$menuHover
}
;
--navbar-bg
:
#ffffff
;
--navbar-text
:
#303133
;
/* splitpanes default-theme 变量 */
--splitpanes-default-bg
:
#ffffff
;
}
// 暗黑模式变量
...
...
@@ -119,7 +120,7 @@ html.dark {
--blockquote-bg
:
#1d1e1f
;
--blockquote-border
:
#303030
;
--blockquote-text
:
#d0d0d0
;
/* Cron 时间表达式 模式变量 */
--cron-border
:
#303030
;
...
...
@@ -127,11 +128,12 @@ html.dark {
--splitpanes-default-bg
:
#141414
;
/* 侧边栏菜单覆盖 */
.sidebar-container
{
.el-menu-item
,
.menu-title
{
.sidebar-container
{
.el-menu-item
,
.menu-title
{
color
:
var
(
--
el-text-color-regular
);
}
&
.theme-dark
.nest-menu
.el-sub-menu
>
.el-sub-menu__title
,
&
.theme-dark
.nest-menu
.el-sub-menu
>
.el-sub-menu__title
,
&
.theme-dark
.el-sub-menu
.el-menu-item
{
background-color
:
var
(
--
el-bg-color
)
!
important
;
}
...
...
@@ -180,7 +182,8 @@ html.dark {
--el-table-border-color
:
var
(
--
el-border-color-light
)
!
important
;
--el-table-row-hover-bg-color
:
var
(
--
el-bg-color-overlay
)
!
important
;
.el-table__header-wrapper
,
.el-table__fixed-header-wrapper
{
.el-table__header-wrapper
,
.el-table__fixed-header-wrapper
{
th
{
background-color
:
var
(
--
el-bg-color-overlay
,
#f8f8f9
)
!
important
;
color
:
var
(
--
el-text-color-regular
,
#515a6e
);
...
...
@@ -199,9 +202,10 @@ html.dark {
background-color
:
var
(
--
el-bg-color-overlay
);
}
}
/* 下拉菜单样式覆盖 */
.el-dropdown-menu__item
:not
(
.is-disabled
)
:focus
,
.el-dropdown-menu__item
:not
(
.is-disabled
)
:hover
{
.el-dropdown-menu__item
:not
(
.is-disabled
)
:focus
,
.el-dropdown-menu__item
:not
(
.is-disabled
)
:hover
{
background-color
:
var
(
--
navbar-hover
)
!
important
;
}
...
...
@@ -211,11 +215,9 @@ html.dark {
border-left-color
:
var
(
--
blockquote-border
)
!
important
;
color
:
var
(
--
blockquote-text
)
!
important
;
}
/* 时间表达式标题样式覆盖 */
.popup-result
.title
{
background
:
var
(
--
cron-border
);
}
}
src/layout/components/Navbar.vue
View file @
04757222
<
template
>
<div
class=
"navbar"
>
<hamburger
id=
"hamburger-container"
:is-active=
"appStore.sidebar.opened"
class=
"hamburger-container"
@
toggleClick=
"toggleSideBar"
/>
<breadcrumb
v-if=
"!settingsStore.topNav"
id=
"breadcrumb-container"
class=
"breadcrumb-container"
/>
<hamburger
id=
"hamburger-container"
:is-active=
"appStore.sidebar.opened"
class=
"hamburger-container"
@
toggleClick=
"toggleSideBar"
/>
<breadcrumb
v-if=
"!settingsStore.topNav"
id=
"breadcrumb-container"
class=
"breadcrumb-container"
/>
<top-nav
v-if=
"settingsStore.topNav"
id=
"topmenu-container"
class=
"topmenu-container"
/>
<div
class=
"right-menu"
>
<!-- 添加租户选择器 -->
<!--
<tenant-select
class=
"right-menu-item hover-effect"
v-if=
"userStore.tenants.length >= 1"
/>
-->
<el-dropdown
class=
"tenant-selector"
@
command=
"handleTenantChange"
>
<!--
<tenant-select
class=
"right-menu-item hover-effect"
v-if=
"userStore.tenants.length >= 1"
/>
-->
<
!--
<
el-dropdown
class=
"tenant-selector"
@
command=
"handleTenantChange"
>
<span
class=
"el-dropdown-link"
>
{{
currentTenantName
}}
<el-icon
class=
"el-icon--right"
><arrow-down
/></el-icon>
</span>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
v-for=
"tenant in availableTenants"
:key=
"tenant.apiLoginTenantInfoResponse.tenantBizId"
:command=
"tenant"
v-for=
"tenant in availableTenants"
:key=
"tenant.apiLoginTenantInfoResponse.tenantBizId"
:command=
"tenant"
>
{{
tenant
.
apiLoginTenantInfoResponse
.
tenantName
}}
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</el-dropdown>
-->
<
template
v-if=
"appStore.device !== 'mobile'"
>
<header-search
id=
"header-search"
class=
"right-menu-item"
/>
<el-tooltip
content=
"源码地址"
effect=
"dark"
placement=
"bottom"
>
<
!--
<
el-tooltip
content=
"源码地址"
effect=
"dark"
placement=
"bottom"
>
<ruo-yi-git
id=
"ruoyi-git"
class=
"right-menu-item hover-effect"
/>
</el-tooltip>
</el-tooltip>
-->
<el-tooltip
content=
"文档地址"
effect=
"dark"
placement=
"bottom"
>
<
!--
<
el-tooltip
content=
"文档地址"
effect=
"dark"
placement=
"bottom"
>
<ruo-yi-doc
id=
"ruoyi-doc"
class=
"right-menu-item hover-effect"
/>
</el-tooltip>
</el-tooltip>
-->
<screenfull
id=
"screenfull"
class=
"right-menu-item hover-effect"
/>
...
...
@@ -48,23 +57,31 @@
</el-tooltip>
</
template
>
<el-dropdown
@
command=
"handleCommand"
class=
"avatar-container right-menu-item hover-effect"
trigger=
"hover"
>
<el-dropdown
@
command=
"handleCommand"
class=
"avatar-container right-menu-item hover-effect"
trigger=
"hover"
>
<div
class=
"avatar-wrapper"
>
<img
:src=
"userStore.avatar"
class=
"user-avatar"
/>
<span
class=
"user-nickname"
>
{{ userStore.nickName }}
</span>
</div>
<
template
#
dropdown
>
<el-dropdown-menu>
<router-link
to=
"/user/profile"
>
<
!--
<
router-link
to=
"/user/profile"
>
<el-dropdown-item>
个人中心
</el-dropdown-item>
</router-link>
</router-link>
-->
<el-dropdown-item
divided
command=
"logout"
>
<span>
退出登录
</span>
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
<div
class=
"right-menu-item hover-effect setting"
@
click=
"setLayout"
v-if=
"settingsStore.showSettings"
>
<div
class=
"right-menu-item hover-effect setting"
@
click=
"setLayout"
v-if=
"settingsStore.showSettings"
>
<svg-icon
icon-class=
"more-up"
/>
</div>
</div>
...
...
@@ -98,9 +115,10 @@ const availableTenants = computed(() => {
// 添加空值检查
if
(
!
userStore
.
tenants
)
return
[]
return
userStore
.
tenants
.
filter
(
tenant
=>
return
userStore
.
tenants
.
filter
(
tenant
=>
// (tenant.apiLoginProjectInfoResponseList && tenant.apiLoginProjectInfoResponseList.length > 0) &&
(
tenant
.
apiLoginTenantInfoResponse
&&
tenant
.
apiLoginTenantInfoResponse
.
status
===
1
)
tenant
.
apiLoginTenantInfoResponse
&&
tenant
.
apiLoginTenantInfoResponse
.
status
===
1
)
})
...
...
@@ -115,7 +133,7 @@ const currentTenantName = computed(() => {
})
// 切换租户处理
const
handleTenantChange
=
(
tenant
)
=>
{
const
handleTenantChange
=
tenant
=>
{
userStore
.
switchTenant
(
tenant
)
}
...
...
@@ -125,10 +143,10 @@ function toggleSideBar() {
function
handleCommand
(
command
)
{
switch
(
command
)
{
case
"setLayout"
:
case
'setLayout'
:
setLayout
()
break
case
"logout"
:
case
'logout'
:
logout
()
break
default
:
...
...
@@ -141,11 +159,13 @@ function logout() {
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}).
then
(()
=>
{
userStore
.
logOut
().
then
(()
=>
{
location
.
href
=
'/index'
})
.
then
(()
=>
{
userStore
.
logOut
().
then
(()
=>
{
location
.
href
=
'/index'
})
})
}).
catch
(()
=>
{
})
.
catch
(()
=>
{
})
}
const
emits
=
defineEmits
([
'setLayout'
])
...
...
@@ -158,7 +178,7 @@ function toggleTheme() {
}
</
script
>
<
style
lang=
'scss'
scoped
>
<
style
lang=
"scss"
scoped
>
.tenant-selector
{
margin-left
:
20px
;
cursor
:
pointer
;
...
...
@@ -236,7 +256,7 @@ function toggleTheme() {
svg
{
transition
:
transform
0.3s
;
&:hover
{
transform
:
scale
(
1.15
);
}
...
...
@@ -260,7 +280,7 @@ function toggleTheme() {
border-radius
:
50%
;
}
.user-nickname
{
.user-nickname
{
position
:
relative
;
left
:
5px
;
bottom
:
10px
;
...
...
@@ -278,7 +298,7 @@ function toggleTheme() {
}
}
//
租户选择器样式
//
租户选择器样式
//
.tenant-select
{
//
margin-right
:
10px
;
//
padding
:
0
10px
;
...
...
src/layout/components/Sidebar/Logo.vue
View file @
04757222
<
template
>
<div
class=
"sidebar-logo-container"
:class=
"
{
'collapse'
: collapse }">
<div
class=
"sidebar-logo-container"
:class=
"
{
collapse
: collapse }">
<transition
name=
"sidebarLogoFade"
>
<router-link
v-if=
"collapse"
key=
"collapse"
class=
"sidebar-logo-link"
to=
"/"
>
<img
v-if=
"logo"
:src=
"logo"
class=
"sidebar-logo"
/>
...
...
@@ -14,7 +14,7 @@
</
template
>
<
script
setup
>
import
logo
from
'@/assets/logo/
l
ogo.png'
import
logo
from
'@/assets/logo/
csfL
ogo.png'
import
useSettingsStore
from
'@/store/modules/settings'
import
variables
from
'@/assets/styles/variables.module.scss'
...
...
@@ -68,6 +68,7 @@ const getLogoTextColor = computed(() => {
&
.sidebar-logo-link
{
height
:
100%
;
width
:
100%
;
text-align
:
center
;
&
.sidebar-logo
{
width
:
32px
;
...
...
@@ -94,4 +95,4 @@ const getLogoTextColor = computed(() => {
}
}
}
</
style
>
\ No newline at end of file
</
style
>
src/permission.js
View file @
04757222
...
...
@@ -2,22 +2,32 @@ import router from './router'
import
{
ElMessage
}
from
'element-plus'
import
NProgress
from
'nprogress'
import
'nprogress/nprogress.css'
import
{
getToken
}
from
'@/utils/auth'
import
{
isHttp
,
isPathMatch
}
from
'@/utils/validate'
import
{
isRelogin
}
from
'@/utils/request'
import
useUserStore
from
'@/store/modules/user'
// 使用命名导入
import
useSettingsStore
from
'@/store/modules/settings'
// 使用命名导入
import
useUserStore
from
'@/store/modules/user'
// 使用命名导入
import
useSettingsStore
from
'@/store/modules/settings'
// 使用命名导入
import
usePermissionStore
from
'@/store/modules/permission'
// 使用命名导入
import
{
getToken
,
setToken
,
removeToken
}
from
'@/utils/auth'
NProgress
.
configure
({
showSpinner
:
false
})
const
whiteList
=
[
'/login'
,
'/register'
]
const
isWhiteList
=
(
path
)
=>
{
const
isWhiteList
=
path
=>
{
return
whiteList
.
some
(
pattern
=>
isPathMatch
(
pattern
,
path
))
}
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
console
.
log
(
'跳转进来了'
,
to
)
// 带token是从外部跳转进系统的
if
(
to
.
query
.
token
)
{
setToken
(
to
.
query
.
token
)
useUserStore
().
setProjectInfo
({
tenantBizId
:
to
.
query
.
tenantBizId
,
projectBizId
:
to
.
query
.
projectBizId
})
}
NProgress
.
start
()
if
(
getToken
())
{
to
.
meta
.
title
&&
useSettingsStore
().
setTitle
(
to
.
meta
.
title
)
...
...
@@ -28,28 +38,36 @@ router.beforeEach((to, from, next) => {
}
else
if
(
isWhiteList
(
to
.
path
))
{
next
()
}
else
{
console
.
log
(
'roles'
,
useUserStore
().
roles
.
length
)
if
(
useUserStore
().
roles
.
length
===
0
)
{
isRelogin
.
show
=
true
// 判断当前用户是否已拉取完user_info信息
useUserStore
().
getInfo
().
then
(()
=>
{
isRelogin
.
show
=
false
usePermissionStore
().
generateRoutes
().
then
(
accessRoutes
=>
{
// 根据roles权限生成可访问的路由表
accessRoutes
.
forEach
(
route
=>
{
if
(
!
isHttp
(
route
.
path
))
{
router
.
addRoute
(
route
)
// 动态添加可访问路由表
}
})
next
({
...
to
,
replace
:
true
})
// hack方法 确保addRoutes已完成
useUserStore
()
.
getInfo
()
.
then
(()
=>
{
isRelogin
.
show
=
false
usePermissionStore
()
.
generateRoutes
()
.
then
(
accessRoutes
=>
{
// 根据roles权限生成可访问的路由表
accessRoutes
.
forEach
(
route
=>
{
if
(
!
isHttp
(
route
.
path
))
{
router
.
addRoute
(
route
)
// 动态添加可访问路由表
}
})
next
({
...
to
,
replace
:
true
})
// hack方法 确保addRoutes已完成
})
})
}).
catch
(
err
=>
{
useUserStore
().
logOut
().
then
(()
=>
{
ElMessage
.
error
(
err
)
next
({
path
:
'/'
})
.
catch
(
err
=>
{
useUserStore
()
.
logOut
()
.
then
(()
=>
{
ElMessage
.
error
(
err
)
next
({
path
:
'/'
})
})
})
})
}
else
{
next
()
}
...
...
src/store/modules/permission.js
View file @
04757222
...
...
@@ -9,55 +9,57 @@ import useUserStore from '@/store/modules/user'
// 匹配views里面所有的.vue文件
const
modules
=
import
.
meta
.
glob
(
'./../../views/**/*.vue'
)
const
usePermissionStore
=
defineStore
(
'permission'
,
{
state
:
()
=>
({
routes
:
[],
addRoutes
:
[],
defaultRoutes
:
[],
topbarRouters
:
[],
sidebarRouters
:
[]
}),
actions
:
{
setRoutes
(
routes
)
{
this
.
addRoutes
=
routes
this
.
routes
=
constantRoutes
.
concat
(
routes
)
},
setDefaultRoutes
(
routes
)
{
this
.
defaultRoutes
=
constantRoutes
.
concat
(
routes
)
},
setTopbarRoutes
(
routes
)
{
this
.
topbarRouters
=
routes
},
setSidebarRouters
(
routes
)
{
this
.
sidebarRouters
=
routes
},
generateRoutes
()
{
return
new
Promise
(
resolve
=>
{
const
userStore
=
useUserStore
()
const
tenantBizId
=
userStore
.
currentTenant
.
apiLoginTenantInfoResponse
.
tenantBizId
||
"tenant_1001"
getRouters
(
tenantBizId
).
then
(
res
=>
{
const
sdata
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
))
const
rdata
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
))
const
defaultData
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
))
const
sidebarRoutes
=
filterAsyncRouter
(
sdata
)
const
rewriteRoutes
=
filterAsyncRouter
(
rdata
,
false
,
true
)
const
defaultRoutes
=
filterAsyncRouter
(
defaultData
)
this
.
setRoutes
(
rewriteRoutes
)
this
.
setSidebarRouters
(
constantRoutes
.
concat
(
sidebarRoutes
))
this
.
setDefaultRoutes
(
sidebarRoutes
)
this
.
setTopbarRoutes
(
defaultRoutes
)
resolve
(
rewriteRoutes
)
})
const
usePermissionStore
=
defineStore
(
'permission'
,
{
state
:
()
=>
({
routes
:
[],
addRoutes
:
[],
defaultRoutes
:
[],
topbarRouters
:
[],
sidebarRouters
:
[]
}),
actions
:
{
setRoutes
(
routes
)
{
this
.
addRoutes
=
routes
this
.
routes
=
constantRoutes
.
concat
(
routes
)
console
.
log
(
'===================================='
)
console
.
log
(
'this.routes'
,
this
.
routes
)
console
.
log
(
'===================================='
)
},
setDefaultRoutes
(
routes
)
{
this
.
defaultRoutes
=
constantRoutes
.
concat
(
routes
)
},
setTopbarRoutes
(
routes
)
{
this
.
topbarRouters
=
routes
},
setSidebarRouters
(
routes
)
{
this
.
sidebarRouters
=
routes
},
generateRoutes
()
{
return
new
Promise
(
resolve
=>
{
const
userStore
=
useUserStore
()
const
tenantBizId
=
userStore
.
currentTenant
.
apiLoginTenantInfoResponse
.
tenantBizId
||
'tenant_1001'
getRouters
(
tenantBizId
).
then
(
res
=>
{
const
sdata
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
))
const
rdata
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
))
const
defaultData
=
JSON
.
parse
(
JSON
.
stringify
(
res
.
data
))
const
sidebarRoutes
=
filterAsyncRouter
(
sdata
)
const
rewriteRoutes
=
filterAsyncRouter
(
rdata
,
false
,
true
)
const
defaultRoutes
=
filterAsyncRouter
(
defaultData
)
this
.
setRoutes
(
rewriteRoutes
)
this
.
setSidebarRouters
(
constantRoutes
.
concat
(
sidebarRoutes
))
this
.
setDefaultRoutes
(
sidebarRoutes
)
this
.
setTopbarRoutes
(
defaultRoutes
)
resolve
(
rewriteRoutes
)
})
}
}
)
}
})
}
})
// export default usePermissionStore
...
...
@@ -66,28 +68,28 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
return
asyncRouterMap
.
filter
(
route
=>
{
// 确保路由有有效路径
if
(
!
route
.
path
||
route
.
path
.
trim
()
===
''
)
{
console
.
warn
(
'忽略无效路由项(缺少路径):'
,
route
)
;
return
false
;
console
.
warn
(
'忽略无效路由项(缺少路径):'
,
route
)
return
false
}
// 只处理目录(1)和菜单(2)类型
if
(
route
.
menuType
!==
1
&&
route
.
menuType
!==
2
)
{
return
false
;
return
false
}
// 创建必要的元信息
if
(
!
route
.
meta
)
{
route
.
meta
=
{}
;
route
.
meta
=
{}
}
// 设置菜单标题
route
.
meta
.
title
=
route
.
menuName
;
route
.
meta
.
icon
=
route
.
icon
;
route
.
meta
.
isCache
=
route
.
isCache
===
1
;
route
.
meta
.
title
=
route
.
menuName
route
.
meta
.
icon
=
route
.
icon
route
.
meta
.
isCache
=
route
.
isCache
===
1
//确保单子菜单的父菜单也显示
if
(
route
.
menuType
===
1
)
{
route
.
alwaysShow
=
true
;
// 强制显示父菜单
route
.
alwaysShow
=
true
// 强制显示父菜单
}
// 新增:添加标签页显示属性(关键修改)
...
...
@@ -96,36 +98,36 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
// 确保顶级菜单有布局组件
if
(
route
.
parentBizId
===
'0'
&&
!
route
.
component
)
{
route
.
component
=
'Layout'
;
route
.
component
=
'Layout'
}
// 组件映射处理
if
(
route
.
component
)
{
if
(
route
.
component
===
'Layout'
)
{
route
.
component
=
Layout
;
route
.
component
=
Layout
}
else
if
(
route
.
component
===
'ParentView'
)
{
route
.
component
=
ParentView
;
route
.
component
=
ParentView
}
else
if
(
route
.
component
===
'InnerLink'
)
{
route
.
component
=
InnerLink
;
route
.
component
=
InnerLink
}
else
{
route
.
component
=
loadView
(
route
.
component
)
;
route
.
component
=
loadView
(
route
.
component
)
}
}
// 递归处理子路由
if
(
route
.
children
&&
route
.
children
.
length
)
{
route
.
children
=
filterAsyncRouter
(
route
.
children
,
route
,
type
)
;
route
.
children
=
filterAsyncRouter
(
route
.
children
,
route
,
type
)
// 设置重定向到第一个子路由(对于目录类型)
if
(
route
.
menuType
===
1
&&
route
.
children
.
length
>
0
)
{
route
.
redirect
=
route
.
children
[
0
].
path
;
route
.
redirect
=
route
.
children
[
0
].
path
}
}
else
{
delete
route
.
children
;
delete
route
.
children
}
return
true
;
})
;
return
true
})
}
// // 遍历后台传来的路由字符串,转换为组件对象
// function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
...
...
@@ -185,7 +187,7 @@ export function filterDynamicRoutes(routes) {
return
res
}
export
const
loadView
=
(
view
)
=>
{
export
const
loadView
=
view
=>
{
let
res
for
(
const
path
in
modules
)
{
const
dir
=
path
.
split
(
'views/'
)[
1
].
split
(
'.vue'
)[
0
]
...
...
src/store/modules/user.js
View file @
04757222
import
router
from
'@/router'
import
{
ElMessageBox
,
}
from
'element-plus'
import
{
ElMessageBox
}
from
'element-plus'
import
{
login
,
logout
,
getInfo
}
from
'@/api/login'
import
{
getToken
,
setToken
,
removeToken
}
from
'@/utils/auth'
import
{
isHttp
,
isEmpty
}
from
"@/utils/validate"
import
{
isHttp
,
isEmpty
}
from
'@/utils/validate'
import
defAva
from
'@/assets/images/profile.jpg'
import
usePermissionStore
from
'@/store/modules/permission'
const
useUserStore
=
defineStore
(
'user'
,
{
state
:
()
=>
({
token
:
getToken
()
,
id
:
''
,
name
:
''
,
nickName
:
''
,
avatar
:
''
,
isSuperAdmin
:
0
,
roles
:
[],
permissions
:
[],
tenants
:
[],
// 新增租户列表
currentTenant
:
null
// 新增当前租户
}),
actions
:
{
// 登录
login
(
userInfo
)
{
const
username
=
userInfo
.
username
.
trim
()
const
password
=
userInfo
.
password
const
code
=
userInfo
.
code
const
uuid
=
userInfo
.
uuid
return
new
Promise
((
resolve
,
reject
)
=>
{
login
(
username
,
password
,
code
,
uuid
)
.
then
(
res
=>
{
const
useUserStore
=
defineStore
(
'user'
,
{
state
:
()
=>
({
token
:
getToken
(),
id
:
''
,
name
:
''
,
nickName
:
''
,
avatar
:
''
,
isSuperAdmin
:
0
,
roles
:
[]
,
permissions
:
[]
,
tenants
:
[],
// 新增租户列表
currentTenant
:
null
,
// 新增当前租户
projectInfo
:
null
//保存从中台跳转过来的项目信息
}),
actions
:
{
// 登录
login
(
userInfo
)
{
const
username
=
userInfo
.
username
.
trim
()
const
password
=
userInfo
.
password
const
code
=
userInfo
.
code
const
uuid
=
userInfo
.
uuid
return
new
Promise
((
resolve
,
reject
)
=>
{
login
(
username
,
password
,
code
,
uuid
)
.
then
(
res
=>
{
setToken
(
res
.
data
.
token
)
this
.
token
=
res
.
data
.
token
resolve
()
}).
catch
(
error
=>
{
})
.
catch
(
error
=>
{
reject
(
error
)
})
})
},
// 获取用户信息
getInfo
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
getInfo
().
then
(
res
=>
{
})
},
// 获取用户信息
getInfo
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
getInfo
()
.
then
(
res
=>
{
const
user
=
res
.
data
.
apiLoginUserInfoResponse
let
avatar
=
user
.
avatar
||
""
let
avatar
=
user
.
avatar
||
''
if
(
!
isHttp
(
avatar
))
{
avatar
=
(
isEmpty
(
avatar
)
)
?
defAva
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
avatar
avatar
=
isEmpty
(
avatar
)
?
defAva
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
avatar
}
// 设置租户列表
this
.
tenants
=
res
.
data
.
apiLoginTenantResponseList
||
[]
// 尝试从本地存储获取当前租户,否则使用第一个
const
savedTenant
=
JSON
.
parse
(
localStorage
.
getItem
(
''
+
''
))
const
savedTenant
=
JSON
.
parse
(
localStorage
.
getItem
(
''
+
''
))
const
currentTenant
=
savedTenant
||
(
this
.
tenants
.
length
>
0
?
this
.
tenants
[
0
]
:
null
)
if
(
currentTenant
)
{
...
...
@@ -76,49 +77,56 @@ const useUserStore = defineStore(
this
.
isSuperAdmin
=
user
.
isSuperAdmin
/* 初始密码提示 */
if
(
res
.
data
.
isDefaultModifyPwd
)
{
ElMessageBox
.
confirm
(
'您的密码还是初始密码,请修改密码!'
,
'安全提示'
,
{
if
(
res
.
data
.
isDefaultModifyPwd
)
{
ElMessageBox
.
confirm
(
'您的密码还是初始密码,请修改密码!'
,
'安全提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}).
then
(()
=>
{
router
.
push
({
name
:
'Profile'
,
params
:
{
activeTab
:
'resetPwd'
}
})
}).
catch
(()
=>
{})
})
.
then
(()
=>
{
router
.
push
({
name
:
'Profile'
,
params
:
{
activeTab
:
'resetPwd'
}
})
})
.
catch
(()
=>
{})
}
/* 过期密码提示 */
if
(
!
res
.
data
.
isDefaultModifyPwd
&&
res
.
isPasswordExpired
)
{
ElMessageBox
.
confirm
(
'您的密码已过期,请尽快修改密码!'
,
'安全提示'
,
{
if
(
!
res
.
data
.
isDefaultModifyPwd
&&
res
.
isPasswordExpired
)
{
ElMessageBox
.
confirm
(
'您的密码已过期,请尽快修改密码!'
,
'安全提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}).
then
(()
=>
{
router
.
push
({
name
:
'Profile'
,
params
:
{
activeTab
:
'resetPwd'
}
})
}).
catch
(()
=>
{})
})
.
then
(()
=>
{
router
.
push
({
name
:
'Profile'
,
params
:
{
activeTab
:
'resetPwd'
}
})
})
.
catch
(()
=>
{})
}
resolve
(
res
)
}).
catch
(
error
=>
{
})
.
catch
(
error
=>
{
reject
(
error
)
})
})
},
//切换租户
switchTenant
(
tenant
)
{
return
new
Promise
((
resolve
)
=>
{
this
.
currentTenant
=
tenant
localStorage
.
setItem
(
'currentTenant'
,
JSON
.
stringify
(
tenant
))
})
},
//切换租户
switchTenant
(
tenant
)
{
return
new
Promise
(
resolve
=>
{
this
.
currentTenant
=
tenant
localStorage
.
setItem
(
'currentTenant'
,
JSON
.
stringify
(
tenant
))
// 保存租户ID到专用字段
localStorage
.
setItem
(
'selectedTenantId'
,
tenant
.
apiLoginTenantInfoResponse
.
tenantBizId
)
// 保存租户ID到专用字段
localStorage
.
setItem
(
'selectedTenantId'
,
tenant
.
apiLoginTenantInfoResponse
.
tenantBizId
)
// 更新角色和权限
if
(
tenant
.
roles
&&
tenant
.
roles
.
length
>
0
)
{
this
.
roles
=
tenant
.
roles
this
.
permissions
=
tenant
.
permissions
}
else
{
this
.
roles
=
[
'ROLE_DEFAULT'
]
}
// 更新角色和权限
if
(
tenant
.
roles
&&
tenant
.
roles
.
length
>
0
)
{
this
.
roles
=
tenant
.
roles
this
.
permissions
=
tenant
.
permissions
}
else
{
this
.
roles
=
[
'ROLE_DEFAULT'
]
}
usePermissionStore
().
generateRoutes
().
then
(
accessRoutes
=>
{
usePermissionStore
()
.
generateRoutes
()
.
then
(
accessRoutes
=>
{
// 移除旧路由
const
currentRoutes
=
router
.
getRoutes
()
currentRoutes
.
forEach
(
route
=>
{
...
...
@@ -139,35 +147,41 @@ const useUserStore = defineStore(
// window.location.reload() // 确保完全刷新
// })
})
router
.
push
(
'/workbench'
)
})
},
// 退出系统
logOut
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
this
.
token
=
''
this
.
roles
=
[]
this
.
permissions
=
[]
this
.
tenants
=
[]
this
.
currentTenant
=
null
removeToken
()
localStorage
.
removeItem
(
'currentTenant'
)
resolve
()
// logout(this.token).then(() => {
// this.token = ''
// this.roles = []
// this.permissions = []
// this.tenants = []
// this.currentTenant = null
// removeToken()
// localStorage.removeItem('currentTenant')
// resolve()
// }).catch(error => {
// reject(error)
// })
})
}
router
.
push
(
'/workbench'
)
})
},
// 退出系统
logOut
()
{
return
new
Promise
((
resolve
,
reject
)
=>
{
this
.
token
=
''
this
.
roles
=
[]
this
.
permissions
=
[]
this
.
tenants
=
[]
this
.
currentTenant
=
null
removeToken
()
localStorage
.
removeItem
(
'currentTenant'
)
resolve
()
// logout(this.token).then(() => {
// this.token = ''
// this.roles = []
// this.permissions = []
// this.tenants = []
// this.currentTenant = null
// removeToken()
// localStorage.removeItem('currentTenant')
// resolve()
// }).catch(error => {
// reject(error)
// })
})
},
clearRoles
()
{
this
.
roles
=
[]
},
setProjectInfo
(
project
)
{
this
.
projectInfo
=
project
}
})
}
})
export
default
useUserStore
src/views/index.vue
View file @
04757222
...
...
@@ -20,10 +20,7 @@
@
click=
"goTarget('https://gitee.com/y_project/RuoYi-Vue')"
>
访问码云
</el-button
>
<el-button
icon=
"HomeFilled"
plain
@
click=
"goTarget('http://ruoyi.vip')"
<el-button
icon=
"HomeFilled"
plain
@
click=
"goTarget('http://ruoyi.vip')"
>
访问主页
</el-button
>
</p>
...
...
@@ -83,22 +80,20 @@
<p>
<i
class=
"el-icon-user-solid"
></i>
QQ群:
<s>
满937441
</s>
<s>
满887144332
</s>
<s>
满180251782
</s>
<s>
满104180207
</s>
<s>
满186866453
</s>
<s>
满201396349
</s>
<s>
满101456076
</s>
<s>
满101539465
</s>
<s>
满264312783
</s>
<s>
满167385320
</s>
<s>
满104748341
</s>
<s>
满160110482
</s>
<s>
满170801498
</s>
<s>
满108482800
</s>
<s>
满101046199
</s>
<s>
满136919097
</s>
<s>
满143961921
</s>
<s>
满174951577
</s>
<s>
满101456076
</s>
<s>
满101539465
</s>
<s>
满264312783
</s>
<s>
满167385320
</s>
<s>
满104748341
</s>
<s>
满160110482
</s>
<s>
满170801498
</s>
<s>
满108482800
</s>
<s>
满101046199
</s>
<s>
满136919097
</s>
<s>
满143961921
</s>
<s>
满174951577
</s>
<s>
满161281055
</s>
<s>
满138988063
</s>
<s>
满151450850
</s>
<s>
满224622315
</s>
<s>
满287842588
</s>
<s>
满187944233
</s>
<s>
满228578329
</s>
<a
href=
"http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766"
target=
"_blank"
>
191164766
</a>
</p>
<p>
<i
class=
"el-icon-chat-dot-round"
></i>
微信:
<a
href=
"javascript:;"
>
/ *若依
</a
<s>
满287842588
</s>
<s>
满187944233
</s>
<s>
满228578329
</s>
<a
href=
"http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766"
target=
"_blank"
>
191164766
</a
>
</p>
<p><i
class=
"el-icon-chat-dot-round"
></i>
微信:
<a
href=
"javascript:;"
>
/ *若依
</a></p>
<p>
<i
class=
"el-icon-money"
></i>
支付宝:
<a
href=
"javascript:;"
class=
"支付宝信息"
<i
class=
"el-icon-money"
></i>
支付宝:
<a
href=
"javascript:;"
class=
"支付宝信息"
>
/ *若依
</a
>
</p>
...
...
@@ -878,9 +873,7 @@
<li>
调整表头固定列默认样式
</li>
<li>
代码生成模板调整,字段为String并且必填则加空串条件
</li>
<li>
代码生成字典Integer/Long使用parseInt
</li>
<li>
修复dict_sort不可update为0的问题
&
查询返回增加dict_sort升序排序
</li>
<li>
修复dict_sort不可update为0的问题
&
查询返回增加dict_sort升序排序
</li>
<li>
修正岗位导出权限注解
</li>
<li>
禁止加密密文返回前端
</li>
<li>
修复代码生成页面中的查询条件创建时间未生效的问题
</li>
...
...
@@ -1042,11 +1035,7 @@
</div>
</
template
>
<div
class=
"body"
>
<img
src=
"@/assets/images/pay.png"
alt=
"donate"
style=
"width:100%"
/>
<img
src=
"@/assets/images/pay.png"
alt=
"donate"
style=
"width: 100%"
/>
<span
style=
"display: inline-block; height: 30px; line-height: 30px"
>
你可以请作者喝杯咖啡表示鼓励
</span
>
...
...
@@ -1088,7 +1077,7 @@ function goTarget(url) {
margin
:
0
;
}
font-family
:
"open sans"
,
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
font-family
:
'open sans'
,
'Helvetica Neue'
,
Helvetica
,
Arial
,
sans-serif
;
font-size
:
13px
;
color
:
#676a6c
;
overflow-x
:
hidden
;
...
...
@@ -1128,4 +1117,3 @@ function goTarget(url) {
}
}
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment