Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
球球不吃虾
vue-vben-admin
提交
ff2b12b4
V
vue-vben-admin
项目概览
球球不吃虾
/
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 搜索 >>
提交
ff2b12b4
编写于
1月 17, 2021
作者:
V
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor(menu): added component. Solve the menu stuck problem
上级
056fc131
变更
43
隐藏空白更改
内联
并排
Showing
43 changed file
with
1793 addition
and
213 deletion
+1793
-213
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+4
-0
mock/sys/user.ts
mock/sys/user.ts
+1
-2
package.json
package.json
+9
-9
src/components/Application/src/search/AppSearchModal.vue
src/components/Application/src/search/AppSearchModal.vue
+49
-48
src/components/MenuPlus/index.ts
src/components/MenuPlus/index.ts
+0
-1
src/components/MenuPlus/src/index.vue
src/components/MenuPlus/src/index.vue
+0
-64
src/components/SimpleMenu/index.ts
src/components/SimpleMenu/index.ts
+1
-0
src/components/SimpleMenu/src/SimpleMenu.vue
src/components/SimpleMenu/src/SimpleMenu.vue
+135
-0
src/components/SimpleMenu/src/SimpleMenuTag.vue
src/components/SimpleMenu/src/SimpleMenuTag.vue
+70
-0
src/components/SimpleMenu/src/SimpleSubMenu.vue
src/components/SimpleMenu/src/SimpleSubMenu.vue
+115
-0
src/components/SimpleMenu/src/components/Menu.vue
src/components/SimpleMenu/src/components/Menu.vue
+149
-0
src/components/SimpleMenu/src/components/MenuCollapseTransition.vue
...ents/SimpleMenu/src/components/MenuCollapseTransition.vue
+78
-0
src/components/SimpleMenu/src/components/MenuItem.vue
src/components/SimpleMenu/src/components/MenuItem.vue
+103
-0
src/components/SimpleMenu/src/components/SubMenuItem.vue
src/components/SimpleMenu/src/components/SubMenuItem.vue
+329
-0
src/components/SimpleMenu/src/components/menu.less
src/components/SimpleMenu/src/components/menu.less
+332
-0
src/components/SimpleMenu/src/components/types.ts
src/components/SimpleMenu/src/components/types.ts
+25
-0
src/components/SimpleMenu/src/components/useMenu.ts
src/components/SimpleMenu/src/components/useMenu.ts
+86
-0
src/components/SimpleMenu/src/components/useSimpleMenuContext.ts
...ponents/SimpleMenu/src/components/useSimpleMenuContext.ts
+18
-0
src/components/SimpleMenu/src/index.less
src/components/SimpleMenu/src/index.less
+67
-0
src/components/SimpleMenu/src/types.ts
src/components/SimpleMenu/src/types.ts
+5
-0
src/components/SimpleMenu/src/useOpenKeys.ts
src/components/SimpleMenu/src/useOpenKeys.ts
+45
-0
src/components/Table/src/components/editable/EditableCell.vue
...components/Table/src/components/editable/EditableCell.vue
+1
-1
src/components/Table/src/hooks/useProvinceTable.ts
src/components/Table/src/hooks/useProvinceTable.ts
+0
-16
src/design/ant/index.less
src/design/ant/index.less
+6
-0
src/design/color.less
src/design/color.less
+0
-2
src/hooks/setting/useMenuSetting.ts
src/hooks/setting/useMenuSetting.ts
+6
-3
src/layouts/default/header/index.vue
src/layouts/default/header/index.vue
+1
-1
src/layouts/default/menu/index.tsx
src/layouts/default/menu/index.tsx
+14
-2
src/layouts/default/menu/useLayoutMenu.ts
src/layouts/default/menu/useLayoutMenu.ts
+11
-2
src/layouts/default/sider/MixSider.vue
src/layouts/default/sider/MixSider.vue
+17
-9
src/locales/lang/en/component/drawer.ts
src/locales/lang/en/component/drawer.ts
+5
-0
src/locales/lang/en/component/menu.ts
src/locales/lang/en/component/menu.ts
+3
-0
src/locales/lang/en/component/modal.ts
src/locales/lang/en/component/modal.ts
+4
-0
src/locales/lang/zh_CN/component/drawer.ts
src/locales/lang/zh_CN/component/drawer.ts
+5
-0
src/locales/lang/zh_CN/component/menu.ts
src/locales/lang/zh_CN/component/menu.ts
+3
-0
src/locales/lang/zh_CN/component/modal.ts
src/locales/lang/zh_CN/component/modal.ts
+4
-0
src/logics/theme/index.ts
src/logics/theme/index.ts
+1
-1
src/router/guard/index.ts
src/router/guard/index.ts
+2
-0
src/router/guard/stateGuard.ts
src/router/guard/stateGuard.ts
+1
-1
src/router/menus/index.ts
src/router/menus/index.ts
+2
-0
src/utils/mitt.ts
src/utils/mitt.ts
+2
-2
vite.config.ts
vite.config.ts
+1
-0
yarn.lock
yarn.lock
+83
-49
未找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
ff2b12b4
## Wip
### ✨ Refactor
-
新增
`SimpleMenu`
组件替代左侧菜单组件(顶部菜单没有替换,功能尽量做到简单不卡)。解决菜单卡顿问题。
### 🐛 Bug Fixes
-
修复
`TableAction`
图标问题
...
...
mock/sys/user.ts
浏览文件 @
ff2b12b4
...
...
@@ -39,7 +39,7 @@ export default [
// mock user login
{
url
:
'
/api/login
'
,
timeout
:
10
00
,
timeout
:
2
00
,
method
:
'
post
'
,
response
:
({
body
})
=>
{
const
{
username
,
password
}
=
body
;
...
...
@@ -62,7 +62,6 @@ export default [
},
{
url
:
'
/api/getUserInfoById
'
,
timeout
:
200
,
method
:
'
get
'
,
response
:
({
query
})
=>
{
const
{
userId
}
=
query
;
...
...
package.json
浏览文件 @
ff2b12b4
...
...
@@ -19,7 +19,7 @@
},
"dependencies"
:
{
"
@iconify/iconify
"
:
"
^2.0.0-rc.6
"
,
"
@vueuse/core
"
:
"
^4.0.
5
"
,
"
@vueuse/core
"
:
"
^4.0.
8
"
,
"
ant-design-vue
"
:
"
^2.0.0-rc.8
"
,
"
apexcharts
"
:
"
^3.23.1
"
,
"
axios
"
:
"
^0.21.1
"
,
...
...
@@ -45,12 +45,12 @@
"devDependencies"
:
{
"
@commitlint/cli
"
:
"
^11.0.0
"
,
"
@commitlint/config-conventional
"
:
"
^11.0.0
"
,
"
@iconify/json
"
:
"
^1.1.28
6
"
,
"
@iconify/json
"
:
"
^1.1.28
7
"
,
"
@ls-lint/ls-lint
"
:
"
^1.9.2
"
,
"
@purge-icons/generated
"
:
"
^0.5.1
"
,
"
@types/echarts
"
:
"
^4.9.3
"
,
"
@types/fs-extra
"
:
"
^9.0.6
"
,
"
@types/http-proxy
"
:
"
^1.17.
4
"
,
"
@types/http-proxy
"
:
"
^1.17.
5
"
,
"
@types/koa-static
"
:
"
^4.0.1
"
,
"
@types/lodash-es
"
:
"
^4.17.4
"
,
"
@types/mockjs
"
:
"
^1.0.3
"
,
...
...
@@ -63,24 +63,24 @@
"
@typescript-eslint/eslint-plugin
"
:
"
^4.13.0
"
,
"
@typescript-eslint/parser
"
:
"
^4.13.0
"
,
"
@vitejs/plugin-legacy
"
:
"
^1.2.1
"
,
"
@vitejs/plugin-vue
"
:
"
^1.0.
5
"
,
"
@vitejs/plugin-vue
"
:
"
^1.0.
6
"
,
"
@vitejs/plugin-vue-jsx
"
:
"
^1.0.2
"
,
"
@vue/compiler-sfc
"
:
"
^3.0.5
"
,
"
@vuedx/typecheck
"
:
"
^0.5.0
"
,
"
@vuedx/typescript-plugin-vue
"
:
"
^0.5.0
"
,
"
autoprefixer
"
:
"
^10.2.1
"
,
"
commitizen
"
:
"
^4.2.
2
"
,
"
commitizen
"
:
"
^4.2.
3
"
,
"
conventional-changelog-cli
"
:
"
^2.1.1
"
,
"
conventional-changelog-custom-config
"
:
"
^0.3.1
"
,
"
cross-env
"
:
"
^7.0.3
"
,
"
dotenv
"
:
"
^8.2.0
"
,
"
eslint
"
:
"
^7.1
7
.0
"
,
"
eslint
"
:
"
^7.1
8
.0
"
,
"
eslint-config-prettier
"
:
"
^7.1.0
"
,
"
eslint-plugin-prettier
"
:
"
^3.3.1
"
,
"
eslint-plugin-vue
"
:
"
^7.4.1
"
,
"
esno
"
:
"
^0.4.0
"
,
"
fs-extra
"
:
"
^9.0.1
"
,
"
husky
"
:
"
^4.3.
7
"
,
"
husky
"
:
"
^4.3.
8
"
,
"
koa-static
"
:
"
^5.0.0
"
,
"
less
"
:
"
^4.1.0
"
,
"
lint-staged
"
:
"
^10.5.3
"
,
...
...
@@ -96,11 +96,11 @@
"
stylelint-order
"
:
"
^4.1.0
"
,
"
ts-node
"
:
"
^9.1.0
"
,
"
typescript
"
:
"
^4.1.3
"
,
"
vite
"
:
"
^2.0.0-beta.
27
"
,
"
vite
"
:
"
^2.0.0-beta.
30
"
,
"
vite-plugin-html
"
:
"
^2.0.0-beta.5
"
,
"
vite-plugin-mock
"
:
"
^2.0.0-beta.3
"
,
"
vite-plugin-purge-icons
"
:
"
^0.5.1
"
,
"
vite-plugin-pwa
"
:
"
^0.3.
6
"
,
"
vite-plugin-pwa
"
:
"
^0.3.
8
"
,
"
vue-eslint-parser
"
:
"
^7.3.0
"
,
"
yargs
"
:
"
^16.2.0
"
},
...
...
src/components/Application/src/search/AppSearchModal.vue
浏览文件 @
ff2b12b4
...
...
@@ -2,54 +2,52 @@
<Teleport
to=
"body"
>
<transition
name=
"zoom-fade"
mode=
"out-in"
>
<div
:class=
"getClass"
@
click.stop
v-if=
"visible"
>
<ClickOutSide
@
clickOutside=
"handleClose"
>
<div
:class=
"`$
{prefixCls}-content`">
<div
:class=
"`$
{prefixCls}-input__wrapper`">
<a-input
:class=
"`$
{prefixCls}-input`"
:placeholder="t('common.searchText')"
allow-clear
@change="handleSearch"
>
<template
#prefix
>
<SearchOutlined
/>
</
template
>
</a-input>
<span
:class=
"`${prefixCls}-cancel`"
@
click=
"handleClose"
>
{{
t('common.cancelText')
}}
</span>
</div>
<div
:class=
"`$
{prefixCls}-content`" v-click-outside="handleClose">
<div
:class=
"`$
{prefixCls}-input__wrapper`">
<a-input
:class=
"`$
{prefixCls}-input`"
:placeholder="t('common.searchText')"
allow-clear
@change="handleSearch"
>
<template
#prefix
>
<SearchOutlined
/>
</
template
>
</a-input>
<span
:class=
"`${prefixCls}-cancel`"
@
click=
"handleClose"
>
{{
t('common.cancelText')
}}
</span>
</div>
<div
:class=
"`${prefixCls}-not-data`"
v-show=
"getIsNotData"
>
{{ t('component.app.searchNotData') }}
</div>
<ul
:class=
"`${prefixCls}-list`"
v-show=
"!getIsNotData"
ref=
"scrollWrap"
>
<li
:ref=
"setRefs(index)"
v-for=
"(item, index) in searchResult"
:key=
"item.path"
:data-index=
"index"
@
mouseenter=
"handleMouseenter"
@
click=
"handleEnter"
:class=
"[
`${prefixCls}-list__item`,
{
[`${prefixCls}-list__item--active`]: activeIndex === index,
},
]"
>
<div
:class=
"`${prefixCls}-list__item-icon`"
>
<g-icon
:icon=
"item.icon || 'mdi:form-select'"
:size=
"20"
/>
</div>
<div
:class=
"`${prefixCls}-list__item-text`"
>
{{ item.name }}
</div>
<div
:class=
"`${prefixCls}-list__item-enter`"
>
<g-icon
icon=
"ant-design:enter-outlined"
:size=
"20"
/>
</div>
</li>
</ul>
<AppSearchFooter
/>
<div
:class=
"`${prefixCls}-not-data`"
v-show=
"getIsNotData"
>
{{ t('component.app.searchNotData') }}
</div>
</ClickOutSide>
<ul
:class=
"`${prefixCls}-list`"
v-show=
"!getIsNotData"
ref=
"scrollWrap"
>
<li
:ref=
"setRefs(index)"
v-for=
"(item, index) in searchResult"
:key=
"item.path"
:data-index=
"index"
@
mouseenter=
"handleMouseenter"
@
click=
"handleEnter"
:class=
"[
`${prefixCls}-list__item`,
{
[`${prefixCls}-list__item--active`]: activeIndex === index,
},
]"
>
<div
:class=
"`${prefixCls}-list__item-icon`"
>
<g-icon
:icon=
"item.icon || 'mdi:form-select'"
:size=
"20"
/>
</div>
<div
:class=
"`${prefixCls}-list__item-text`"
>
{{ item.name }}
</div>
<div
:class=
"`${prefixCls}-list__item-enter`"
>
<g-icon
icon=
"ant-design:enter-outlined"
:size=
"20"
/>
</div>
</li>
</ul>
<AppSearchFooter
/>
</div>
</div>
</transition>
</Teleport>
...
...
@@ -63,17 +61,20 @@
import
{
SearchOutlined
}
from
'
@ant-design/icons-vue
'
;
import
AppSearchFooter
from
'
./AppSearchFooter.vue
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
import
{
ClickOutSide
}
from
'
/@/components/ClickOutSide
'
;
import
{
useAppInject
}
from
'
/@/hooks/web/useAppInject
'
;
import
clickOutside
from
'
/@/directives/clickOutside
'
;
export
default
defineComponent
({
name
:
'
AppSearchModal
'
,
components
:
{
SearchOutlined
,
ClickOutSide
,
AppSearchFooter
},
components
:
{
SearchOutlined
,
AppSearchFooter
},
emits
:
[
'
close
'
],
props
:
{
visible
:
Boolean
,
},
directives
:
{
clickOutside
,
},
setup
(
_
,
{
emit
})
{
const
scrollWrap
=
ref
<
ElRef
>
(
null
);
const
{
prefixCls
}
=
useDesign
(
'
app-search-modal
'
);
...
...
src/components/MenuPlus/index.ts
已删除
100644 → 0
浏览文件 @
056fc131
export
{
default
as
Menu
}
from
'
./src/index.vue
'
;
src/components/MenuPlus/src/index.vue
已删除
100644 → 0
浏览文件 @
056fc131
<
template
>
<ul
:class=
"getClass"
:style=
"getStyle"
>
<slot></slot>
</ul>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
ref
,
computed
,
CSSProperties
,
unref
}
from
'
vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
export
default
defineComponent
({
props
:
{
mode
:
propTypes
.
oneOf
([
'
horizontal
'
,
'
vertical
'
]).
def
(
'
vertical
'
),
theme
:
propTypes
.
oneOf
([
'
light
'
,
'
dark
'
,
'
primary
'
]).
def
(
'
light
'
),
activeName
:
propTypes
.
oneOfType
([
propTypes
.
string
,
propTypes
.
number
]),
openNames
:
propTypes
.
array
.
def
([]),
accordion
:
propTypes
.
bool
,
width
:
propTypes
.
string
.
def
(
'
210px
'
),
},
setup
(
props
)
{
const
currentActiveName
=
ref
(
props
.
activeName
);
const
openedNames
=
ref
<
string
[]
>
();
const
{
prefixCls
}
=
useDesign
(
'
menu
'
);
const
getClass
=
computed
(()
=>
{
const
{
theme
,
mode
}
=
props
;
let
curTheme
=
theme
;
if
(
mode
===
'
vertical
'
&&
theme
===
'
primary
'
)
{
curTheme
=
'
light
'
;
}
return
[
prefixCls
,
`
${
prefixCls
}
-
${
curTheme
}
`
,
{
[
`
${
prefixCls
}
-
${
mode
}
`
]:
mode
,
},
];
});
const
getStyle
=
computed
(
():
CSSProperties
=>
{
const
{
mode
,
width
}
=
props
;
if
(
mode
===
'
vertical
'
)
{
return
{
width
:
width
,
};
}
return
{};
}
);
function
updateActiveName
()
{
if
(
unref
(
currentActiveName
)
===
undefined
)
{
currentActiveName
.
value
=
-
1
;
}
}
function
updateOpened
()
{}
return
{
getClass
,
getStyle
};
},
});
</
script
>
src/components/SimpleMenu/index.ts
0 → 100644
浏览文件 @
ff2b12b4
export
{
default
as
SimpleMenu
}
from
'
./src/SimpleMenu.vue
'
;
src/components/SimpleMenu/src/SimpleMenu.vue
0 → 100644
浏览文件 @
ff2b12b4
<
template
>
<Menu
v-bind=
"getBindValues"
@
select=
"handleSelect"
:activeName=
"activeName"
:openNames=
"openNames"
:class=
"prefixCls"
:activeSubMenuNames=
"activeSubMenuNames"
>
<template
v-for=
"item in items"
:key=
"item.path"
>
<SimpleSubMenu
:item=
"item"
:parent=
"true"
:collapsedShowTitle=
"collapsedShowTitle"
:collapse=
"collapse"
/>
</
template
>
</Menu>
</template>
<
script
lang=
"ts"
>
import
type
{
PropType
}
from
'
vue
'
;
import
type
{
MenuState
}
from
'
./types
'
;
import
type
{
Menu
as
MenuType
}
from
'
/@/router/types
'
;
import
{
defineComponent
,
computed
,
ref
,
unref
,
reactive
,
toRefs
,
watch
}
from
'
vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
Menu
from
'
./components/Menu.vue
'
;
import
SimpleSubMenu
from
'
./SimpleSubMenu.vue
'
;
import
{
listenerLastChangeTab
}
from
'
/@/logics/mitt/tabChange
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
import
{
REDIRECT_NAME
}
from
'
/@/router/constant
'
;
import
{
RouteLocationNormalizedLoaded
,
useRouter
}
from
'
vue-router
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
useOpenKeys
}
from
'
./useOpenKeys
'
;
export
default
defineComponent
({
name
:
'
SimpleMenu
'
,
inheritAttrs
:
false
,
components
:
{
Menu
,
SimpleSubMenu
,
},
props
:
{
items
:
{
type
:
Array
as
PropType
<
MenuType
[]
>
,
default
:
()
=>
[],
},
collapse
:
propTypes
.
bool
,
mixSider
:
propTypes
.
bool
,
theme
:
propTypes
.
string
,
accordion
:
propTypes
.
bool
.
def
(
true
),
collapsedShowTitle
:
propTypes
.
bool
,
beforeClickFn
:
{
type
:
Function
as
PropType
<
(
key
:
string
)
=>
Promise
<
boolean
>>
,
},
},
setup
(
props
,
{
attrs
,
emit
})
{
const
currentActiveMenu
=
ref
(
''
);
const
isClickGo
=
ref
(
false
);
const
menuState
=
reactive
<
MenuState
>
({
activeName
:
''
,
openNames
:
[],
activeSubMenuNames
:
[],
});
const
{
currentRoute
}
=
useRouter
();
const
{
prefixCls
}
=
useDesign
(
'
simple-menu
'
);
const
{
items
,
accordion
,
mixSider
}
=
toRefs
(
props
);
const
{
setOpenKeys
}
=
useOpenKeys
(
menuState
,
items
,
accordion
,
mixSider
);
const
getBindValues
=
computed
(()
=>
({
...
attrs
,
...
props
}));
watch
(
()
=>
props
.
collapse
,
(
collapse
)
=>
{
if
(
collapse
)
{
menuState
.
openNames
=
[];
}
else
{
setOpenKeys
(
currentRoute
.
value
.
path
);
}
},
{
immediate
:
true
}
);
listenerLastChangeTab
((
route
)
=>
{
if
(
route
.
name
===
REDIRECT_NAME
)
return
;
currentActiveMenu
.
value
=
route
.
meta
?.
currentActiveMenu
;
handleMenuChange
(
route
);
if
(
unref
(
currentActiveMenu
))
{
menuState
.
activeName
=
unref
(
currentActiveMenu
);
setOpenKeys
(
unref
(
currentActiveMenu
));
}
});
async
function
handleMenuChange
(
route
?:
RouteLocationNormalizedLoaded
)
{
if
(
unref
(
isClickGo
))
{
isClickGo
.
value
=
false
;
return
;
}
const
path
=
(
route
||
unref
(
currentRoute
)).
path
;
menuState
.
activeName
=
path
;
setOpenKeys
(
path
);
// if (unref(currentActiveMenu)) return;
}
async
function
handleSelect
(
key
:
string
)
{
const
{
beforeClickFn
}
=
props
;
if
(
beforeClickFn
&&
isFunction
(
beforeClickFn
))
{
const
flag
=
await
beforeClickFn
(
key
);
if
(
!
flag
)
return
;
}
emit
(
'
menuClick
'
,
key
);
isClickGo
.
value
=
true
;
setOpenKeys
(
key
);
menuState
.
activeName
=
key
;
}
return
{
prefixCls
,
getBindValues
,
handleSelect
,
...
toRefs
(
menuState
),
};
},
});
</
script
>
<
style
lang=
"less"
>
@import './index.less';
</
style
>
src/components/SimpleMenu/src/SimpleMenuTag.vue
0 → 100644
浏览文件 @
ff2b12b4
<
template
>
<span
:class=
"getTagClass"
v-if=
"getShowTag"
>
{{
getContent
}}
</span>
</
template
>
<
script
lang=
"ts"
>
import
type
{
Menu
}
from
'
/@/router/types
'
;
import
type
{
PropType
}
from
'
vue
'
;
import
{
defineComponent
,
computed
}
from
'
vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
export
default
defineComponent
({
name
:
'
SimpleMenuTag
'
,
props
:
{
item
:
{
type
:
Object
as
PropType
<
Menu
>
,
default
:
{},
},
collapseParent
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
},
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'
simple-menu
'
);
const
getShowTag
=
computed
(()
=>
{
const
{
item
}
=
props
;
if
(
!
item
)
return
false
;
const
{
tag
}
=
item
;
if
(
!
tag
)
return
false
;
const
{
dot
,
content
}
=
tag
;
if
(
!
dot
&&
!
content
)
return
false
;
return
true
;
});
const
getContent
=
computed
(()
=>
{
if
(
!
getShowTag
.
value
)
return
''
;
const
{
item
,
collapseParent
}
=
props
;
const
{
tag
}
=
item
;
const
{
dot
,
content
}
=
tag
!
;
return
dot
||
collapseParent
?
''
:
content
;
});
const
getTagClass
=
computed
(()
=>
{
const
{
item
,
collapseParent
}
=
props
;
const
{
tag
=
{}
}
=
item
||
{};
const
{
dot
,
type
=
'
error
'
}
=
tag
;
const
tagCls
=
`
${
prefixCls
}
-tag`
;
return
[
tagCls
,
[
`
${
tagCls
}
--
${
type
}
`
],
{
[
`
${
tagCls
}
--collapse`
]:
collapseParent
,
[
`
${
tagCls
}
--dot`
]:
dot
,
},
];
});
return
{
getTagClass
,
getShowTag
,
getContent
,
};
},
});
</
script
>
src/components/SimpleMenu/src/SimpleSubMenu.vue
0 → 100644
浏览文件 @
ff2b12b4
<
template
>
<MenuItem
:name=
"item.path"
v-if=
"!menuHasChildren(item) && getShowMenu"
v-bind=
"$props"
:class=
"getLevelClass"
>
<Icon
v-if=
"getIcon"
:icon=
"getIcon"
:size=
"16"
/>
<div
v-if=
"collapsedShowTitle && getIsCollapseParent"
class=
"mt-1 collapse-title"
>
{{
getI18nName
}}
</div>
<template
#title
>
<span
:class=
"['ml-2']"
>
{{
getI18nName
}}
</span>
<SimpleMenuTag
:item=
"item"
:collapseParent=
"getIsCollapseParent"
/>
</
template
>
</MenuItem>
<SubMenu
:name=
"item.path"
v-if=
"menuHasChildren(item) && getShowMenu"
:class=
"[getLevelClass, theme]"
:collapsedShowTitle=
"collapsedShowTitle"
>
<
template
#title
>
<Icon
v-if=
"getIcon"
:icon=
"getIcon"
:size=
"16"
/>
<div
v-if=
"collapsedShowTitle && getIsCollapseParent"
class=
"mt-2 collapse-title"
>
{{
getI18nName
}}
</div>
<span
v-show=
"getShowSubTitle"
:class=
"['ml-2', `$
{prefixCls}-sub-title`]">
{{
getI18nName
}}
</span>
<SimpleMenuTag
:item=
"item"
:collapseParent=
"!!collapse && !!parent"
/>
</
template
>
<
template
v-for=
"childrenItem in item.children || []"
:key=
"childrenItem.path"
>
<SimpleSubMenu
v-bind=
"$props"
:item=
"childrenItem"
:parent=
"false"
/>
</
template
>
</SubMenu>
</template>
<
script
lang=
"ts"
>
import
type
{
PropType
}
from
'
vue
'
;
import
type
{
Menu
}
from
'
/@/router/types
'
;
import
{
defineComponent
,
computed
}
from
'
vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
Icon
from
'
/@/components/Icon/index
'
;
import
MenuItem
from
'
./components/MenuItem.vue
'
;
import
SubMenu
from
'
./components/SubMenuItem.vue
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
import
{
createAsyncComponent
}
from
'
/@/utils/factory/createAsyncComponent
'
;
const
{
t
}
=
useI18n
();
export
default
defineComponent
({
name
:
'
SimpleSubMenu
'
,
components
:
{
SubMenu
,
MenuItem
,
SimpleMenuTag
:
createAsyncComponent
(()
=>
import
(
'
./SimpleMenuTag.vue
'
)),
Icon
,
},
props
:
{
item
:
{
type
:
Object
as
PropType
<
Menu
>
,
default
:
{},
},
parent
:
propTypes
.
bool
,
collapsedShowTitle
:
propTypes
.
bool
,
collapse
:
propTypes
.
bool
,
theme
:
propTypes
.
oneOf
([
'
dark
'
,
'
light
'
]),
},
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'
simple-menu
'
);
const
getShowMenu
=
computed
(()
=>
{
return
!
props
.
item
.
meta
?.
hideMenu
;
});
const
getIcon
=
computed
(()
=>
props
.
item
?.
icon
);
const
getI18nName
=
computed
(()
=>
t
(
props
.
item
?.
name
));
const
getShowSubTitle
=
computed
(()
=>
!
props
.
collapse
||
!
props
.
parent
);
const
getIsCollapseParent
=
computed
(()
=>
!!
props
.
collapse
&&
!!
props
.
parent
);
const
getLevelClass
=
computed
(()
=>
{
return
[
{
[
`
${
prefixCls
}
__parent`
]:
props
.
parent
,
[
`
${
prefixCls
}
__children`
]:
!
props
.
parent
,
},
];
});
function
menuHasChildren
(
menuTreeItem
:
Menu
):
boolean
{
return
(
Reflect
.
has
(
menuTreeItem
,
'
children
'
)
&&
!!
menuTreeItem
.
children
&&
menuTreeItem
.
children
.
length
>
0
);
}
return
{
prefixCls
,
menuHasChildren
,
getShowMenu
,
getIcon
,
getI18nName
,
getShowSubTitle
,
getLevelClass
,
getIsCollapseParent
,
};
},
});
</
script
>
src/components/SimpleMenu/src/components/Menu.vue
0 → 100644
浏览文件 @
ff2b12b4
<
template
>
<ul
:class=
"getClass"
>
<slot></slot>
</ul>
</
template
>
<
script
lang=
"ts"
>
import
type
{
PropType
}
from
'
vue
'
;
import
type
{
SubMenuProvider
}
from
'
./types
'
;
import
{
defineComponent
,
ref
,
computed
,
onMounted
,
watchEffect
,
watch
,
nextTick
,
getCurrentInstance
,
provide
,
}
from
'
vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
import
{
createSimpleRootMenuContext
}
from
'
./useSimpleMenuContext
'
;
import
Mitt
from
'
/@/utils/mitt
'
;
import
{
isString
}
from
'
/@/utils/is
'
;
export
default
defineComponent
({
name
:
'
Menu
'
,
props
:
{
theme
:
propTypes
.
oneOf
([
'
light
'
,
'
dark
'
]).
def
(
'
light
'
),
activeName
:
propTypes
.
oneOfType
([
propTypes
.
string
,
propTypes
.
number
]),
openNames
:
{
type
:
Array
as
PropType
<
string
[]
>
,
default
:
[],
},
accordion
:
propTypes
.
bool
.
def
(
true
),
width
:
propTypes
.
string
.
def
(
'
100%
'
),
collapsedWidth
:
propTypes
.
string
.
def
(
'
48px
'
),
indentSize
:
propTypes
.
number
.
def
(
16
),
collapse
:
propTypes
.
bool
.
def
(
true
),
activeSubMenuNames
:
{
type
:
Array
as
PropType
<
(
string
|
number
)[]
>
,
default
:
[],
},
},
emits
:
[
'
select
'
,
'
open-change
'
],
setup
(
props
,
{
emit
})
{
const
rootMenuEmitter
=
new
Mitt
();
const
instance
=
getCurrentInstance
();
const
currentActiveName
=
ref
<
string
|
number
>
(
''
);
const
openedNames
=
ref
<
string
[]
>
([]);
const
{
prefixCls
}
=
useDesign
(
'
menu
'
);
const
isRemoveAllPopup
=
ref
(
false
);
createSimpleRootMenuContext
({
rootMenuEmitter
:
rootMenuEmitter
,
activeName
:
currentActiveName
,
});
const
getClass
=
computed
(()
=>
{
const
{
theme
}
=
props
;
return
[
prefixCls
,
`
${
prefixCls
}
-
${
theme
}
`
,
`
${
prefixCls
}
-vertical`
,
{
[
`
${
prefixCls
}
-collapse`
]:
props
.
collapse
,
},
];
});
watchEffect
(()
=>
{
openedNames
.
value
=
props
.
openNames
;
});
watchEffect
(()
=>
{
if
(
props
.
activeName
)
{
currentActiveName
.
value
=
props
.
activeName
;
}
});
watch
(
()
=>
props
.
openNames
,
()
=>
{
nextTick
(()
=>
{
updateOpened
();
});
}
);
function
updateOpened
()
{
rootMenuEmitter
.
emit
(
'
on-update-opened
'
,
openedNames
.
value
);
}
function
addSubMenu
(
name
:
string
)
{
if
(
openedNames
.
value
.
includes
(
name
))
return
;
openedNames
.
value
.
push
(
name
);
updateOpened
();
}
function
removeSubMenu
(
name
:
string
)
{
openedNames
.
value
=
openedNames
.
value
.
filter
((
item
)
=>
item
!==
name
);
updateOpened
();
}
function
removeAll
()
{
openedNames
.
value
=
[];
updateOpened
();
}
function
sliceIndex
(
index
:
number
)
{
if
(
index
===
-
1
)
return
;
openedNames
.
value
=
openedNames
.
value
.
slice
(
0
,
index
+
1
);
updateOpened
();
}
provide
<
SubMenuProvider
>
(
`subMenu:
${
instance
?.
uid
}
`
,
{
addSubMenu
,
removeSubMenu
,
getOpenNames
:
()
=>
openedNames
.
value
,
removeAll
,
isRemoveAllPopup
,
sliceIndex
,
level
:
0
,
props
,
});
onMounted
(()
=>
{
openedNames
.
value
=
!
props
.
collapse
?
[...
props
.
openNames
]
:
[];
updateOpened
();
rootMenuEmitter
.
on
(
'
on-menu-item-select
'
,
(
name
:
string
)
=>
{
currentActiveName
.
value
=
name
;
nextTick
(()
=>
{
props
.
collapse
&&
removeAll
();
});
emit
(
'
select
'
,
name
);
});
});
return
{
getClass
,
openedNames
};
},
});
</
script
>
<
style
lang=
"less"
>
@import './menu.less';
</
style
>
src/components/SimpleMenu/src/components/MenuCollapseTransition.vue
0 → 100644
浏览文件 @
ff2b12b4
<
template
>
<transition
mode=
"out-in"
v-on=
"on"
>
<slot></slot>
</transition>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'
vue
'
;
import
{
addClass
,
removeClass
}
from
'
/@/utils/domUtils
'
;
export
default
defineComponent
({
name
:
'
MenuCollapseTransition
'
,
setup
()
{
return
{
on
:
{
beforeEnter
(
el
:
any
)
{
addClass
(
el
,
'
collapse-transition
'
);
if
(
!
el
.
dataset
)
el
.
dataset
=
{};
el
.
dataset
.
oldPaddingTop
=
el
.
style
.
paddingTop
;
el
.
dataset
.
oldPaddingBottom
=
el
.
style
.
paddingBottom
;
el
.
style
.
height
=
'
0
'
;
el
.
style
.
paddingTop
=
0
;
el
.
style
.
paddingBottom
=
0
;
},
enter
(
el
:
any
)
{
el
.
dataset
.
oldOverflow
=
el
.
style
.
overflow
;
if
(
el
.
scrollHeight
!==
0
)
{
el
.
style
.
height
=
el
.
scrollHeight
+
'
px
'
;
el
.
style
.
paddingTop
=
el
.
dataset
.
oldPaddingTop
;
el
.
style
.
paddingBottom
=
el
.
dataset
.
oldPaddingBottom
;
}
else
{
el
.
style
.
height
=
''
;
el
.
style
.
paddingTop
=
el
.
dataset
.
oldPaddingTop
;
el
.
style
.
paddingBottom
=
el
.
dataset
.
oldPaddingBottom
;
}
el
.
style
.
overflow
=
'
hidden
'
;
},
afterEnter
(
el
:
any
)
{
removeClass
(
el
,
'
collapse-transition
'
);
el
.
style
.
height
=
''
;
el
.
style
.
overflow
=
el
.
dataset
.
oldOverflow
;
},
beforeLeave
(
el
:
any
)
{
if
(
!
el
.
dataset
)
el
.
dataset
=
{};
el
.
dataset
.
oldPaddingTop
=
el
.
style
.
paddingTop
;
el
.
dataset
.
oldPaddingBottom
=
el
.
style
.
paddingBottom
;
el
.
dataset
.
oldOverflow
=
el
.
style
.
overflow
;
el
.
style
.
height
=
el
.
scrollHeight
+
'
px
'
;
el
.
style
.
overflow
=
'
hidden
'
;
},
leave
(
el
:
any
)
{
if
(
el
.
scrollHeight
!==
0
)
{
addClass
(
el
,
'
collapse-transition
'
);
el
.
style
.
height
=
0
;
el
.
style
.
paddingTop
=
0
;
el
.
style
.
paddingBottom
=
0
;
}
},
afterLeave
(
el
:
any
)
{
removeClass
(
el
,
'
collapse-transition
'
);
el
.
style
.
height
=
''
;
el
.
style
.
overflow
=
el
.
dataset
.
oldOverflow
;
el
.
style
.
paddingTop
=
el
.
dataset
.
oldPaddingTop
;
el
.
style
.
paddingBottom
=
el
.
dataset
.
oldPaddingBottom
;
},
},
};
},
});
</
script
>
src/components/SimpleMenu/src/components/MenuItem.vue
0 → 100644
浏览文件 @
ff2b12b4
<
template
>
<li
:class=
"getClass"
@
click.stop=
"handleClickItem"
:style=
"getCollapse ?
{} : getItemStyle">
<Tooltip
placement=
"right"
v-if=
"showTooptip"
>
<template
#title
>
<slot
name=
"title"
></slot>
</
template
>
<div
:class=
"`${prefixCls}-tooltip`"
>
<slot
/>
</div>
</Tooltip>
<
template
v-else
>
<slot></slot>
<slot
name=
"title"
></slot>
</
template
>
</li>
</template>
<
script
lang=
"ts"
>
import
{
PropType
}
from
'
vue
'
;
import
{
defineComponent
,
ref
,
computed
,
unref
,
getCurrentInstance
,
watch
}
from
'
vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
import
{
useMenuItem
}
from
'
./useMenu
'
;
import
{
Tooltip
}
from
'
ant-design-vue
'
;
import
{
useSimpleRootMenuContext
}
from
'
./useSimpleMenuContext
'
;
export
default
defineComponent
({
name
:
'
MenuItem
'
,
components
:
{
Tooltip
},
props
:
{
name
:
{
type
:
[
String
,
Number
]
as
PropType
<
string
|
number
>
,
required
:
true
,
},
disabled
:
propTypes
.
bool
,
},
setup
(
props
,
{
slots
})
{
const
instance
=
getCurrentInstance
();
const
active
=
ref
(
false
);
const
{
getItemStyle
,
getParentList
,
getParentMenu
,
getParentRootMenu
}
=
useMenuItem
(
instance
);
const
{
prefixCls
}
=
useDesign
(
'
menu
'
);
const
{
rootMenuEmitter
,
activeName
}
=
useSimpleRootMenuContext
();
const
getClass
=
computed
(()
=>
{
return
[
`
${
prefixCls
}
-item`
,
{
[
`
${
prefixCls
}
-item-active`
]:
unref
(
active
),
[
`
${
prefixCls
}
-item-selected`
]:
unref
(
active
),
[
`
${
prefixCls
}
-item-disabled`
]:
!!
props
.
disabled
,
},
];
});
const
getCollapse
=
computed
(()
=>
unref
(
getParentRootMenu
)?.
props
.
collapse
);
const
showTooptip
=
computed
(()
=>
{
return
unref
(
getParentMenu
)?.
type
.
name
===
'
Menu
'
&&
unref
(
getCollapse
)
&&
slots
.
title
;
});
function
handleClickItem
()
{
const
{
disabled
}
=
props
;
if
(
disabled
)
return
;
rootMenuEmitter
.
emit
(
'
on-menu-item-select
'
,
props
.
name
);
if
(
unref
(
getCollapse
))
return
;
const
{
uidList
}
=
getParentList
();
rootMenuEmitter
.
emit
(
'
on-update-opened
'
,
{
opend
:
false
,
parent
:
instance
?.
parent
,
uidList
:
uidList
,
});
}
watch
(
()
=>
activeName
.
value
,
(
name
:
string
)
=>
{
if
(
name
===
props
.
name
)
{
const
{
list
,
uidList
}
=
getParentList
();
active
.
value
=
true
;
list
.
forEach
((
item
)
=>
{
if
(
item
.
proxy
)
{
(
item
.
proxy
as
any
).
active
=
true
;
}
});
rootMenuEmitter
.
emit
(
'
on-update-active-name:submenu
'
,
uidList
);
}
else
{
active
.
value
=
false
;
}
},
{
immediate
:
true
}
);
return
{
getClass
,
prefixCls
,
getItemStyle
,
getCollapse
,
handleClickItem
,
showTooptip
};
},
});
</
script
>
src/components/SimpleMenu/src/components/SubMenuItem.vue
0 → 100644
浏览文件 @
ff2b12b4
<
template
>
<li
:class=
"getClass"
>
<template
v-if=
"!getCollapse"
>
<div
:class=
"`$
{prefixCls}-submenu-title`" @click.stop="handleClick" :style="getItemStyle">
<slot
name=
"title"
></slot>
<Icon
icon=
"eva:arrow-ios-downward-outline"
:size=
"14"
:class=
"`$
{prefixCls}-submenu-title-icon`"
/>
</div>
<MenuCollapseTransition>
<ul
:class=
"prefixCls"
v-show=
"opened"
>
<slot></slot>
</ul>
</MenuCollapseTransition>
</
template
>
<Popover
placement=
"right"
:overlayClassName=
"`${prefixCls}-menu-popover`"
v-else
:visible=
"getIsOpend"
@
visibleChange=
"handleVisibleChange"
:overlayStyle=
"getOverlayStyle"
:align=
"{ offset: [0, 0] }"
>
<div
:class=
"getSubClass"
v-bind=
"getEvents(false)"
>
<div
:class=
"[
{
[`${prefixCls}-submenu-popup`]: !getParentSubMenu,
[`${prefixCls}-submenu-collapsed-show-tit`]: collapsedShowTitle,
},
]"
>
<slot
name=
"title"
></slot>
</div>
<Icon
v-if=
"getParentSubMenu"
icon=
"eva:arrow-ios-downward-outline"
:size=
"14"
:class=
"`${prefixCls}-submenu-title-icon`"
/>
</div>
<
template
#content
v-show=
"opened"
>
<div
v-bind=
"getEvents(true)"
>
<ul
:class=
"[prefixCls, `$
{prefixCls}-${getTheme}`, `${prefixCls}-popup`]">
<slot></slot>
</ul>
</div>
</
template
>
</Popover>
</li>
</template>
<
script
lang=
"ts"
>
import
type
{
CSSProperties
,
PropType
}
from
'
vue
'
;
import
type
{
SubMenuProvider
}
from
'
./types
'
;
import
{
defineComponent
,
computed
,
unref
,
getCurrentInstance
,
toRefs
,
reactive
,
provide
,
onBeforeMount
,
inject
,
}
from
'
vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
import
{
useMenuItem
}
from
'
./useMenu
'
;
import
{
useSimpleRootMenuContext
}
from
'
./useSimpleMenuContext
'
;
import
MenuCollapseTransition
from
'
./MenuCollapseTransition.vue
'
;
import
Icon
from
'
/@/components/Icon
'
;
import
{
Popover
}
from
'
ant-design-vue
'
;
import
{
isBoolean
,
isObject
}
from
'
/@/utils/is
'
;
import
Mitt
from
'
/@/utils/mitt
'
;
const
DELAY
=
200
;
export
default
defineComponent
({
name
:
'
SubMenu
'
,
components
:
{
Icon
,
MenuCollapseTransition
,
Popover
,
},
props
:
{
name
:
{
type
:
[
String
,
Number
]
as
PropType
<
string
|
number
>
,
required
:
true
,
},
disabled
:
propTypes
.
bool
,
collapsedShowTitle
:
propTypes
.
bool
,
},
setup
(
props
)
{
const
instance
=
getCurrentInstance
();
const
state
=
reactive
({
active
:
false
,
opened
:
false
,
});
const
data
=
reactive
({
timeout
:
null
as
TimeoutHandle
|
null
,
mouseInChild
:
false
,
isChild
:
false
,
});
const
{
getParentSubMenu
,
getItemStyle
,
getParentMenu
,
getParentList
}
=
useMenuItem
(
instance
);
const
{
prefixCls
}
=
useDesign
(
'
menu
'
);
const
subMenuEmitter
=
new
Mitt
();
const
{
rootMenuEmitter
}
=
useSimpleRootMenuContext
();
const
{
addSubMenu
:
parentAddSubmenu
,
removeSubMenu
:
parentRemoveSubmenu
,
removeAll
:
parentRemoveAll
,
getOpenNames
:
parentGetOpenNames
,
isRemoveAllPopup
,
sliceIndex
,
level
,
props
:
rootProps
,
handleMouseleave
:
parentHandleMouseleave
,
}
=
inject
<
SubMenuProvider
>
(
`subMenu:
${
getParentMenu
.
value
?.
uid
}
`
)
!
;
const
getClass
=
computed
(()
=>
{
return
[
`
${
prefixCls
}
-submenu`
,
{
[
`
${
prefixCls
}
-item-active`
]:
state
.
active
,
[
`
${
prefixCls
}
-opened`
]:
state
.
opened
,
[
`
${
prefixCls
}
-submenu-disabled`
]:
props
.
disabled
,
[
`
${
prefixCls
}
-submenu-has-parent-submenu`
]:
unref
(
getParentSubMenu
),
[
`
${
prefixCls
}
-child-item-active`
]:
state
.
active
,
},
];
});
const
getAccordion
=
computed
(()
=>
rootProps
.
accordion
);
const
getCollapse
=
computed
(()
=>
rootProps
.
collapse
);
const
getTheme
=
computed
(()
=>
rootProps
.
theme
);
const
getOverlayStyle
=
computed
(
():
CSSProperties
=>
{
return
{
minWidth
:
'
200px
'
,
};
}
);
const
getIsOpend
=
computed
(()
=>
{
const
name
=
props
.
name
;
if
(
unref
(
getCollapse
))
{
return
parentGetOpenNames
().
includes
(
name
);
}
return
state
.
opened
;
});
const
getSubClass
=
computed
(()
=>
{
const
isActive
=
rootProps
.
activeSubMenuNames
.
includes
(
props
.
name
);
return
[
`
${
prefixCls
}
-submenu-title`
,
{
[
`
${
prefixCls
}
-submenu-active`
]:
isActive
,
[
`
${
prefixCls
}
-submenu-active-border`
]:
isActive
&&
level
===
0
,
[
`
${
prefixCls
}
-submenu-collapse`
]:
unref
(
getCollapse
)
&&
level
===
0
,
},
];
});
function
getEvents
(
deep
:
boolean
)
{
if
(
!
unref
(
getCollapse
))
{
return
{};
}
return
{
onMouseenter
:
handleMouseenter
,
onMouseleave
:
()
=>
handleMouseleave
(
deep
),
};
}
function
handleClick
()
{
const
{
disabled
}
=
props
;
if
(
disabled
||
unref
(
getCollapse
))
return
;
const
opened
=
state
.
opened
;
if
(
unref
(
getAccordion
))
{
const
{
uidList
}
=
getParentList
();
rootMenuEmitter
.
emit
(
'
on-update-opened
'
,
{
opend
:
false
,
parent
:
instance
?.
parent
,
uidList
:
uidList
,
});
}
state
.
opened
=
!
opened
;
}
function
handleMouseenter
()
{
const
disabled
=
props
.
disabled
;
if
(
disabled
)
return
;
subMenuEmitter
.
emit
(
'
submenu:mouse-enter-child
'
);
const
index
=
parentGetOpenNames
().
findIndex
((
item
)
=>
item
===
props
.
name
);
sliceIndex
(
index
);
const
isRoot
=
level
===
0
&&
parentGetOpenNames
().
length
===
2
;
if
(
isRoot
)
{
parentRemoveAll
();
}
data
.
isChild
=
parentGetOpenNames
().
includes
(
props
.
name
);
clearTimeout
(
data
.
timeout
!
);
data
.
timeout
=
setTimeout
(()
=>
{
parentAddSubmenu
(
props
.
name
);
},
DELAY
);
}
function
handleMouseleave
(
deepDispatch
=
false
)
{
const
parentName
=
getParentMenu
.
value
?.
props
.
name
;
if
(
!
parentName
)
{
isRemoveAllPopup
.
value
=
true
;
}
if
(
parentGetOpenNames
().
slice
(
-
1
)[
0
]
===
props
.
name
)
{
data
.
isChild
=
false
;
}
subMenuEmitter
.
emit
(
'
submenu:mouse-leave-child
'
);
if
(
data
.
timeout
)
{
clearTimeout
(
data
.
timeout
!
);
data
.
timeout
=
setTimeout
(()
=>
{
if
(
isRemoveAllPopup
.
value
)
{
parentRemoveAll
();
}
else
if
(
!
data
.
mouseInChild
)
{
parentRemoveSubmenu
(
props
.
name
);
}
},
DELAY
);
}
if
(
deepDispatch
)
{
if
(
getParentSubMenu
.
value
)
{
parentHandleMouseleave
?.(
true
);
}
}
}
onBeforeMount
(()
=>
{
subMenuEmitter
.
on
(
'
submenu:mouse-enter-child
'
,
()
=>
{
data
.
mouseInChild
=
true
;
isRemoveAllPopup
.
value
=
false
;
clearTimeout
(
data
.
timeout
!
);
});
subMenuEmitter
.
on
(
'
submenu:mouse-leave-child
'
,
()
=>
{
if
(
data
.
isChild
)
return
;
data
.
mouseInChild
=
false
;
clearTimeout
(
data
.
timeout
!
);
});
rootMenuEmitter
.
on
(
'
on-update-opened
'
,
(
data
:
boolean
|
(
string
|
number
)[]
|
Recordable
)
=>
{
if
(
unref
(
getCollapse
))
return
;
if
(
isBoolean
(
data
))
{
state
.
opened
=
data
;
return
;
}
if
(
isObject
(
data
))
{
const
{
opend
,
parent
,
uidList
}
=
data
as
Recordable
;
if
(
parent
===
instance
?.
parent
)
{
state
.
opened
=
opend
;
}
else
if
(
!
uidList
.
includes
(
instance
?.
uid
))
{
state
.
opened
=
false
;
}
return
;
}
if
(
props
.
name
&&
Array
.
isArray
(
data
))
{
state
.
opened
=
(
data
as
(
string
|
number
)[]).
includes
(
props
.
name
);
}
}
);
rootMenuEmitter
.
on
(
'
on-update-active-name:submenu
'
,
(
data
:
number
[])
=>
{
state
.
active
=
data
.
includes
(
instance
?.
uid
!
);
});
});
function
handleVisibleChange
(
visible
:
boolean
)
{
state
.
opened
=
visible
;
}
// provide
provide
<
SubMenuProvider
>
(
`subMenu:
${
instance
?.
uid
}
`
,
{
addSubMenu
:
parentAddSubmenu
,
removeSubMenu
:
parentRemoveSubmenu
,
getOpenNames
:
parentGetOpenNames
,
removeAll
:
parentRemoveAll
,
isRemoveAllPopup
,
sliceIndex
,
level
:
level
+
1
,
handleMouseleave
,
props
:
rootProps
,
});
return
{
getClass
,
prefixCls
,
getCollapse
,
getItemStyle
,
handleClick
,
handleVisibleChange
,
getParentSubMenu
,
getOverlayStyle
,
getTheme
,
getIsOpend
,
getEvents
,
getSubClass
,
...
toRefs
(
state
),
...
toRefs
(
data
),
};
},
});
</
script
>
src/components/SimpleMenu/src/components/menu.less
0 → 100644
浏览文件 @
ff2b12b4
@menu-prefix-cls: ~'@{namespace}-menu';
@menu-popup-prefix-cls: ~'@{namespace}-menu-popup';
@submenu-popup-prefix-cls: ~'@{namespace}-menu-submenu-popup';
// @menu-dark: #191a23;
// @menu-dark-active-bg: #101117;
@transition-time: 0.2s;
@menu-dark-subsidiary-color: rgba(255, 255, 255, 0.7);
.light-border {
&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
display: block;
width: 2px;
background: @primary-color;
content: '';
}
}
.@{menu-prefix-cls}-menu-popover {
.ant-popover-arrow {
display: none;
}
.ant-popover-inner-content {
padding: 0;
}
.@{menu-prefix-cls} {
&-opened > * > &-submenu-title-icon {
transform: translateY(-50%) rotate(90deg) !important;
}
&-item,
&-submenu-title {
position: relative;
z-index: 1;
padding: 12px 20px;
color: @menu-dark-subsidiary-color;
cursor: pointer;
transition: all @transition-time @ease-in-out;
// &:hover {
// color: @primary-color;
// }
&-icon {
position: absolute;
top: 50%;
right: 18px;
transform: translateY(-50%) rotate(-90deg);
transition: transform @transition-time @ease-in-out;
}
}
&-dark {
.@{menu-prefix-cls}-item,
.@{menu-prefix-cls}-submenu-title {
color: @menu-dark-subsidiary-color;
// background: @menu-dark-active-bg;
&:hover {
color: #fff;
}
&-selected {
color: #fff;
background: @primary-color !important;
}
}
}
&-light {
.@{menu-prefix-cls}-item,
.@{menu-prefix-cls}-submenu-title {
color: @text-color-base;
&:hover {
color: @primary-color;
}
&-selected {
z-index: 2;
color: @primary-color;
background: fade(@primary-color, 8);
.light-border();
}
}
}
}
}
.content();
.content() {
.@{menu-prefix-cls} {
position: relative;
display: block;
width: 100%;
padding: 0;
margin: 0;
font-size: @font-size-base;
color: @text-color-base;
list-style: none;
outline: none;
.collapse-transition {
transition: @transition-time height ease-in-out, @transition-time padding-top ease-in-out,
@transition-time padding-bottom ease-in-out;
}
&-light {
background: #fff;
.@{menu-prefix-cls}-submenu-active {
color: @primary-color !important;
// background: fade(@primary-color, 8);
&-border {
.light-border();
}
}
}
&-dark {
// background: @menu-dark;
.@{menu-prefix-cls}-submenu-active {
color: #fff !important;
}
}
&-item {
position: relative;
z-index: 1;
display: flex;
font-size: @font-size-base;
color: inherit;
list-style: none;
cursor: pointer;
outline: none;
align-items: center;
// transition: all @transition-time @ease-in-out;
&:hover,
&:active {
color: inherit;
}
}
&-item > i {
margin-right: 6px;
}
&-submenu-title > i,
&-submenu-title span > i {
margin-right: 8px;
}
// vertical
&-vertical &-item,
&-vertical &-submenu-title {
position: relative;
z-index: 1;
padding: 12px 24px;
cursor: pointer;
// transition: all @transition-time @ease-in-out;
&:hover {
color: @primary-color;
}
.@{menu-prefix-cls}-tooltip {
width: calc(100% - 0px);
padding: 12px 0;
text-align: center;
}
.@{menu-prefix-cls}-submenu-popup {
padding: 12px 0;
}
}
&-vertical &-submenu-collapse {
.@{submenu-popup-prefix-cls} {
display: flex;
justify-content: center;
align-items: center;
}
.@{menu-prefix-cls}-submenu-collapsed-show-tit {
flex-direction: column;
}
}
&-vertical&-collapse &-item,
&-vertical&-collapse &-submenu-title {
padding: 0 0;
}
&-vertical &-submenu-title-icon {
position: absolute;
top: 50%;
right: 18px;
transform: translateY(-50%);
}
&-submenu-title-icon {
transition: transform @transition-time @ease-in-out;
}
&-vertical &-opened > * > &-submenu-title-icon {
transform: translateY(-50%) rotate(180deg);
}
&-vertical &-submenu {
&-nested {
padding-left: 20px;
}
.@{menu-prefix-cls}-item {
padding-left: 43px;
}
}
&-light&-vertical &-item {
&-active:not(.@{menu-prefix-cls}-submenu) {
z-index: 2;
color: @primary-color;
background: fade(@primary-color, 8);
.light-border();
}
&-active.@{menu-prefix-cls}-submenu {
color: @primary-color;
}
}
&-light&-vertical&-collapse {
> li.@{menu-prefix-cls}-item-active,
.@{menu-prefix-cls}-submenu-active {
position: relative;
background: fade(@primary-color, 3);
&::after {
display: none;
}
&::before {
position: absolute;
top: 0;
left: 0;
width: 3px;
height: 100%;
background: @primary-color;
content: '';
}
}
}
&-dark&-vertical &-item,
&-dark&-vertical &-submenu-title {
color: @menu-dark-subsidiary-color;
&-active:not(.@{menu-prefix-cls}-submenu) {
color: #fff !important;
background: @primary-color !important;
}
&:hover {
color: #fff;
// background: @menu-dark;
}
// &-active:not(.@{menu-prefix-cls}-submenu) {
// color: @primary-color;
// }
}
&-dark&-vertical&-collapse {
> li.@{menu-prefix-cls}-item-active,
.@{menu-prefix-cls}-submenu-active {
position: relative;
color: #fff !important;
background-color: @sider-dark-darken-bg-color !important;
&::before {
position: absolute;
top: 0;
left: 0;
width: 3px;
height: 100%;
background: @primary-color;
content: '';
}
.@{menu-prefix-cls}-submenu-collapse {
background-color: transparent;
}
}
}
&-dark&-vertical &-submenu &-item {
// &:hover {
// color: #fff;
// background: transparent;
// }
&-active,
&-active:hover {
color: #fff;
border-right: none;
}
}
&-dark&-vertical &-child-item-active > &-submenu-title {
color: #fff;
}
&-dark&-vertical &-opened {
// background: @menu-dark-active-bg;
// .@{menu-prefix-cls}-submenu-title {
// background: @menu-dark;
// }
.@{menu-prefix-cls}-submenu-has-parent-submenu {
.@{menu-prefix-cls}-submenu-title {
background: transparent;
}
}
}
}
}
src/components/SimpleMenu/src/components/types.ts
0 → 100644
浏览文件 @
ff2b12b4
import
{
Ref
}
from
'
vue
'
;
export
interface
Props
{
theme
:
string
;
activeName
?:
string
|
number
|
undefined
;
openNames
:
string
[];
accordion
:
boolean
;
width
:
string
;
collapsedWidth
:
string
;
indentSize
:
number
;
collapse
:
boolean
;
activeSubMenuNames
:
(
string
|
number
)[];
}
export
interface
SubMenuProvider
{
addSubMenu
:
(
name
:
string
|
number
,
update
?:
boolean
)
=>
void
;
removeSubMenu
:
(
name
:
string
|
number
,
update
?:
boolean
)
=>
void
;
removeAll
:
()
=>
void
;
sliceIndex
:
(
index
:
number
)
=>
void
;
isRemoveAllPopup
:
Ref
<
boolean
>
;
getOpenNames
:
()
=>
(
string
|
number
)[];
handleMouseleave
?:
Fn
;
level
:
number
;
props
:
Props
;
}
src/components/SimpleMenu/src/components/useMenu.ts
0 → 100644
浏览文件 @
ff2b12b4
import
{
computed
,
ComponentInternalInstance
,
unref
}
from
'
vue
'
;
import
type
{
CSSProperties
}
from
'
vue
'
;
export
function
useMenuItem
(
instance
:
ComponentInternalInstance
|
null
)
{
const
getParentMenu
=
computed
(()
=>
{
return
findParentMenu
([
'
Menu
'
,
'
SubMenu
'
]);
});
const
getParentRootMenu
=
computed
(()
=>
{
return
findParentMenu
([
'
Menu
'
]);
});
const
getParentSubMenu
=
computed
(()
=>
{
return
findParentMenu
([
'
SubMenu
'
]);
});
const
getItemStyle
=
computed
(
():
CSSProperties
=>
{
let
parent
=
instance
?.
parent
;
if
(
!
parent
)
return
{};
const
indentSize
=
(
unref
(
getParentRootMenu
)?.
props
.
indentSize
as
number
)
??
20
;
let
padding
=
indentSize
;
if
(
unref
(
getParentRootMenu
)?.
props
.
collapse
)
{
padding
=
indentSize
;
}
else
{
while
(
parent
&&
parent
.
type
.
name
!==
'
Menu
'
)
{
if
(
parent
.
type
.
name
===
'
SubMenu
'
)
{
padding
+=
indentSize
;
}
parent
=
parent
.
parent
;
}
}
return
{
paddingLeft
:
padding
+
'
px
'
};
}
);
function
findParentMenu
(
name
:
string
[])
{
let
parent
=
instance
?.
parent
;
if
(
!
parent
)
return
null
;
while
(
parent
&&
name
.
indexOf
(
parent
.
type
.
name
!
)
===
-
1
)
{
parent
=
parent
.
parent
;
}
return
parent
;
}
function
getParentList
()
{
let
parent
=
instance
;
if
(
!
parent
)
return
{
uidList
:
[],
list
:
[],
};
const
ret
=
[];
while
(
parent
&&
parent
.
type
.
name
!==
'
Menu
'
)
{
if
(
parent
.
type
.
name
===
'
SubMenu
'
)
{
ret
.
push
(
parent
);
}
parent
=
parent
.
parent
;
}
return
{
uidList
:
ret
.
map
((
item
)
=>
item
.
uid
),
list
:
ret
,
};
}
function
getParentInstance
(
instance
:
ComponentInternalInstance
,
name
=
'
SubMenu
'
)
{
let
parent
=
instance
.
parent
;
while
(
parent
)
{
if
(
parent
.
type
.
name
!==
name
)
{
return
parent
;
}
parent
=
parent
.
parent
;
}
return
parent
;
}
return
{
getParentMenu
,
getParentInstance
,
getParentRootMenu
,
getParentList
,
getParentSubMenu
,
getItemStyle
,
};
}
src/components/SimpleMenu/src/components/useSimpleMenuContext.ts
0 → 100644
浏览文件 @
ff2b12b4
import
type
{
InjectionKey
,
Ref
}
from
'
vue
'
;
import
{
createContext
,
useContext
}
from
'
/@/hooks/core/useContext
'
;
import
Mitt
from
'
/@/utils/mitt
'
;
export
interface
SimpleRootMenuContextProps
{
rootMenuEmitter
:
Mitt
;
activeName
:
Ref
<
string
|
number
>
;
}
const
key
:
InjectionKey
<
SimpleRootMenuContextProps
>
=
Symbol
();
export
function
createSimpleRootMenuContext
(
context
:
SimpleRootMenuContextProps
)
{
return
createContext
<
SimpleRootMenuContextProps
>
(
context
,
key
,
{
readonly
:
false
,
native
:
true
});
}
export
function
useSimpleRootMenuContext
()
{
return
useContext
<
SimpleRootMenuContextProps
>
(
key
);
}
src/components/SimpleMenu/src/index.less
0 → 100644
浏览文件 @
ff2b12b4
@simple-prefix-cls: ~'@{namespace}-simple-menu';
@prefix-cls: ~'@{namespace}-menu';
.@{prefix-cls} {
&-dark&-vertical .@{simple-prefix-cls}__parent {
background-color: @sider-dark-bg-color;
> .@{prefix-cls}-submenu-title {
background-color: @sider-dark-bg-color;
}
}
&-dark&-vertical .@{simple-prefix-cls}__children,
&-dark&-popup .@{simple-prefix-cls}__children {
background-color: @sider-dark-lighten-1-bg-color;
> .@{prefix-cls}-submenu-title {
background-color: @sider-dark-lighten-1-bg-color;
}
}
.collapse-title {
font-size: 12px;
}
}
.@{simple-prefix-cls} {
&-tag {
position: absolute;
top: calc(50% - 10px);
right: 30px;
display: inline-block;
padding: 2px 3px;
margin-right: 4px;
font-size: 10px;
line-height: 14px;
color: #fff;
border-radius: 2px;
&--collapse {
top: 6px !important;
right: 2px;
}
&--dot {
top: calc(50% - 4px);
width: 6px;
height: 6px;
padding: 0;
border-radius: 50%;
}
&--primary {
background: @primary-color;
}
&--error {
background: @error-color;
}
&--success {
background: @success-color;
}
&--warn {
background: @warning-color;
}
}
}
src/components/SimpleMenu/src/types.ts
0 → 100644
浏览文件 @
ff2b12b4
export
interface
MenuState
{
activeName
:
string
;
openNames
:
string
[];
activeSubMenuNames
:
string
[];
}
src/components/SimpleMenu/src/useOpenKeys.ts
0 → 100644
浏览文件 @
ff2b12b4
import
type
{
Menu
as
MenuType
}
from
'
/@/router/types
'
;
import
type
{
MenuState
}
from
'
./types
'
;
import
{
Ref
,
toRaw
}
from
'
vue
'
;
import
{
unref
}
from
'
vue
'
;
import
{
es6Unique
}
from
'
/@/utils
'
;
import
{
getAllParentPath
}
from
'
/@/router/helper/menuHelper
'
;
import
{
useTimeoutFn
}
from
'
/@/hooks/core/useTimeout
'
;
export
function
useOpenKeys
(
menuState
:
MenuState
,
menus
:
Ref
<
MenuType
[]
>
,
accordion
:
Ref
<
boolean
>
,
mixSider
:
Ref
<
boolean
>
// mode: Ref<MenuModeEnum>,
)
{
async
function
setOpenKeys
(
path
:
string
)
{
// if (mode.value === MenuModeEnum.HORIZONTAL) {
// return;
// }
const
native
=
!
mixSider
.
value
;
useTimeoutFn
(
()
=>
{
const
menuList
=
toRaw
(
menus
.
value
);
if
(
menuList
?.
length
===
0
)
{
menuState
.
activeSubMenuNames
=
[];
menuState
.
openNames
=
[];
return
;
}
const
keys
=
getAllParentPath
(
menuList
,
path
);
if
(
!
unref
(
accordion
))
{
menuState
.
openNames
=
es6Unique
([...
menuState
.
openNames
,
...
keys
]);
}
else
{
menuState
.
openNames
=
keys
;
}
menuState
.
activeSubMenuNames
=
menuState
.
openNames
;
},
16
,
native
);
}
return
{
setOpenKeys
};
}
src/components/Table/src/components/editable/EditableCell.vue
浏览文件 @
ff2b12b4
...
...
@@ -31,7 +31,7 @@
import
type
{
CSSProperties
,
PropType
}
from
'
vue
'
;
import
type
{
BasicColumn
}
from
'
../../types/table
'
;
import
{
defineComponent
,
ref
,
unref
,
nextTick
,
computed
,
watchEffect
,
toRaw
}
from
'
vue
'
;
import
{
defineComponent
,
ref
,
unref
,
nextTick
,
computed
,
watchEffect
}
from
'
vue
'
;
import
{
FormOutlined
,
CloseOutlined
,
CheckOutlined
}
from
'
@ant-design/icons-vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
...
...
src/components/Table/src/hooks/useProvinceTable.ts
已删除
100644 → 0
浏览文件 @
056fc131
import
type
{
Ref
}
from
'
vue
'
;
import
type
{
TableActionType
}
from
'
../types/table
'
;
import
{
provide
,
inject
}
from
'
vue
'
;
const
key
=
Symbol
(
'
table
'
);
type
Instance
=
TableActionType
&
{
wrapRef
:
Ref
<
Nullable
<
HTMLElement
>>
};
export
function
provideTable
(
instance
:
Instance
)
{
provide
(
key
,
instance
);
}
export
function
injectTable
():
Instance
{
return
inject
(
key
)
as
Instance
;
}
src/design/ant/index.less
浏览文件 @
ff2b12b4
...
...
@@ -22,6 +22,12 @@
background: rgba(0, 0, 0, 0.3);
}
.ant-popover {
&-content {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
}
// =================================
// ==============descriptions=======
// =================================
...
...
src/design/color.less
浏览文件 @
ff2b12b4
...
...
@@ -9,7 +9,6 @@
--sider-dark-darken-bg-color: #273352;
--sider-dark-lighten-1-bg-color: #273352;
--sider-dark-lighten-2-bg-color: #273352;
--sider-dark-lighten-3-bg-color: #273352;
}
@white: #fff;
...
...
@@ -88,7 +87,6 @@
@sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color);
@sider-dark-lighten-1-bg-color: var(--sider-dark-lighten-1-bg-color);
@sider-dark-lighten-2-bg-color: var(--sider-dark-lighten-2-bg-color);
@sider-dark-lighten-3-bg-color: var(--sider-dark-lighten-3-bg-color);
// trigger
@trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2);
...
...
src/hooks/setting/useMenuSetting.ts
浏览文件 @
ff2b12b4
...
...
@@ -78,9 +78,12 @@ const getIsMixMode = computed(() => {
});
const
getRealWidth
=
computed
(()
=>
{
return
unref
(
getCollapsed
)
&&
!
unref
(
getMixSideFixed
)
?
unref
(
getMiniWidthNumber
)
:
unref
(
getMenuWidth
);
if
(
unref
(
getIsMixSidebar
))
{
return
unref
(
getCollapsed
)
&&
!
unref
(
getMixSideFixed
)
?
unref
(
getMiniWidthNumber
)
:
unref
(
getMenuWidth
);
}
return
unref
(
getCollapsed
)
?
unref
(
getMiniWidthNumber
)
:
unref
(
getMenuWidth
);
});
const
getMiniWidthNumber
=
computed
(()
=>
{
...
...
src/layouts/default/header/index.vue
浏览文件 @
ff2b12b4
...
...
@@ -142,7 +142,7 @@
});
const
getLogoWidth
=
computed
(()
=>
{
if
(
!
unref
(
getIsMixMode
))
{
if
(
!
unref
(
getIsMixMode
)
||
unref
(
getIsMobile
)
)
{
return
{};
}
const
width
=
unref
(
getMenuWidth
)
<
180
?
180
:
unref
(
getMenuWidth
);
...
...
src/layouts/default/menu/index.tsx
浏览文件 @
ff2b12b4
...
...
@@ -4,6 +4,7 @@ import type { PropType, CSSProperties } from 'vue';
import
{
computed
,
defineComponent
,
unref
,
toRef
}
from
'
vue
'
;
import
{
BasicMenu
}
from
'
/@/components/Menu
'
;
import
{
SimpleMenu
}
from
'
/@/components/SimpleMenu
'
;
import
{
AppLogo
}
from
'
/@/components/Application
'
;
import
{
MenuModeEnum
,
MenuSplitTyeEnum
}
from
'
/@/enums/menuEnum
'
;
...
...
@@ -126,7 +127,18 @@ export default defineComponent({
}
function
renderMenu
()
{
return
(
const
menus
=
unref
(
menusRef
);
if
(
!
menus
||
!
menus
.
length
)
return
null
;
return
!
props
.
isHorizontal
?
(
<
SimpleMenu
items
=
{
menus
}
theme
=
{
unref
(
getComputedMenuTheme
)
}
accordion
=
{
unref
(
getAccordion
)
}
collapse
=
{
unref
(
getCollapsed
)
}
collapsedShowTitle
=
{
unref
(
getCollapsedShowTitle
)
}
onMenuClick
=
{
handleMenuClick
}
/>
)
:
(
<
BasicMenu
beforeClickFn
=
{
beforeMenuClickFn
}
isHorizontal
=
{
props
.
isHorizontal
}
...
...
@@ -135,7 +147,7 @@ export default defineComponent({
showLogo
=
{
unref
(
getIsShowLogo
)
}
mode
=
{
unref
(
getComputedMenuMode
)
}
theme
=
{
unref
(
getComputedMenuTheme
)
}
items
=
{
unref
(
menusRef
)
}
items
=
{
menus
}
accordion
=
{
unref
(
getAccordion
)
}
onMenuClick
=
{
handleMenuClick
}
/>
...
...
src/layouts/default/menu/useLayoutMenu.ts
浏览文件 @
ff2b12b4
...
...
@@ -40,7 +40,12 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
async
([
path
]:
[
string
,
MenuSplitTyeEnum
])
=>
{
if
(
unref
(
splitNotLeft
)
||
unref
(
getIsMobile
))
return
;
const
parentPath
=
await
getCurrentParentPath
(
path
);
const
{
meta
}
=
unref
(
currentRoute
);
const
currentActiveMenu
=
meta
.
currentActiveMenu
;
let
parentPath
=
await
getCurrentParentPath
(
path
);
if
(
!
parentPath
)
{
parentPath
=
await
getCurrentParentPath
(
currentActiveMenu
);
}
parentPath
&&
throttleHandleSplitLeftMenu
(
parentPath
);
},
{
...
...
@@ -67,11 +72,15 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
// Handle left menu split
async
function
handleSplitLeftMenu
(
parentPath
:
string
)
{
console
.
log
(
'
======================
'
);
console
.
log
(
unref
(
getSplitLeft
));
console
.
log
(
'
======================
'
);
if
(
unref
(
getSplitLeft
)
||
unref
(
getIsMobile
))
return
;
// spilt mode left
const
children
=
await
getChildrenMenus
(
parentPath
);
if
(
!
children
)
{
if
(
!
children
||
!
children
.
length
)
{
setMenuSetting
({
hidden
:
true
});
menusRef
.
value
=
[];
return
;
...
...
src/layouts/default/sider/MixSider.vue
浏览文件 @
ff2b12b4
...
...
@@ -61,9 +61,7 @@
/>
</div>
<ScrollContainer
:class=
"`$
{prefixCls}-menu-list__content`">
<BasicMenu
:isHorizontal=
"false"
mode=
"inline"
<SimpleMenu
:items=
"chilrenMenus"
:theme=
"getMenuTheme"
mixSider
...
...
@@ -85,7 +83,7 @@
import
{
defineComponent
,
onMounted
,
ref
,
computed
,
unref
}
from
'
vue
'
;
import
{
BasicMenu
,
MenuTag
}
from
'
/@/components/Menu
'
;
import
{
MenuTag
}
from
'
/@/components/Menu
'
;
import
{
ScrollContainer
}
from
'
/@/components/Container
'
;
import
Icon
from
'
/@/components/Icon
'
;
import
{
AppLogo
}
from
'
/@/components/Application
'
;
...
...
@@ -103,13 +101,14 @@
import
clickOutside
from
'
/@/directives/clickOutside
'
;
import
{
getShallowMenus
,
getChildrenMenus
,
getCurrentParentPath
}
from
'
/@/router/menus
'
;
import
{
listenerLastChangeTab
}
from
'
/@/logics/mitt/tabChange
'
;
import
{
SimpleMenu
}
from
'
/@/components/SimpleMenu
'
;
export
default
defineComponent
({
name
:
'
LayoutMixSider
'
,
components
:
{
ScrollContainer
,
AppLogo
,
Basic
Menu
,
Simple
Menu
,
MenuTag
,
Icon
,
Trigger
,
...
...
@@ -335,6 +334,7 @@
<
style
lang=
"less"
>
@prefix-cls: ~'@{namespace}-layout-mix-sider';
@tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag';
@menu-prefix-cls: ~'@{namespace}-menu';
@width: 80px;
.@{prefix-cls} {
position: fixed;
...
...
@@ -351,6 +351,10 @@
right: 2px;
}
.@{menu-prefix-cls} {
width: 100% !important;
}
&-dom {
height: 100%;
overflow: hidden;
...
...
@@ -392,6 +396,10 @@
}
}
.@{prefix-cls}-menu-list {
&__content {
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1);
}
&__title {
.pushpin {
color: rgba(0, 0, 0, 0.35);
...
...
@@ -578,10 +586,10 @@
&-drag-bar {
position: absolute;
top:
0
;
right: -
3
px;
width:
3
px;
height:
100%
;
top:
50px
;
right: -
1
px;
width:
1
px;
height:
calc(100% - 50px)
;
cursor: ew-resize;
background: #f8f8f9;
border-top: none;
...
...
src/locales/lang/en/component/drawer.ts
0 → 100644
浏览文件 @
ff2b12b4
export
default
{
loadingText
:
'
Loading...
'
,
cancelText
:
'
Close
'
,
okText
:
'
Confirm
'
,
};
src/locales/lang/en/component/menu.ts
0 → 100644
浏览文件 @
ff2b12b4
export
default
{
search
:
'
Menu search
'
,
};
src/locales/lang/en/component/modal.ts
0 → 100644
浏览文件 @
ff2b12b4
export
default
{
cancelText
:
'
Close
'
,
okText
:
'
Confirm
'
,
};
src/locales/lang/zh_CN/component/drawer.ts
0 → 100644
浏览文件 @
ff2b12b4
export
default
{
loadingText
:
'
加载中...
'
,
cancelText
:
'
关闭
'
,
okText
:
'
确认
'
,
};
src/locales/lang/zh_CN/component/menu.ts
0 → 100644
浏览文件 @
ff2b12b4
export
default
{
search
:
'
菜单搜索
'
,
};
src/locales/lang/zh_CN/component/modal.ts
0 → 100644
浏览文件 @
ff2b12b4
export
default
{
cancelText
:
'
关闭
'
,
okText
:
'
确认
'
,
};
src/logics/theme/index.ts
浏览文件 @
ff2b12b4
...
...
@@ -71,7 +71,7 @@ export function updateSidebarBgColor(color: string) {
setCssVar
(
SIDER_DARK_BG_COLOR
,
color
);
setCssVar
(
SIDER_DARK_DARKEN_BG_COLOR
,
darken
(
color
,
6
));
setCssVar
(
SIDER_LIGHTEN_1_BG_COLOR
,
lighten
(
color
,
4
));
setCssVar
(
SIDER_LIGHTEN_1_BG_COLOR
,
lighten
(
color
,
5
));
setCssVar
(
SIDER_LIGHTEN_2_BG_COLOR
,
lighten
(
color
,
8
));
// only #ffffff is light
...
...
src/router/guard/index.ts
浏览文件 @
ff2b12b4
...
...
@@ -8,6 +8,7 @@ import { createMessageGuard } from './messageGuard';
import
{
createScrollGuard
}
from
'
./scrollGuard
'
;
import
{
createHttpGuard
}
from
'
./httpGuard
'
;
import
{
createPageGuard
}
from
'
./pageGuard
'
;
import
{
createStateGuard
}
from
'
./stateGuard
'
;
export
function
createGuard
(
router
:
Router
)
{
createPageGuard
(
router
);
...
...
@@ -18,4 +19,5 @@ export function createGuard(router: Router) {
createTitleGuard
(
router
);
createProgressGuard
(
router
);
createPermissionGuard
(
router
);
createStateGuard
(
router
);
}
src/router/guard/stateGuard.ts
浏览文件 @
ff2b12b4
...
...
@@ -3,7 +3,7 @@ import { appStore } from '/@/store/modules/app';
import
{
PageEnum
}
from
'
/@/enums/pageEnum
'
;
import
{
removeTabChangeListener
}
from
'
/@/logics/mitt/tabChange
'
;
export
function
create
Http
Guard
(
router
:
Router
)
{
export
function
create
State
Guard
(
router
:
Router
)
{
router
.
afterEach
((
to
)
=>
{
// Just enter the login page and clear the authentication information
if
(
to
.
path
===
PageEnum
.
BASE_LOGIN
)
{
...
...
src/router/menus/index.ts
浏览文件 @
ff2b12b4
...
...
@@ -54,7 +54,9 @@ export const getMenus = async (): Promise<Menu[]> => {
// 获取当前路径的顶级路径
export
async
function
getCurrentParentPath
(
currentPath
:
string
)
{
const
menus
=
await
getAsyncMenus
();
const
allParentPath
=
await
getAllParentPath
(
menus
,
currentPath
);
return
allParentPath
?.[
0
];
}
...
...
src/utils/mitt.ts
浏览文件 @
ff2b12b4
...
...
@@ -28,7 +28,7 @@ export default class Mitt {
* @param {Function} handler Function to call in response to given event
*/
on
(
type
:
string
|
Symbol
,
handler
:
Fn
)
{
const
handlers
=
this
.
cache
.
get
(
type
);
const
handlers
=
this
.
cache
?
.
get
(
type
);
const
added
=
handlers
&&
handlers
.
push
(
handler
);
if
(
!
added
)
{
this
.
cache
.
set
(
type
,
[
handler
]);
...
...
@@ -57,7 +57,7 @@ export default class Mitt {
* @param {string|symbol} type The event type to invoke
* @param {*} [evt] Any value (object is recommended and powerful), passed to each handler
*/
emit
(
type
:
string
|
Symbol
,
evt
:
any
)
{
emit
(
type
:
string
|
Symbol
,
evt
?
:
any
)
{
for
(
const
handler
of
(
this
.
cache
.
get
(
type
)
||
[]).
slice
())
handler
(
evt
);
for
(
const
handler
of
(
this
.
cache
.
get
(
'
*
'
)
||
[]).
slice
())
handler
(
type
,
evt
);
}
...
...
vite.config.ts
浏览文件 @
ff2b12b4
...
...
@@ -89,6 +89,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
optimizeDeps
:
{
include
:
[
'
@ant-design/icons-vue
'
,
'
echarts/map/js/china
'
,
'
ant-design-vue/es/locale/zh_CN
'
,
'
moment/dist/locale/zh-cn
'
,
'
ant-design-vue/es/locale/en_US
'
,
...
...
yarn.lock
浏览文件 @
ff2b12b4
...
...
@@ -1123,10 +1123,10 @@
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.2.1.tgz#29a5a86bcfaa41555c8483a287294e520cc28cd6"
integrity sha512-WmvsSfVKQx62vLbHXJvdh4PDjSK9YU6VW9ppXTlbjgDKCYtpy2sMWbK4i9OBdxY6RRwMMVctZhWo6Y5jfMRyTg==
"@eslint/eslintrc@^0.
2.2
":
version "0.
2.2
"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.
2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76
"
integrity sha512-
EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ
==
"@eslint/eslintrc@^0.
3.0
":
version "0.
3.0
"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.
3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318
"
integrity sha512-
1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg
==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
...
...
@@ -1135,7 +1135,7 @@
ignore "^4.0.6"
import-fresh "^3.2.1"
js-yaml "^3.13.1"
lodash "^4.17.
19
"
lodash "^4.17.
20
"
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
...
...
@@ -1184,10 +1184,10 @@
dependencies:
cross-fetch "^3.0.6"
"@iconify/json@^1.1.28
5
":
version "1.1.28
5
"
resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.28
5.tgz#2f1665c9f3ce4cd9eb2e0c980c0ac8955ce520fc
"
integrity sha512-
ABoWg/GibeN3hzTvvzd9oSmSo3V8Hyb3f0LMMUD195xlrd8083nBzFFhA12EfEMnxNsouj6ZtvlgIDnYWEXRow
==
"@iconify/json@^1.1.28
7
":
version "1.1.28
7
"
resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.28
7.tgz#31fe253ce97fb2bf673a60c2467810a3f48a00c3
"
integrity sha512-
wvmQDpHqzbYZv2mDsdp1eXUN+ff53FjElT19uVxFRPOkY2kaIhs7dMPS/ZeDD38TE2eH1arTzZ2KhtB+Mxe8VQ
==
"@intlify/core-base@9.0.0-beta.16":
version "9.0.0-beta.16"
...
...
@@ -1494,10 +1494,10 @@
resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69"
integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA==
"@types/http-proxy@^1.17.
4
":
version "1.17.
4
"
resolved "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.
4.tgz#e7c92e3dbe3e13aa799440ff42e6d3a17a9d045b
"
integrity sha512-
IrSHl2u6AWXduUaDLqYpt45tLVCtYv7o4Z0s1KghBCDgIIS9oW5K1H8mZG/A2CfeLdEa7rTd1ACOiHBc1EMT2
Q==
"@types/http-proxy@^1.17.
5
":
version "1.17.
5
"
resolved "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.
5.tgz#c203c5e6e9dc6820d27a40eb1e511c70a220423d
"
integrity sha512-
GNkDE7bTv6Sf8JbV2GksknKOsk7OznNYHSdrtvPJXO0qJ9odZig6IZKUi5RFGi6d1bf6dgIAe4uXi3DBc7069
Q==
dependencies:
"@types/node" "*"
...
...
@@ -1751,10 +1751,10 @@
"@typescript-eslint/types" "4.13.0"
eslint-visitor-keys "^2.0.0"
"@vitejs/plugin-legacy@^1.2.
0
":
version "1.2.
0
"
resolved "https://registry.npmjs.org/@vitejs/plugin-legacy/-/plugin-legacy-1.2.
0.tgz#e6a2f7802f1a81c712f72656300fcdf7541eeab0
"
integrity sha512-
eoJi1M7Or16bkRjXFtdG39c8ElvbgxUxlXFo8GO2VmgOGO42r6Ku5MJD4ZkweIM7XGunyFvmEwTYgpUVC4PiPg
==
"@vitejs/plugin-legacy@^1.2.
1
":
version "1.2.
1
"
resolved "https://registry.npmjs.org/@vitejs/plugin-legacy/-/plugin-legacy-1.2.
1.tgz#783a72c56ce987f00caf334acc33195a0bbf6f24
"
integrity sha512-
bVOYH7WxffDSvfFfCGk/UYCzKw59n18fHGOV3VXRSQmeaBmbxuq0CRdAS3EtPvp74DjgA4GiZ+BsrQ0LyF0/yA
==
dependencies:
"@babel/standalone" "^7.12.12"
core-js "^3.8.2"
...
...
@@ -1772,10 +1772,10 @@
"@vue/babel-plugin-jsx" "^1.0.1"
hash-sum "^2.0.0"
"@vitejs/plugin-vue@^1.0.
5
":
version "1.0.
5
"
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.0.
5.tgz#2639178e975bebc505e9be1c88d25faf9bc4dd06
"
integrity sha512-
Fq/Z1rTs7j3QhvmIjeIHqInw2YneXa8Td3z7cYQhyAZXF/WmGMegbapeBqGAoAcGSOfWpOO7Tr0c/T+Qke0O6Q
==
"@vitejs/plugin-vue@^1.0.
6
":
version "1.0.
6
"
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.0.
6.tgz#698afa5a77a6dcd22cf7757801f46a6f01cdbb53
"
integrity sha512-
cWJewtxnVVpjlhq6DoZ7VP7sF1jTZYVg66ehslZ0tJANWk1uRiCXdqD8yQ4npZ4XewDICQzK+c+9i3Xsubx59w
==
"@vue/babel-helper-vue-transform-on@^1.0.0":
version "1.0.0"
...
...
@@ -2023,18 +2023,18 @@
vscode-languageserver-textdocument "^1.0.1"
vscode-uri "^2.1.2"
"@vueuse/core@^4.0.
5
":
version "4.0.
5
"
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.
5.tgz#97bd5f24a28401598436629312eafe66ed0e1bed
"
integrity sha512-
Kfy5ys9o1XIY6NwX9O7iad4/FbHrcDuP/LtsgIFvl7XDQtbYArHu5ZSOQyBwqE32TdAqnFi5sYd4vjSvVvpD4A
==
"@vueuse/core@^4.0.
8
":
version "4.0.
8
"
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.
8.tgz#d5690154c147ae787bf5d67bf8fe3046dff96d85
"
integrity sha512-
wD0JJUXpRgRBPCnGsAqcVk9Zz545zOmIjGv/1Mlco3rVmal7LEZ3rJh8SnBelxuyVNvRwifkK1gtbT24jY6V8Q
==
dependencies:
"@vueuse/shared" "4.0.
5
"
"@vueuse/shared" "4.0.
8
"
vue-demi latest
"@vueuse/shared@4.0.
5
":
version "4.0.
5
"
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.
5.tgz#0610210da9a01843cdb3fa88c177b29b62738efc
"
integrity sha512-
PUSlwoSaerwHA1PPjBGnerXPIvAcVGoxcpjNdbHW44lPqoWskWl2CxG+l2Iz+Zf2iapCatp3ovXnMd16RRvQ1Q
==
"@vueuse/shared@4.0.
8
":
version "4.0.
8
"
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.
8.tgz#ba6c350b5f0ef12e2a603d956cc6d2809ff5be4f
"
integrity sha512-
euAfdZeFHGAyCBoy7izgufC/kTt+yEjuVjeCmfuDQNAj7QsdzEpRlyblD+EGifHbyGFx8F3Ql6/bQzdTdwRFHA
==
dependencies:
vue-demi latest
...
...
@@ -2800,7 +2800,7 @@ commander@~2.17.1:
resolved "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
commitizen@^4.0.3
, commitizen@^4.2.2
:
commitizen@^4.0.3:
version "4.2.2"
resolved "https://registry.npmjs.org/commitizen/-/commitizen-4.2.2.tgz#1a93dd07208521ea1ebbf832593542dac714cc79"
integrity sha512-uz+E6lGsDBDI2mYA4QfOxFeqdWUYwR1ky11YmLgg2BnEEP3YbeejpT4lxzGjkYqumnXr062qTOGavR9NtX/iwQ==
...
...
@@ -2820,6 +2820,26 @@ commitizen@^4.0.3, commitizen@^4.2.2:
strip-bom "4.0.0"
strip-json-comments "3.0.1"
commitizen@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/commitizen/-/commitizen-4.2.3.tgz#088d0ef72500240d331b11e02e288223667c1475"
integrity sha512-pYlYEng7XMV2TW4xtjDKBGqeJ0Teq2zyRSx2S3Ml1XAplHSlJZK8vm1KdGclpMEZuGafbS5TeHXIVnHk8RWIzQ==
dependencies:
cachedir "2.2.0"
cz-conventional-changelog "3.2.0"
dedent "0.7.0"
detect-indent "6.0.0"
find-node-modules "2.0.0"
find-root "1.1.0"
fs-extra "8.1.0"
glob "7.1.4"
inquirer "6.5.2"
is-utf8 "^0.2.1"
lodash "^4.17.20"
minimist "1.2.5"
strip-bom "4.0.0"
strip-json-comments "3.0.1"
common-tags@^1.8.0:
version "1.8.0"
resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
...
...
@@ -3159,6 +3179,20 @@ currently-unhandled@^0.4.1:
dependencies:
array-find-index "^1.0.1"
cz-conventional-changelog@3.2.0:
version "3.2.0"
resolved "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz#6aef1f892d64113343d7e455529089ac9f20e477"
integrity sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==
dependencies:
chalk "^2.4.1"
commitizen "^4.0.3"
conventional-commit-types "^3.0.0"
lodash.map "^4.5.1"
longest "^2.0.1"
word-wrap "^1.0.3"
optionalDependencies:
"@commitlint/load" ">6.1.1"
cz-conventional-changelog@3.3.0:
version "3.3.0"
resolved "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz#9246947c90404149b3fe2cf7ee91acad3b7d22d2"
...
...
@@ -3571,13 +3605,13 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
eslint@^7.1
7
.0:
version "7.1
7
.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.1
7.0.tgz#4ccda5bf12572ad3bf760e6f195886f50569adb0
"
integrity sha512-
zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFw
Q==
eslint@^7.1
8
.0:
version "7.1
8
.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.1
8.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67
"
integrity sha512-
fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjA
Q==
dependencies:
"@babel/code-frame" "^7.0.0"
"@eslint/eslintrc" "^0.
2.2
"
"@eslint/eslintrc" "^0.
3.0
"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
...
...
@@ -3601,7 +3635,7 @@ eslint@^7.17.0:
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
lodash "^4.17.
19
"
lodash "^4.17.
20
"
minimatch "^3.0.4"
natural-compare "^1.4.0"
optionator "^0.9.1"
...
...
@@ -4423,10 +4457,10 @@ human-signals@^1.1.1:
resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
husky@^4.3.
7
:
version "4.3.
7
"
resolved "https://registry.npmjs.org/husky/-/husky-4.3.
7.tgz#ca47bbe6213c1aa8b16bbd504530d9600de91e88
"
integrity sha512-
0fQlcCDq/xypoyYSJvEuzbDPHFf8ZF9IXKJxlrnvxABTSzK1VPT2RKYQKrcgJ+YD39swgoB6sbzywUqFxUiqj
w==
husky@^4.3.
8
:
version "4.3.
8
"
resolved "https://registry.npmjs.org/husky/-/husky-4.3.
8.tgz#31144060be963fd6850e5cc8f019a1dfe194296d
"
integrity sha512-
LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Ano
w==
dependencies:
chalk "^4.0.0"
ci-info "^2.0.0"
...
...
@@ -7840,20 +7874,20 @@ vite-plugin-purge-icons@^0.5.1:
"@purge-icons/generated" "^0.5.1"
rollup-plugin-purge-icons "^0.5.1"
vite-plugin-pwa@^0.3.
6
:
version "0.3.
6
"
resolved "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.3.
6.tgz#a522af3fd5461991907f6829975b437f2c84733
9"
integrity sha512-
GDgT8jFGHUz2j11I7Z0W+X5mnkaUoMVitJ/UjN/ezjy9HcXrvxaIVnhzMdESJSv+dxy4DD9ymD91cF9Ei6//cQ
==
vite-plugin-pwa@^0.3.
8
:
version "0.3.
8
"
resolved "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.3.
8.tgz#c98a683ddbbe87bd55db79acb6a5c849f2a2987
9"
integrity sha512-
W5FBJeS3KjaCG1qu7LMTX9+E0u6qNHFk+hk917s4MnAlQ/XnBs30kgRXVBXtVAPhgvn8rqj2ww+2OYed+MKtIg
==
dependencies:
debug "^4.3.2"
fast-glob "^3.2.4"
pretty-bytes "^5.5.0"
workbox-build "^6.0.2"
vite@^2.0.0-beta.
27
:
version "2.0.0-beta.
27
"
resolved "https://registry.npmjs.org/vite/-/vite-2.0.0-beta.
27.tgz#a2e4b3a698e67c89fd963ff51ee5283ec564c65c
"
integrity sha512-
1fGPjSVE4MmCGVguFy7pPurCLnvHu4fJSzVjejd9GoFqCNie+JKCpe3KGsxIb9B8ot/aDd4ISCB0+fH1/01FUA
==
vite@^2.0.0-beta.
30
:
version "2.0.0-beta.
30
"
resolved "https://registry.npmjs.org/vite/-/vite-2.0.0-beta.
30.tgz#d0c1056d1fb05c489614360f92363eebec41a6b4
"
integrity sha512-
wOeO64J3k4jGjCOkH/6RUcIyT/HOTaDZSiXE75aWYqV9hI7Q6uEeSXbAFtb9bG82RGLEWdsqtCvx5t7gaeqtsw
==
dependencies:
esbuild "^0.8.26"
postcss "^8.2.1"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录