This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
.dark {
|
.dark {
|
||||||
.main(@nav-background: @layout-header-background;
|
.main(@nav-background: @layout-header-background;
|
||||||
@nav-box-shadow-color: fade(@black, 25%);
|
@nav-box-shadow-color: fade(@black, 25%);
|
||||||
|
@nav-scrollbar-background: fade(@white, 50%);
|
||||||
@logo-color: @white;
|
@logo-color: @white;
|
||||||
@logo-box-shadow: none;
|
@logo-box-shadow: none;
|
||||||
@header-action-color: fade(@white, 60%);
|
@header-action-color: fade(@white, 60%);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
.light {
|
.light {
|
||||||
.main(@nav-background: @white;
|
.main(@nav-background: @white;
|
||||||
@nav-box-shadow-color: fade(@black, 5%);
|
@nav-box-shadow-color: fade(@black, 5%);
|
||||||
|
@nav-scrollbar-background: fade(@black, 30%);
|
||||||
@logo-color: @black;
|
@logo-color: @black;
|
||||||
@logo-box-shadow: inset -1px -1px 1px @border-color-split;
|
@logo-box-shadow: inset -1px -1px 1px @border-color-split;
|
||||||
@header-action-color: fade(@black, 35%);
|
@header-action-color: fade(@black, 35%);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
.main(@nav-background: @layout-header-background,
|
.main(@nav-background: @layout-header-background,
|
||||||
@nav-box-shadow-color: fade(@black, 25%),
|
@nav-box-shadow-color: fade(@black, 25%),
|
||||||
|
@nav-scrollbar-background: fade(@white, 30%),
|
||||||
@logo-color: @white,
|
@logo-color: @white,
|
||||||
@logo-box-shadow: none,
|
@logo-box-shadow: none,
|
||||||
@header-action-color: fade(@white, 60%),
|
@header-action-color: fade(@white, 60%),
|
||||||
@@ -35,12 +36,14 @@
|
|||||||
box-shadow: inset 1px 1px 10px rgba(0, 0, 0, .05);
|
box-shadow: inset 1px 1px 10px rgba(0, 0, 0, .05);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>.ant-input-search {
|
>.ant-input-search,
|
||||||
|
>.ant-select-auto-complete {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
margin: 5px @padding-md;
|
margin: 5px @padding-md;
|
||||||
.ant-input {
|
.ant-input {
|
||||||
|
width: 180px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
padding: 5px 30px 5px 11px;
|
padding: 5px 30px 5px 11px;
|
||||||
|
|
||||||
@@ -52,6 +55,9 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ant-select-selection {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +200,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>.ant-input-search {
|
>.ant-input-search,
|
||||||
|
>.ant-select-auto-complete {
|
||||||
.ant-input {
|
.ant-input {
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: fade(@black, 5%);
|
background-color: fade(@black, 5%);
|
||||||
@@ -256,9 +263,27 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
box-shadow: 2px 0 8px @nav-box-shadow-color;
|
box-shadow: 2px 0 8px @nav-box-shadow-color;
|
||||||
|
.swiper-scrollbar {
|
||||||
|
transition: @animation-duration-slow;
|
||||||
|
transition-property: opacity;
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.swiper-scrollbar-drag {
|
||||||
|
background-color: @nav-scrollbar-background;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.swiper-scrollbar {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.swiper-slide {
|
.swiper-slide {
|
||||||
height: auto;
|
height: auto;
|
||||||
|
min-height: 100%;
|
||||||
|
>.ant-spin-nested-loading {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,7 +323,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>.ant-input-search {
|
>.ant-input-search,
|
||||||
|
>.ant-select-auto-complete {
|
||||||
.ant-input {
|
.ant-input {
|
||||||
color: @header-search-color;
|
color: @header-search-color;
|
||||||
background-color: @header-search-background;
|
background-color: @header-search-background;
|
||||||
@@ -306,7 +332,7 @@
|
|||||||
background-color: @header-search-focus-background;
|
background-color: @header-search-focus-background;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ant-input-search-icon {
|
.anticon-search {
|
||||||
color: @header-search-icon-color;
|
color: @header-search-icon-color;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: @header-search-icon-hover-color;
|
color: @header-search-icon-hover-color;
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ export default {
|
|||||||
data.forEach((p, i) => {
|
data.forEach((p, i) => {
|
||||||
n[n.length - 1] = i
|
n[n.length - 1] = i
|
||||||
p.key = n.join('-')
|
p.key = n.join('-')
|
||||||
|
p.scopedSlots = { title: 'title' }
|
||||||
if (p.children) {
|
if (p.children) {
|
||||||
this.generateKey(p.children, Object.assign([], n))
|
this.generateKey(p.children, Object.assign([], n))
|
||||||
}
|
}
|
||||||
@@ -125,14 +126,20 @@ export default {
|
|||||||
mousewheel: true,
|
mousewheel: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
const slots = {
|
const scopedSlots = {
|
||||||
title: ({ title }) => {
|
title: ({ title }) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<span v-if={title.indexOf(this.searchValue) > -1}>
|
{
|
||||||
{title.replace(this.searchValue, <span style="color: #f50">{this.searchValue}</span>)}
|
title.indexOf(this.searchValue) > -1 ?
|
||||||
|
<span>
|
||||||
|
{title.substr(0, title.indexOf(this.searchValue))}
|
||||||
|
<span style="color: #f50">{this.searchValue}</span>
|
||||||
|
{title.substr(title.indexOf(this.searchValue) + this.searchValue.length)}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>{{ title }}</span>
|
:
|
||||||
|
<span>{title}</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
@@ -150,20 +157,14 @@ export default {
|
|||||||
<swiper options={swiperOptions}>
|
<swiper options={swiperOptions}>
|
||||||
<a-spin style={{ height: '100%' }} spinning={this.loading}>
|
<a-spin style={{ height: '100%' }} spinning={this.loading}>
|
||||||
<a-icon slot="indicator" type="loading" spin />
|
<a-icon slot="indicator" type="loading" spin />
|
||||||
|
|
||||||
<swiper-slide>
|
<swiper-slide>
|
||||||
<a-alert closable banner type="error">
|
|
||||||
<template slot="message">
|
|
||||||
<div>搜索无法高亮</div>
|
|
||||||
</template>
|
|
||||||
</a-alert>
|
|
||||||
<a-tree
|
<a-tree
|
||||||
{...{ slots }}
|
|
||||||
treeData={this.data}
|
treeData={this.data}
|
||||||
expandedKeys={this.expandedKeys}
|
expandedKeys={this.expandedKeys}
|
||||||
autoExpandParent={this.autoExpandParent}
|
autoExpandParent={this.autoExpandParent}
|
||||||
onExpand={this.onExpand}
|
onExpand={this.onExpand}
|
||||||
onSelect={this.onSelect}
|
onSelect={this.onSelect}
|
||||||
|
{...{ scopedSlots }}
|
||||||
/>
|
/>
|
||||||
</swiper-slide>
|
</swiper-slide>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<template v-if="mode == 'add'">
|
<template v-if="mode == 'add'">
|
||||||
<a-form-model-item label="密码" prop="password">
|
<a-form-model-item label="密码" prop="password">
|
||||||
<a-input placeholder="请输入密码" type="password" v-model="form.password" />
|
<a-input-password placeholder="请输入密码" v-model="form.password" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item label="确认密码" prop="confirm">
|
<a-form-model-item label="确认密码" prop="confirm">
|
||||||
<a-input placeholder="请确认密码" type="password" v-model="form.confirm" />
|
<a-input-password placeholder="请确认密码" v-model="form.confirm" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</template>
|
</template>
|
||||||
<a-form-model-item label="昵称">
|
<a-form-model-item label="昵称">
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '性别',
|
title: '性别',
|
||||||
|
width: '100px',
|
||||||
dataIndex: 'sex',
|
dataIndex: 'sex',
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
customRender: 'sex',
|
customRender: 'sex',
|
||||||
@@ -149,6 +150,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
|
width: '200px',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
customRender: 'status',
|
customRender: 'status',
|
||||||
|
|||||||
@@ -10,7 +10,29 @@
|
|||||||
>
|
>
|
||||||
<a-icon :type="$root.global.settings.siderCollapsed ? 'menu-unfold' : 'menu-fold'" />
|
<a-icon :type="$root.global.settings.siderCollapsed ? 'menu-unfold' : 'menu-fold'" />
|
||||||
</a>
|
</a>
|
||||||
<a-input-search placeholder="请输入检索关键字" />
|
<!-- <a-input-search placeholder="请输入检索关键字" /> -->
|
||||||
|
<a-auto-complete
|
||||||
|
:dropdown-match-select-width="false"
|
||||||
|
@search="onSearch"
|
||||||
|
@select="onSearchSelect"
|
||||||
|
option-label-prop="value"
|
||||||
|
placeholder="请输入检索关键字"
|
||||||
|
v-model="searchText"
|
||||||
|
>
|
||||||
|
<template slot="dataSource">
|
||||||
|
<a-select-opt-group :key="menu.id" v-for="menu in searchResult">
|
||||||
|
<span slot="label">{{ menu.meta.title }}</span>
|
||||||
|
<a-select-option
|
||||||
|
:key="opt.id"
|
||||||
|
:value="opt.id"
|
||||||
|
v-for="opt in menu.children"
|
||||||
|
>{{ opt.meta.title }}</a-select-option>
|
||||||
|
</a-select-opt-group>
|
||||||
|
</template>
|
||||||
|
<a-input>
|
||||||
|
<a-icon class="certain-category-icon" slot="suffix" type="search" />
|
||||||
|
</a-input>
|
||||||
|
</a-auto-complete>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<a @click="$emit('reload')" class="header-action">
|
<a @click="$emit('reload')" class="header-action">
|
||||||
@@ -32,7 +54,29 @@
|
|||||||
<Sider :nav="nav" @open="(nav) => $emit('open', nav)" />
|
<Sider :nav="nav" @open="(nav) => $emit('open', nav)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<a-input-search placeholder="请输入检索关键字" />
|
<!-- <a-input-search placeholder="请输入检索关键字" /> -->
|
||||||
|
<a-auto-complete
|
||||||
|
:dropdown-match-select-width="false"
|
||||||
|
@search="onSearch"
|
||||||
|
@select="onSearchSelect"
|
||||||
|
option-label-prop="value"
|
||||||
|
placeholder="请输入检索关键字"
|
||||||
|
v-model="searchText"
|
||||||
|
>
|
||||||
|
<template slot="dataSource">
|
||||||
|
<a-select-opt-group :key="menu.id" v-for="menu in searchResult">
|
||||||
|
<span slot="label">{{ menu.meta.title }}</span>
|
||||||
|
<a-select-option
|
||||||
|
:key="opt.id"
|
||||||
|
:value="opt.component"
|
||||||
|
v-for="opt in menu.children"
|
||||||
|
>{{ opt.meta.title }}</a-select-option>
|
||||||
|
</a-select-opt-group>
|
||||||
|
</template>
|
||||||
|
<a-input>
|
||||||
|
<a-icon class="certain-category-icon" slot="suffix" type="search" />
|
||||||
|
</a-input>
|
||||||
|
</a-auto-complete>
|
||||||
<a @click="$emit('reload')" class="header-action">
|
<a @click="$emit('reload')" class="header-action">
|
||||||
<a-icon type="reload" />
|
<a-icon type="reload" />
|
||||||
</a>
|
</a>
|
||||||
@@ -68,5 +112,48 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchText: '',
|
||||||
|
searchResult: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
window._ = this.$_;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSearch(value) {
|
||||||
|
const menus = this.$_.cloneDeep(this.nav.menus);
|
||||||
|
|
||||||
|
const search = (m) => {
|
||||||
|
if (!value) return [];
|
||||||
|
return m.filter((p) => {
|
||||||
|
if (p.children) {
|
||||||
|
p.children = search(p.children);
|
||||||
|
} else {
|
||||||
|
return p.meta.title.indexOf(value) > -1;
|
||||||
|
}
|
||||||
|
return p.children.length;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.searchResult = search(menus);
|
||||||
|
},
|
||||||
|
|
||||||
|
onSearchSelect(value, node) {
|
||||||
|
this.searchText = '';
|
||||||
|
this.onSearch(this.searchText);
|
||||||
|
|
||||||
|
const id = node.componentOptions.propsData.value;
|
||||||
|
//const menu = this.nav.menus.
|
||||||
|
|
||||||
|
// this.openContentWindow({
|
||||||
|
// key: menu.id,
|
||||||
|
// title: menu.meta.title,
|
||||||
|
// icon: menu.meta.icon,
|
||||||
|
// path: menu.component,
|
||||||
|
// });
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -6,16 +6,19 @@
|
|||||||
width="200"
|
width="200"
|
||||||
>
|
>
|
||||||
<Logo />
|
<Logo />
|
||||||
<swiper :options="siderSwiperOptions" :style="{ height: '100%' }" ref="sider-swiper">
|
<swiper :options="siderSwiperOptions" ref="sider-swiper">
|
||||||
<swiper-slide :style="{ height: 'auto' }">
|
<swiper-slide>
|
||||||
|
<a-spin :spinning="nav.loading">
|
||||||
|
<a-icon slot="indicator" spin type="loading" />
|
||||||
<Menu
|
<Menu
|
||||||
:menu-style="{ height: '100%', borderRight: 0 }"
|
:menu-style="{ height: '100%', borderRight: 0 }"
|
||||||
:nav="nav"
|
:nav="nav"
|
||||||
@openChange="onMenuOpenChange"
|
@openChange="onMenuOpenChange"
|
||||||
mode="inline"
|
mode="inline"
|
||||||
/>
|
/>
|
||||||
|
</a-spin>
|
||||||
</swiper-slide>
|
</swiper-slide>
|
||||||
<div class="swiper-scrollbar"></div>
|
<div class="swiper-scrollbar" id="layout--swiper-scrollbar" slot="scrollbar"></div>
|
||||||
</swiper>
|
</swiper>
|
||||||
</a-layout-sider>
|
</a-layout-sider>
|
||||||
<template v-else-if="$root.global.settings.layout === 'top-nav'">
|
<template v-else-if="$root.global.settings.layout === 'top-nav'">
|
||||||
@@ -43,6 +46,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
modules: [],
|
modules: [],
|
||||||
menus: [],
|
menus: [],
|
||||||
|
loading: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -55,7 +59,7 @@ export default {
|
|||||||
slidesPerView: 'auto',
|
slidesPerView: 'auto',
|
||||||
freeMode: true,
|
freeMode: true,
|
||||||
scrollbar: {
|
scrollbar: {
|
||||||
el: '.swiper-scrollbar',
|
el: '#layout--swiper-scrollbar',
|
||||||
},
|
},
|
||||||
mousewheel: true,
|
mousewheel: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
nav: {
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
modules: [],
|
||||||
|
menus: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
menuStyle: {
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
type: Object || String,
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
default: 'inline',
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
renderMenu(menu) {
|
||||||
|
return menu.map((p) => {
|
||||||
|
return p.children ? this.renderSubMenu(p) : this.renderMenuItem(p)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
renderSubMenu(menu) {
|
||||||
|
return (
|
||||||
|
<a-sub-menu key={menu.id}>
|
||||||
|
<span slot="title">
|
||||||
|
{menu.meta.icon ? <a-icon type={menu.meta.icon} /> : null}
|
||||||
|
<span>{menu.meta.title}</span>
|
||||||
|
</span>
|
||||||
|
{this.renderMenu(menu.children)}
|
||||||
|
</a-sub-menu>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
renderMenuItem(menu) {
|
||||||
|
return (
|
||||||
|
<a-menu-item key={menu.id} onClick={() => this.onOpenContentWindow(menu)}>
|
||||||
|
{menu.meta.icon ? <a-icon type={menu.meta.icon} /> : null}
|
||||||
|
<span>{menu.meta.title}</span>
|
||||||
|
</a-menu-item>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
onMenuOpenChange() {
|
||||||
|
this.$emit('openChange')
|
||||||
|
},
|
||||||
|
|
||||||
|
onOpenContentWindow(menu) {
|
||||||
|
this.openContentWindow({
|
||||||
|
key: menu.id,
|
||||||
|
title: menu.meta.title,
|
||||||
|
icon: menu.meta.icon,
|
||||||
|
path: menu.component,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const props = {
|
||||||
|
mode: this.mode,
|
||||||
|
selectable: false,
|
||||||
|
style: this.menuStyle,
|
||||||
|
theme: this.$root.global.settings.navTheme,
|
||||||
|
}
|
||||||
|
|
||||||
|
const on = {
|
||||||
|
openChange: this.onMenuOpenChange,
|
||||||
|
}
|
||||||
|
|
||||||
|
return <a-menu {...{ props, on }}>{this.renderMenu(this.nav.menus)}</a-menu>
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-menu
|
|
||||||
:mode="mode"
|
|
||||||
:selectable="false"
|
|
||||||
:style="menuStyle"
|
|
||||||
:theme="$root.global.settings.navTheme"
|
|
||||||
@openChange="onMenuOpenChange"
|
|
||||||
>
|
|
||||||
<template v-for="c1 in menu">
|
|
||||||
<a-sub-menu :key="c1.id" v-if="c1.children && c1.children.length">
|
|
||||||
<span slot="title">
|
|
||||||
<a-icon :type="c1.meta.icon" v-if="c1.meta.icon" />
|
|
||||||
<span>{{ c1.meta.title }}</span>
|
|
||||||
</span>
|
|
||||||
<template v-for="c2 in c1.children">
|
|
||||||
<a-menu-item :key="c2.id" @click="onOpenContentWindow(c2)">
|
|
||||||
<a-icon :type="c2.meta.icon" v-if="c2.meta.icon" />
|
|
||||||
<span>{{ c2.meta.title }}</span>
|
|
||||||
</a-menu-item>
|
|
||||||
</template>
|
|
||||||
</a-sub-menu>
|
|
||||||
<a-menu-item :key="c1.id" @click="onOpenContentWindow(c1)" v-else>
|
|
||||||
<a-icon :type="c1.meta.icon" v-if="c1.meta.icon" />
|
|
||||||
<span>{{ c1.meta.title }}</span>
|
|
||||||
</a-menu-item>
|
|
||||||
</template>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
nav: {
|
|
||||||
default() {
|
|
||||||
return {
|
|
||||||
modules: [],
|
|
||||||
menus: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
type: Object,
|
|
||||||
},
|
|
||||||
menuStyle: {
|
|
||||||
default() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
type: Object || String,
|
|
||||||
},
|
|
||||||
mode: {
|
|
||||||
default: 'inline',
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
menu: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.serializeMenu();
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
nav: {
|
|
||||||
deep: true,
|
|
||||||
handler() {
|
|
||||||
this.serializeMenu();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
serializeMenu() {
|
|
||||||
const menu = this.$_.cloneDeep(this.nav.menus);
|
|
||||||
const children = this.$_.groupBy(menu, 'pid');
|
|
||||||
this.menu = menu
|
|
||||||
.filter((p) => !p.pid)
|
|
||||||
.map((p) => {
|
|
||||||
return {
|
|
||||||
...p,
|
|
||||||
children: children[p.id],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onMenuOpenChange() {
|
|
||||||
this.$emit('openChange');
|
|
||||||
},
|
|
||||||
|
|
||||||
onOpenContentWindow(menu) {
|
|
||||||
this.openContentWindow({
|
|
||||||
key: menu.id,
|
|
||||||
title: menu.meta.title,
|
|
||||||
icon: menu.meta.icon,
|
|
||||||
path: menu.component,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -79,8 +79,10 @@ export default {
|
|||||||
visible: false,
|
visible: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
menus: [],
|
||||||
|
|
||||||
nav: {
|
nav: {
|
||||||
loaded: false,
|
loading: false,
|
||||||
modules: [],
|
modules: [],
|
||||||
menus: [],
|
menus: [],
|
||||||
},
|
},
|
||||||
@@ -88,6 +90,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
|
this.nav.loading = true;
|
||||||
|
|
||||||
this.$api.getLoginUser().then(({ data }) => {
|
this.$api.getLoginUser().then(({ data }) => {
|
||||||
const info = { ...data };
|
const info = { ...data };
|
||||||
delete info.apps;
|
delete info.apps;
|
||||||
@@ -95,8 +99,9 @@ export default {
|
|||||||
setGlobal(info);
|
setGlobal(info);
|
||||||
|
|
||||||
this.nav.modules = data.apps;
|
this.nav.modules = data.apps;
|
||||||
this.nav.menus = data.menus;
|
this.menus = data.menus;
|
||||||
this.nav.loaded = true;
|
this.serializeMenu();
|
||||||
|
this.nav.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -226,6 +231,22 @@ export default {
|
|||||||
if (!key) key = this.tabActived;
|
if (!key) key = this.tabActived;
|
||||||
this.$refs.content.onLoadContentWindow(key);
|
this.$refs.content.onLoadContentWindow(key);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
serializeMenu() {
|
||||||
|
const menu = this.$_.cloneDeep(this.menus);
|
||||||
|
const children = this.$_.groupBy(menu, 'pid');
|
||||||
|
|
||||||
|
const serialize = (m) => {
|
||||||
|
m.map((p) => {
|
||||||
|
if (children[p.id]) {
|
||||||
|
p.children = serialize(children[p.id]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.nav.menus = serialize(children[0]);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
Reference in New Issue
Block a user