Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Simoje丶
vue-vben-admin
提交
31e2715e
V
vue-vben-admin
项目概览
Simoje丶
/
vue-vben-admin
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vue-vben-admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
31e2715e
编写于
10月 14, 2020
作者:
V
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: detail optimization
上级
74378960
变更
27
隐藏空白更改
内联
并排
Showing
27 changed file
with
304 addition
and
93 deletion
+304
-93
build/script/updateHtml.ts
build/script/updateHtml.ts
+4
-4
build/transform/require-context/index.ts
build/transform/require-context/index.ts
+95
-0
build/utils.ts
build/utils.ts
+8
-12
src/components/CountTo/src/index.vue
src/components/CountTo/src/index.vue
+4
-1
src/components/Menu/src/BasicMenu.tsx
src/components/Menu/src/BasicMenu.tsx
+5
-3
src/components/Menu/src/index.less
src/components/Menu/src/index.less
+31
-3
src/design/var/index.less
src/design/var/index.less
+1
-1
src/hooks/web/useTabs.ts
src/hooks/web/useTabs.ts
+10
-5
src/layouts/default/index.tsx
src/layouts/default/index.tsx
+5
-0
src/layouts/default/multitabs/index.tsx
src/layouts/default/multitabs/index.tsx
+3
-6
src/layouts/page/index.tsx
src/layouts/page/index.tsx
+2
-1
src/router/guard/index.ts
src/router/guard/index.ts
+4
-2
src/router/guard/pageLoadingGuard.ts
src/router/guard/pageLoadingGuard.ts
+10
-2
src/router/menus/index.ts
src/router/menus/index.ts
+2
-1
src/router/menus/modules/demo/feat.ts
src/router/menus/modules/demo/feat.ts
+14
-0
src/router/routes/index.ts
src/router/routes/index.ts
+9
-2
src/router/routes/modules/demo/feat.ts
src/router/routes/modules/demo/feat.ts
+8
-0
src/router/routes/modules/sys.ts
src/router/routes/modules/sys.ts
+0
-12
src/router/types.d.ts
src/router/types.d.ts
+1
-0
src/store/modules/tab.ts
src/store/modules/tab.ts
+26
-15
src/types/source.d.ts
src/types/source.d.ts
+3
-1
src/utils/eventHub.ts
src/utils/eventHub.ts
+0
-3
src/utils/helper/menuHelper.ts
src/utils/helper/menuHelper.ts
+2
-2
src/utils/helper/routeHelper.ts
src/utils/helper/routeHelper.ts
+26
-1
src/views/demo/feat/tab-params/index.vue
src/views/demo/feat/tab-params/index.vue
+17
-0
src/views/sys/redirect/index.vue
src/views/sys/redirect/index.vue
+13
-15
vite.config.ts
vite.config.ts
+1
-1
未找到文件。
build/script/updateHtml.ts
浏览文件 @
31e2715e
...
...
@@ -74,9 +74,7 @@ function injectCdnjs(html: string) {
export
async
function
runUpdateHtml
()
{
const
outDir
=
viteConfig
.
outDir
||
'
dist
'
;
const
indexPath
=
getCwdPath
(
outDir
,
'
index.html
'
);
if
(
!
existsSync
(
`
${
indexPath
}
`
))
{
return
;
}
if
(
!
existsSync
(
indexPath
))
return
;
try
{
let
processedHtml
=
''
;
const
rawHtml
=
readFileSync
(
indexPath
,
'
utf-8
'
);
...
...
@@ -92,7 +90,9 @@ export async function runUpdateHtml() {
}
if
(
minify
)
{
const
{
enable
,
...
miniOpt
}
=
minify
;
processedHtml
=
HtmlMinifier
.
minify
(
processedHtml
,
miniOpt
);
if
(
enable
)
{
processedHtml
=
HtmlMinifier
.
minify
(
processedHtml
,
miniOpt
);
}
}
writeFileSync
(
indexPath
,
processedHtml
);
...
...
build/transform/require-context/index.ts
0 → 100644
浏览文件 @
31e2715e
// https://github.com/luxueyan/vite-transform-globby-import/blob/master/src/index.ts
// TODO 目前还不能监听文件新增及删除 内容已经改变,缓存问题?
// 可以使用,先不打算集成
import
{
join
}
from
'
path
'
;
import
{
lstatSync
}
from
'
fs
'
;
import
glob
from
'
glob
'
;
import
{
createResolver
,
Resolver
}
from
'
vite/dist/node/resolver.js
'
;
import
{
Transform
}
from
'
vite/dist/node/transform.js
'
;
const
modulesDir
:
string
=
join
(
process
.
cwd
(),
'
/node_modules/
'
);
interface
SharedConfig
{
root
?:
string
;
alias
?:
Record
<
string
,
string
>
;
resolvers
?:
Resolver
[];
}
function
template
(
template
:
string
)
{
return
(
data
:
{
[
x
:
string
]:
any
})
=>
{
return
template
.
replace
(
/#
([^
#
]
+
)
#/g
,
(
_
,
g1
)
=>
data
[
g1
]
||
g1
);
};
}
const
globbyTransform
=
function
(
config
:
SharedConfig
):
Transform
{
const
resolver
=
createResolver
(
config
.
root
||
process
.
cwd
(),
config
.
resolvers
||
[],
config
.
alias
||
{}
);
const
cache
=
new
Map
();
const
urlMap
=
new
Map
();
return
{
test
({
path
})
{
const
filePath
=
path
.
replace
(
'
\
u0000
'
,
''
);
// why some path startsWith '\u0000'?
try
{
return
(
!
filePath
.
startsWith
(
modulesDir
)
&&
/
\.(
vue|js|jsx|ts|tsx
)
$/
.
test
(
filePath
)
&&
lstatSync
(
filePath
).
isFile
()
);
}
catch
{
return
false
;
}
},
transform
({
code
,
path
,
isBuild
})
{
let
result
=
cache
.
get
(
path
);
if
(
!
result
)
{
const
reg
=
/import
\s
+
([\w\s
{}*
]
+
)\s
+from
\s
+
([
'"
])
globby
(\?
path
)?
!
([^
'"
]
+
)\2
/g
;
const
lastImport
=
urlMap
.
get
(
path
);
const
match
=
code
.
match
(
reg
);
if
(
lastImport
&&
match
)
{
code
=
code
.
replace
(
lastImport
,
match
[
0
]);
}
result
=
code
.
replace
(
reg
,
(
_
,
g1
,
g2
,
g3
,
g4
)
=>
{
const
filePath
=
path
.
replace
(
'
\
u0000
'
,
''
);
// why some path startsWith '\u0000'?
// resolve path
const
resolvedFilePath
=
g4
.
startsWith
(
'
.
'
)
?
resolver
.
resolveRelativeRequest
(
filePath
,
g4
)
:
{
pathname
:
resolver
.
requestToFile
(
g4
)
};
const
files
=
glob
.
sync
(
resolvedFilePath
.
pathname
,
{
dot
:
true
});
let
templateStr
=
'
import #name# from #file#
'
;
// import default
let
name
=
g1
;
const
m
=
g1
.
match
(
/
\{\s
*
(\w
+
)(\s
+as
\s
+
(\w
+
))?\s
*
\}
/
);
// import module
const
m2
=
g1
.
match
(
/
\*\s
+as
\s
+
(\w
+
)
/
);
// import * as all module
if
(
m
)
{
templateStr
=
`import {
${
m
[
1
]}
as #name# } from #file#`
;
name
=
m
[
3
]
||
m
[
1
];
}
else
if
(
m2
)
{
templateStr
=
'
import * as #name# from #file#
'
;
name
=
m2
[
1
];
}
const
temRender
=
template
(
templateStr
);
const
groups
:
Array
<
string
>
[]
=
[];
const
replaceFiles
=
files
.
map
((
f
,
i
)
=>
{
const
file
=
g2
+
resolver
.
fileToRequest
(
f
)
+
g2
;
groups
.
push
([
name
+
i
,
file
]);
return
temRender
({
name
:
name
+
i
,
file
});
});
urlMap
.
set
(
path
,
replaceFiles
.
join
(
'
\n
'
));
return
(
replaceFiles
.
join
(
'
\n
'
)
+
(
g3
?
'
\n
'
+
groups
.
map
((
v
)
=>
`
${
v
[
0
]}
._path =
${
v
[
1
]}
`
).
join
(
'
\n
'
)
:
''
)
+
`\nconst
${
name
}
= {
${
groups
.
map
((
v
)
=>
v
[
0
]).
join
(
'
,
'
)}
}\n`
);
});
if
(
isBuild
)
cache
.
set
(
path
,
result
);
}
return
result
;
},
};
};
export
default
globbyTransform
;
build/utils.ts
浏览文件 @
31e2715e
...
...
@@ -124,28 +124,24 @@ export function getEnvConfig(match = 'VITE_GLOB_', confFiles = ['.env', '.env.pr
return
envConfig
;
}
export
function
successConsole
(
message
:
any
)
{
function
consoleFn
(
color
:
string
,
message
:
any
)
{
console
.
log
(
chalk
.
blue
.
bold
(
'
****************
'
)
+
chalk
.
green
.
bold
(
'
✨
'
+
message
)
+
(
chalk
as
any
)[
color
].
bold
(
message
)
+
chalk
.
blue
.
bold
(
'
****************
'
)
);
}
export
function
successConsole
(
message
:
any
)
{
consoleFn
(
'
green
'
,
'
✨
'
+
message
);
}
export
function
errorConsole
(
message
:
any
)
{
console
.
log
(
chalk
.
blue
.
bold
(
'
****************
'
)
+
chalk
.
red
.
bold
(
'
✨
'
+
message
)
+
chalk
.
blue
.
bold
(
'
****************
'
)
);
consoleFn
(
'
red
'
,
'
✨
'
+
message
);
}
export
function
warnConsole
(
message
:
any
)
{
console
.
log
(
chalk
.
blue
.
bold
(
'
****************
'
)
+
chalk
.
yellow
.
bold
(
'
✨
'
+
message
)
+
chalk
.
blue
.
bold
(
'
****************
'
)
);
consoleFn
(
'
yellow
'
,
'
✨
'
+
message
);
}
export
function
getCwdPath
(...
dir
:
string
[])
{
...
...
src/components/CountTo/src/index.vue
浏览文件 @
31e2715e
...
...
@@ -5,7 +5,6 @@
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
reactive
,
computed
,
watch
,
onMounted
,
unref
,
toRef
}
from
'
vue
'
;
import
{
countToProps
}
from
'
./props
'
;
import
{
useRaf
}
from
'
/@/hooks/event/useRaf
'
;
import
{
isNumber
}
from
'
/@/utils/is
'
;
...
...
@@ -37,12 +36,14 @@
remaining
:
null
,
rAF
:
null
,
});
onMounted
(()
=>
{
if
(
props
.
autoplay
)
{
start
();
}
emit
(
'
mounted
'
);
});
const
getCountDown
=
computed
(()
=>
{
return
props
.
startVal
>
props
.
endVal
;
});
...
...
@@ -61,6 +62,7 @@
state
.
paused
=
false
;
state
.
rAF
=
requestAnimationFrame
(
count
);
}
function
pauseResume
()
{
if
(
state
.
paused
)
{
resume
();
...
...
@@ -70,6 +72,7 @@
state
.
paused
=
true
;
}
}
function
pause
()
{
cancelAnimationFrame
(
state
.
rAF
);
}
...
...
src/components/Menu/src/BasicMenu.tsx
浏览文件 @
31e2715e
...
...
@@ -7,7 +7,7 @@ import { Menu } from 'ant-design-vue';
import
{
MenuModeEnum
,
MenuTypeEnum
}
from
'
/@/enums/menuEnum
'
;
import
{
menuStore
}
from
'
/@/store/modules/menu
'
;
import
{
getSlot
}
from
'
/@/utils/helper/tsxHelper
'
;
import
{
ScrollContainer
}
from
'
/@/components/Container/index
'
;
//
import { ScrollContainer } from '/@/components/Container/index';
import
SearchInput
from
'
./SearchInput.vue
'
;
import
'
./index.less
'
;
import
{
menuHasChildren
}
from
'
./helper
'
;
...
...
@@ -67,6 +67,7 @@ export default defineComponent({
return
{
height
:
`calc(100% -
${
offset
}
px)`
,
position
:
'
relative
'
,
overflow
:
'
auto
'
,
};
});
...
...
@@ -246,8 +247,9 @@ export default defineComponent({
onClick
=
{
handleInputClick
}
collapsed
=
{
getCollapsedState
}
/>
<
section
style
=
{
unref
(
getMenuWrapStyle
)
}
>
<
ScrollContainer
>
{
()
=>
renderMenu
()
}
</
ScrollContainer
>
<
section
style
=
{
unref
(
getMenuWrapStyle
)
}
class
=
"basic-menu__wrap"
>
{
renderMenu
()
}
{
/* <ScrollContainer>{() => renderMenu()}</ScrollContainer> */
}
</
section
>
</
section
>
);
...
...
src/components/Menu/src/index.less
浏览文件 @
31e2715e
...
...
@@ -14,6 +14,30 @@
}
.basic-menu {
&__wrap {
/* 滚动槽 */
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
// TODO 滚动条样式-待修改
&::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0);
}
/* 滚动条滑块 */
&::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 4px;
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
}
::-webkit-scrollbar-thumb:hover {
background: @border-color-dark;
}
}
.ant-menu-submenu:first-of-type {
margin-top: 4px;
}
...
...
@@ -95,14 +119,14 @@
.ant-menu-submenu-active,
.ant-menu-submenu-title:hover {
background: @top-menu-active-bg-color;
border-radius: 6px 6px 0 0;
//
border-radius: 6px 6px 0 0;
}
.basic-menu-item__level1 {
&.ant-menu-item-selected,
&.ant-menu-submenu-selected {
background: @top-menu-active-bg-color;
border-radius: 6px 6px 0 0;
//
border-radius: 6px 6px 0 0;
}
}
...
...
@@ -148,6 +172,10 @@
}
.basic-menu-item__level1 {
> .ant-menu-sub > li {
background-color: @sub-menu-item-dark-bg-color;
}
margin-bottom: 0;
&.top-active-menu {
...
...
@@ -179,7 +207,7 @@
.ant-menu-submenu-title {
height: @app-menu-item-height;
margin: 0;
//
margin: 0;
line-height: @app-menu-item-height;
}
}
...
...
src/design/var/index.less
浏览文件 @
31e2715e
...
...
@@ -18,4 +18,4 @@
// app menu
// left-menu
@app-menu-item-height: 4
4
px;
@app-menu-item-height: 4
8
px;
src/hooks/web/useTabs.ts
浏览文件 @
31e2715e
import
type
{
AppRouteRecordRaw
}
from
'
/@/router/types.d
'
;
import
{
useTimeout
}
from
'
/@/hooks/core/useTimeout
'
;
import
{
PageEnum
}
from
'
/@/enums/pageEnum
'
;
import
{
TabItem
,
tabStore
}
from
'
/@/store/modules/tab
'
;
import
{
appStore
}
from
'
/@/store/modules/app
'
;
import
router
from
'
/@/router
'
;
import
{
ref
}
from
'
vue
'
;
import
{
pathToRegexp
}
from
'
path-to-regexp
'
;
const
activeKeyRef
=
ref
<
string
>
(
''
);
...
...
@@ -68,7 +68,11 @@ export function useTabs() {
function
getTo
(
path
:
string
):
any
{
const
routes
=
router
.
getRoutes
();
const
fn
=
(
p
:
string
):
any
=>
{
const
to
=
routes
.
find
((
item
)
=>
item
.
path
===
p
);
const
to
=
routes
.
find
((
item
)
=>
{
if
(
item
.
path
===
'
/:path(.*)*
'
)
return
;
const
regexp
=
pathToRegexp
(
item
.
path
);
return
regexp
.
test
(
p
);
});
if
(
!
to
)
return
''
;
if
(
!
to
.
redirect
)
return
to
;
if
(
to
.
redirect
)
{
...
...
@@ -88,12 +92,13 @@ export function useTabs() {
resetCache
:
()
=>
canIUseFn
()
&&
resetCache
(),
addTab
:
(
path
:
PageEnum
,
goTo
=
false
,
replace
=
false
)
=>
{
const
to
=
getTo
(
path
);
if
(
!
to
)
return
;
useTimeout
(()
=>
{
tabStore
.
addTabByPathAction
(
(
to
as
unknown
)
as
AppRouteRecordRaw
);
tabStore
.
addTabByPathAction
();
},
0
);
activeKeyRef
.
value
=
to
.
path
;
goTo
&&
replace
?
router
.
replace
:
router
.
push
(
to
.
path
);
activeKeyRef
.
value
=
path
;
goTo
&&
replace
?
router
.
replace
:
router
.
push
(
path
);
},
activeKeyRef
,
};
...
...
src/layouts/default/index.tsx
浏览文件 @
31e2715e
...
...
@@ -82,10 +82,13 @@ export default defineComponent({
{
()
=>
(
<>
{
isLock
&&
<
LockPage
/>
}
{
!
unref
(
getFullContent
)
&&
unref
(
isShowMixHeaderRef
)
&&
unref
(
showHeaderRef
)
&&
(
<
LayoutHeader
/>
)
}
{
showSettingButton
&&
<
SettingBtn
/>
}
<
Layout
>
{
()
=>
(
<>
...
...
@@ -102,7 +105,9 @@ export default defineComponent({
{
()
=>
<
MultipleTabs
/>
}
</
Layout
.
Header
>
)
}
{
useOpenBackTop
&&
<
BackTop
target
=
{
getTarget
}
/>
}
<
div
class
=
{
[
`default-layout__main`
,
fixedHeaderCls
]
}
>
{
openPageLoading
&&
(
<
FullLoading
...
...
src/layouts/default/multitabs/index.tsx
浏览文件 @
31e2715e
...
...
@@ -9,6 +9,7 @@ import {
// ref,
unref
,
onMounted
,
toRaw
,
}
from
'
vue
'
;
import
{
Tabs
}
from
'
ant-design-vue
'
;
import
TabContent
from
'
./TabContent
'
;
...
...
@@ -73,11 +74,7 @@ export default defineComponent({
routes
&&
routes
.
forEach
((
route
)
=>
{
if
(
route
.
meta
&&
route
.
meta
.
affix
)
{
tabs
.
push
({
path
:
route
.
path
,
name
:
route
.
name
,
meta
:
{
...
route
.
meta
},
});
tabs
.
push
(
toRaw
(
route
)
as
TabItem
);
}
});
return
tabs
;
...
...
@@ -114,7 +111,7 @@ export default defineComponent({
};
return
(
<
span
>
<
TabContent
{
...
tabContentProps
}
/>
<
TabContent
{
...
(
tabContentProps
as
any
)
}
/>
</
span
>
);
}
...
...
src/layouts/page/index.tsx
浏览文件 @
31e2715e
...
...
@@ -40,7 +40,8 @@ export default defineComponent({
<
RouterView
>
{
{
default
:
({
Component
,
route
}:
{
Component
:
any
;
route
:
RouteLocation
})
=>
{
const
name
=
route
.
meta
.
inTab
?
'
'
:
null
;
// 已经位于tab内的不再显示动画
const
name
=
route
.
meta
.
inTab
?
'
fade
'
:
null
;
const
Content
=
openCache
?
(
<
KeepAlive
max
=
{
max
}
include
=
{
cacheTabs
}
>
<
Component
{
...
route
.
params
}
/>
...
...
src/router/guard/index.ts
浏览文件 @
31e2715e
...
...
@@ -7,7 +7,7 @@ import { createProgressGuard } from './progressGuard';
import
{
createPermissionGuard
}
from
'
./permissionGuard
'
;
import
{
createPageLoadingGuard
}
from
'
./pageLoadingGuard
'
;
import
{
useSetting
}
from
'
/@/hooks/core/useSetting
'
;
import
{
getIsOpenTab
}
from
'
/@/utils/helper/routeHelper
'
;
import
{
getIsOpenTab
,
setCurrentTo
}
from
'
/@/utils/helper/routeHelper
'
;
const
{
projectSetting
}
=
useSetting
();
export
function
createGuard
(
router
:
Router
)
{
...
...
@@ -17,7 +17,7 @@ export function createGuard(router: Router) {
axiosCanceler
=
new
AxiosCanceler
();
}
router
.
beforeEach
(
async
(
to
)
=>
{
const
isOpen
=
getIsOpenTab
(
to
.
p
ath
);
const
isOpen
=
getIsOpenTab
(
to
.
fullP
ath
);
to
.
meta
.
inTab
=
isOpen
;
try
{
if
(
closeMessageOnSwitch
)
{
...
...
@@ -30,6 +30,8 @@ export function createGuard(router: Router) {
}
catch
(
error
)
{
console
.
warn
(
'
basic guard error:
'
+
error
);
}
setCurrentTo
(
to
);
return
true
;
});
openNProgress
&&
createProgressGuard
(
router
);
createPermissionGuard
(
router
);
...
...
src/router/guard/pageLoadingGuard.ts
浏览文件 @
31e2715e
...
...
@@ -2,6 +2,7 @@ import type { Router } from 'vue-router';
import
{
tabStore
}
from
'
/@/store/modules/tab
'
;
import
{
appStore
}
from
'
/@/store/modules/app
'
;
import
{
userStore
}
from
'
/@/store/modules/user
'
;
import
{
getParams
}
from
'
/@/utils/helper/routeHelper
'
;
export
function
createPageLoadingGuard
(
router
:
Router
)
{
let
isFirstLoad
=
true
;
...
...
@@ -29,9 +30,16 @@ export function createPageLoadingGuard(router: Router) {
}
return
true
;
});
router
.
afterEach
(
async
(
to
)
=>
{
router
.
afterEach
(
async
(
to
,
from
)
=>
{
const
{
openRouterTransition
,
openPageLoading
}
=
appStore
.
getProjectConfig
;
if
((
!
openRouterTransition
&&
openPageLoading
)
||
isFirstLoad
||
to
.
meta
.
afterCloseLoading
)
{
const
realToPath
=
to
.
path
.
replace
(
getParams
(
to
),
''
);
const
realFormPath
=
from
.
path
.
replace
(
getParams
(
from
),
''
);
if
(
(
!
openRouterTransition
&&
openPageLoading
)
||
isFirstLoad
||
to
.
meta
.
afterCloseLoading
||
realToPath
===
realFormPath
)
{
setTimeout
(()
=>
{
appStore
.
commitPageLoadingState
(
false
);
},
110
);
...
...
src/router/menus/index.ts
浏览文件 @
31e2715e
...
...
@@ -107,7 +107,8 @@ export async function getFlatChildrenMenus(children: Menu[]) {
function
basicFilter
(
routes
:
RouteRecordNormalized
[])
{
return
(
menu
:
Menu
)
=>
{
const
matchRoute
=
routes
.
find
((
route
)
=>
route
.
path
===
menu
.
path
);
if
(
!
matchRoute
)
return
false
;
if
(
!
matchRoute
)
return
true
;
menu
.
icon
=
menu
.
icon
||
matchRoute
.
meta
.
icon
;
menu
.
meta
=
matchRoute
.
meta
;
return
true
;
...
...
src/router/menus/modules/demo/feat.ts
浏览文件 @
31e2715e
...
...
@@ -45,6 +45,20 @@ const menu: MenuModule = {
path
:
'
/full-screen
'
,
name
:
'
全屏
'
,
},
{
path
:
'
/testTab
'
,
name
:
'
带参Tab
'
,
children
:
[
{
path
:
'
/id1
'
,
name
:
'
带参tab1
'
,
},
{
path
:
'
/id2
'
,
name
:
'
带参tab2
'
,
},
],
},
],
},
};
...
...
src/router/routes/index.ts
浏览文件 @
31e2715e
...
...
@@ -3,8 +3,6 @@ import type { AppRouteRecordRaw, AppRouteModule } from '/@/router/types';
import
{
DEFAULT_LAYOUT_COMPONENT
,
PAGE_NOT_FOUND_ROUTE
,
REDIRECT_ROUTE
}
from
'
../constant
'
;
import
{
genRouteModule
}
from
'
/@/utils/helper/routeHelper
'
;
import
LoginRoute
from
'
./modules/sys
'
;
import
dashboard
from
'
./modules/dashboard
'
;
// demo
...
...
@@ -48,5 +46,14 @@ export const RootRoute: AppRouteRecordRaw = {
children
:
[],
};
export
const
LoginRoute
:
AppRouteRecordRaw
=
{
path
:
'
/login
'
,
name
:
'
Login
'
,
component
:
()
=>
import
(
'
/@/views/sys/login/Login.vue
'
),
meta
:
{
title
:
'
登录
'
,
},
};
// 基础路由 不用权限
export
const
basicRoutes
=
[
LoginRoute
,
RootRoute
];
src/router/routes/modules/demo/feat.ts
浏览文件 @
31e2715e
...
...
@@ -96,5 +96,13 @@ export default {
title
:
'
全屏
'
,
},
},
{
path
:
'
/testTab/:id
'
,
name
:
'
TestTab
'
,
component
:
()
=>
import
(
'
/@/views/demo/feat/tab-params/index.vue
'
),
meta
:
{
title
:
'
Tab带参
'
,
},
},
],
}
as
AppRouteModule
;
src/router/routes/modules/sys.ts
已删除
100644 → 0
浏览文件 @
74378960
import
type
{
AppRouteRecordRaw
}
from
'
/@/router/types
'
;
const
routes
:
AppRouteRecordRaw
=
{
path
:
'
/login
'
,
name
:
'
Login
'
,
component
:
()
=>
import
(
'
/@/views/sys/login/Login.vue
'
),
meta
:
{
title
:
'
登录
'
,
},
};
export
default
routes
;
src/router/types.d.ts
浏览文件 @
31e2715e
...
...
@@ -39,6 +39,7 @@ export interface AppRouteRecordRaw extends Omit<RouteRecordRaw, 'meta'> {
components
?:
any
;
children
?:
AppRouteRecordRaw
[];
props
?:
any
;
fullPath
?:
string
;
}
export
interface
Menu
{
...
...
src/store/modules/tab.ts
浏览文件 @
31e2715e
...
...
@@ -11,6 +11,7 @@ import { appStore } from '/@/store/modules/app';
import
store
from
'
/@/store
'
;
import
router
from
'
/@/router
'
;
import
{
PAGE_NOT_FOUND_ROUTE
,
REDIRECT_ROUTE
}
from
'
/@/router/constant
'
;
import
{
getCurrentTo
}
from
'
/@/utils/helper/routeHelper
'
;
type
CacheName
=
string
|
symbol
|
null
|
undefined
;
/**
...
...
@@ -18,7 +19,10 @@ type CacheName = string | symbol | null | undefined;
*/
// declare namespace TabsStore {
export
interface
TabItem
{
path
:
string
;
fullPath
:
string
;
path
?:
string
;
params
?:
any
;
query
?:
any
;
name
?:
CacheName
;
meta
?:
RouteMeta
;
}
...
...
@@ -86,20 +90,21 @@ class Tab extends VuexModule {
*/
@
Mutation
commitAddTab
(
route
:
AppRouteRecordRaw
|
TabItem
):
void
{
const
{
path
,
name
,
meta
}
=
route
;
const
{
path
,
name
,
meta
,
fullPath
,
params
,
query
}
=
route
as
TabItem
;
// 404 页面不需要添加tab
if
(
path
===
PageEnum
.
ERROR_PAGE
)
{
return
;
}
else
if
([
REDIRECT_ROUTE
.
name
,
PAGE_NOT_FOUND_ROUTE
.
name
].
includes
(
name
as
string
))
{
return
;
}
// 已经存在的页面,不重复添加tab
const
hasTab
=
this
.
tabsState
.
some
((
tab
)
=>
{
return
tab
.
path
===
p
ath
;
return
tab
.
fullPath
===
fullP
ath
;
});
if
(
hasTab
)
return
;
this
.
tabsState
.
push
({
path
,
name
,
meta
});
this
.
tabsState
.
push
({
path
,
fullPath
,
name
,
meta
,
params
,
query
});
if
(
unref
(
getOpenKeepAliveRef
)
&&
name
)
{
const
noKeepAlive
=
meta
&&
meta
.
ignoreKeepAlive
;
const
hasName
=
this
.
keepAliveTabsState
.
includes
(
name
);
...
...
@@ -113,9 +118,9 @@ class Tab extends VuexModule {
@
Mutation
commitCloseTab
(
route
:
AppRouteRecordRaw
|
TabItem
):
void
{
try
{
const
{
p
ath
,
name
,
meta
:
{
affix
}
=
{}
}
=
route
;
const
{
fullP
ath
,
name
,
meta
:
{
affix
}
=
{}
}
=
route
;
if
(
affix
)
return
;
const
index
=
this
.
tabsState
.
findIndex
((
item
)
=>
item
.
path
===
p
ath
);
const
index
=
this
.
tabsState
.
findIndex
((
item
)
=>
item
.
fullPath
===
fullP
ath
);
index
!==
-
1
&&
this
.
tabsState
.
splice
(
index
,
1
);
if
(
unref
(
getOpenKeepAliveRef
)
&&
name
)
{
...
...
@@ -153,7 +158,7 @@ class Tab extends VuexModule {
@
Mutation
closeMultipleTab
({
pathList
,
nameList
}:
{
pathList
:
string
[];
nameList
:
string
[]
}):
void
{
this
.
tabsState
=
toRaw
(
this
.
tabsState
).
filter
((
item
)
=>
!
pathList
.
includes
(
item
.
p
ath
));
this
.
tabsState
=
toRaw
(
this
.
tabsState
).
filter
((
item
)
=>
!
pathList
.
includes
(
item
.
fullP
ath
));
if
(
unref
(
getOpenKeepAliveRef
)
&&
nameList
)
{
this
.
keepAliveTabsState
=
toRaw
(
this
.
keepAliveTabsState
).
filter
(
(
item
)
=>
!
nameList
.
includes
(
item
as
string
)
...
...
@@ -172,7 +177,7 @@ class Tab extends VuexModule {
for
(
const
item
of
leftTabs
)
{
const
affix
=
item
.
meta
?
item
.
meta
.
affix
:
false
;
if
(
!
affix
)
{
pathList
.
push
(
item
.
p
ath
);
pathList
.
push
(
item
.
fullP
ath
);
nameList
.
push
(
item
.
name
as
string
);
}
}
...
...
@@ -181,13 +186,19 @@ class Tab extends VuexModule {
}
@
Action
addTabByPathAction
(
to
:
AppRouteRecordRaw
):
void
{
to
&&
this
.
commitAddTab
((
to
as
unknown
)
as
AppRouteRecordRaw
);
addTabByPathAction
():
void
{
const
toRoute
=
getCurrentTo
();
if
(
!
toRoute
)
return
;
const
{
meta
}
=
toRoute
;
if
(
meta
&&
meta
.
affix
)
{
return
;
}
this
.
commitAddTab
((
toRoute
as
unknown
)
as
AppRouteRecordRaw
);
}
@
Action
closeRightTabAction
(
route
:
AppRouteRecordRaw
|
TabItem
):
void
{
const
index
=
this
.
tabsState
.
findIndex
((
item
)
=>
item
.
path
===
route
.
p
ath
);
const
index
=
this
.
tabsState
.
findIndex
((
item
)
=>
item
.
fullPath
===
route
.
fullP
ath
);
if
(
index
>=
0
&&
index
<
this
.
tabsState
.
length
-
1
)
{
const
rightTabs
=
this
.
tabsState
.
slice
(
index
+
1
,
this
.
tabsState
.
length
);
...
...
@@ -197,7 +208,7 @@ class Tab extends VuexModule {
for
(
const
item
of
rightTabs
)
{
const
affix
=
item
.
meta
?
item
.
meta
.
affix
:
false
;
if
(
!
affix
)
{
pathList
.
push
(
item
.
p
ath
);
pathList
.
push
(
item
.
fullP
ath
);
nameList
.
push
(
item
.
name
as
string
);
}
}
...
...
@@ -207,16 +218,16 @@ class Tab extends VuexModule {
@
Action
closeOtherTabAction
(
route
:
AppRouteRecordRaw
|
TabItem
):
void
{
const
closePathList
=
this
.
tabsState
.
map
((
item
)
=>
item
.
p
ath
);
const
closePathList
=
this
.
tabsState
.
map
((
item
)
=>
item
.
fullP
ath
);
const
pathList
:
string
[]
=
[];
const
nameList
:
string
[]
=
[];
closePathList
.
forEach
((
path
)
=>
{
if
(
path
!==
route
.
p
ath
)
{
if
(
path
!==
route
.
fullP
ath
)
{
const
closeItem
=
this
.
tabsState
.
find
((
item
)
=>
item
.
path
===
path
);
if
(
!
closeItem
)
return
;
const
affix
=
closeItem
.
meta
?
closeItem
.
meta
.
affix
:
false
;
if
(
!
affix
)
{
pathList
.
push
(
closeItem
.
p
ath
);
pathList
.
push
(
closeItem
.
fullP
ath
);
nameList
.
push
(
closeItem
.
name
as
string
);
}
}
...
...
src/types/source.d.ts
浏览文件 @
31e2715e
declare
module
'
ant-design-vue/es/locale/zh_CN
'
;
declare
module
'
vue-draggable-resizable
'
;
declare
module
'
globby!/@/router/routes/modules/**/*.@(ts)
'
;
declare
module
'
globby!/@/router/menus/modules/**/*.@(ts)
'
;
declare
const
React
:
string
;
declare
module
'
*.bmp
'
{
const
src
:
string
;
...
...
src/utils/eventHub.ts
浏览文件 @
31e2715e
...
...
@@ -16,9 +16,6 @@ class EventHub {
emit
(
eventName
:
string
,
data
?:
any
)
{
if
(
this
.
cache
[
eventName
]
===
undefined
)
return
;
console
.
log
(
'
======================
'
);
console
.
log
(
this
.
cache
,
eventName
);
console
.
log
(
'
======================
'
);
this
.
cache
[
eventName
].
forEach
((
fn
)
=>
fn
(
data
));
}
off
(
eventName
:
string
,
fn
:
(
data
:
any
)
=>
void
)
{
...
...
src/utils/helper/menuHelper.ts
浏览文件 @
31e2715e
...
...
@@ -4,7 +4,6 @@ import type { MenuModule, Menu, AppRouteRecordRaw } from '/@/router/types';
import
{
findPath
,
forEach
,
treeMap
,
treeToList
}
from
'
./treeHelper
'
;
import
{
cloneDeep
}
from
'
lodash-es
'
;
//
export
function
getAllParentPath
(
treeData
:
any
[],
path
:
string
)
{
const
menuList
=
findPath
(
treeData
,
(
n
)
=>
n
.
path
===
path
)
as
Menu
[];
return
(
menuList
||
[]).
map
((
item
)
=>
item
.
path
);
...
...
@@ -14,6 +13,7 @@ export function flatMenus(menus: Menu[]) {
return
treeToList
(
menus
);
}
// 拼接父级路径
function
joinParentPath
(
list
:
any
,
node
:
any
)
{
let
allPaths
=
getAllParentPath
(
list
,
node
.
path
);
...
...
@@ -26,7 +26,6 @@ function joinParentPath(list: any, node: any) {
parentPath
+=
/^
\/
/
.
test
(
p
)
?
p
:
`/
${
p
}
`
;
});
}
node
.
path
=
`
${
parentPath
}${
/^
\
//.test(node.path) ? node.path : `/${node.path}`}`.replace(
/
\
/
\
//g,
'
/
'
...
...
@@ -34,6 +33,7 @@ function joinParentPath(list: any, node: any) {
return
node
;
}
// 解析菜单模块
export function transformMenuModule(menuModule: MenuModule): Menu {
const { menu } = menuModule;
...
...
src/utils/helper/routeHelper.ts
浏览文件 @
31e2715e
import
type
{
AppRouteModule
,
AppRouteRecordRaw
}
from
'
/@/router/types
'
;
import
type
{
RouteRecordRaw
}
from
'
vue-router
'
;
import
type
{
Route
LocationNormalized
,
Route
RecordRaw
}
from
'
vue-router
'
;
import
{
appStore
}
from
'
/@/store/modules/app
'
;
import
{
tabStore
}
from
'
/@/store/modules/tab
'
;
import
{
createRouter
,
createWebHashHistory
}
from
'
vue-router
'
;
import
{
toRaw
}
from
'
vue
'
;
import
{
PAGE_LAYOUT_COMPONENT
}
from
'
/@/router/constant
'
;
let
currentTo
:
RouteLocationNormalized
|
null
=
null
;
export
function
getCurrentTo
()
{
return
currentTo
;
}
export
function
setCurrentTo
(
to
:
RouteLocationNormalized
)
{
currentTo
=
to
;
}
// 转化路由模块
// 将多级转成2层。keepAlive问题
export
function
genRouteModule
(
moduleList
:
AppRouteModule
[])
{
const
ret
:
AppRouteRecordRaw
[]
=
[];
for
(
const
routeMod
of
moduleList
)
{
...
...
@@ -27,6 +39,7 @@ export function genRouteModule(moduleList: AppRouteModule[]) {
return
ret
as
RouteRecordRaw
[];
}
// 动态引入
function
asyncImportRoute
(
routes
:
AppRouteRecordRaw
[])
{
routes
.
forEach
((
item
)
=>
{
const
{
component
,
children
}
=
item
;
...
...
@@ -37,6 +50,7 @@ function asyncImportRoute(routes: AppRouteRecordRaw[]) {
});
}
// 将后台对象转成路由对象
export
function
transformObjToRoute
(
routeList
:
AppRouteModule
[])
{
routeList
.
forEach
((
route
)
=>
{
asyncImportRoute
(
route
.
routes
);
...
...
@@ -48,6 +62,7 @@ export function transformObjToRoute(routeList: AppRouteModule[]) {
return
routeList
;
}
//
export
function
getIsOpenTab
(
toPath
:
string
)
{
const
{
openKeepAlive
,
multiTabsSetting
:
{
show
}
=
{}
}
=
appStore
.
getProjectConfig
;
...
...
@@ -57,3 +72,13 @@ export function getIsOpenTab(toPath: string) {
}
return
false
;
}
export
function
getParams
(
data
:
any
=
{})
{
const
{
params
=
{}
}
=
data
;
let
ret
=
''
;
Object
.
keys
(
params
).
forEach
((
key
)
=>
{
const
p
=
params
[
key
];
ret
+=
`/
${
p
}
`
;
});
return
ret
;
}
src/views/demo/feat/tab-params/index.vue
0 → 100644
浏览文件 @
31e2715e
<
template
>
<div
class=
"p-4"
>
Current Param :
{{
params
}}
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
computed
,
defineComponent
,
unref
}
from
'
vue
'
;
import
{
useRouter
}
from
'
vue-router
'
;
export
default
defineComponent
({
setup
()
{
const
{
currentRoute
}
=
useRouter
();
return
{
params
:
computed
(()
=>
{
return
unref
(
currentRoute
).
params
;
}),
};
},
});
</
script
>
src/views/sys/redirect/index.vue
浏览文件 @
31e2715e
...
...
@@ -2,7 +2,7 @@
<div
/>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
onBeforeMount
,
unref
}
from
'
vue
'
;
import
{
defineComponent
,
unref
}
from
'
vue
'
;
import
{
appStore
}
from
'
/@/store/modules/app
'
;
...
...
@@ -11,21 +11,19 @@
name
:
'
Redirect
'
,
setup
()
{
const
{
currentRoute
,
replace
}
=
useRouter
();
onBeforeMount
(()
=>
{
const
{
params
,
query
}
=
unref
(
currentRoute
);
const
{
path
}
=
params
;
const
_path
=
Array
.
isArray
(
path
)
?
path
.
join
(
'
/
'
)
:
path
;
replace
({
path
:
'
/
'
+
_path
,
query
,
});
const
{
openRouterTransition
,
openPageLoading
}
=
appStore
.
getProjectConfig
;
if
(
openRouterTransition
&&
openPageLoading
)
{
setTimeout
(()
=>
{
appStore
.
setPageLoadingAction
(
false
);
},
0
);
}
const
{
params
,
query
}
=
unref
(
currentRoute
);
const
{
path
}
=
params
;
const
_path
=
Array
.
isArray
(
path
)
?
path
.
join
(
'
/
'
)
:
path
;
replace
({
path
:
'
/
'
+
_path
,
query
,
});
const
{
openRouterTransition
,
openPageLoading
}
=
appStore
.
getProjectConfig
;
if
(
openRouterTransition
&&
openPageLoading
)
{
setTimeout
(()
=>
{
appStore
.
setPageLoadingAction
(
false
);
},
0
);
}
return
{};
},
});
...
...
vite.config.ts
浏览文件 @
31e2715e
...
...
@@ -71,7 +71,7 @@ const viteConfig: UserConfig = {
* boolean | 'terser' | 'esbuild'
* @default 'terser'
*/
minify
:
isDevFn
()
?
false
:
'
terser
'
,
minify
:
'
terser
'
,
/**
* 基本公共路径
* @default '/'
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录