This commit is contained in:
ky_sunl
2021-04-19 01:54:28 +00:00
parent d8c36320a5
commit ccb20d51ae
8 changed files with 208 additions and 113 deletions

View File

@@ -43,7 +43,6 @@
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;
@@ -362,6 +361,8 @@
} }
.ant-menu-horizontal { .ant-menu-horizontal {
line-height: @layout-header-height; line-height: @layout-header-height;
border-bottom: 0;
>.ant-menu-submenu { >.ant-menu-submenu {
top: 0; top: 0;

View File

@@ -5,7 +5,7 @@ export default {
type: Number, type: Number,
}, },
pageSize: { pageSize: {
default: 20, default: 10,
type: Number, type: Number,
}, },
loadData: { loadData: {

View File

@@ -1,3 +1,5 @@
import { template } from "lodash"
export default { export default {
props: { props: {
loadData: { loadData: {
@@ -126,6 +128,17 @@ export default {
mousewheel: true, mousewheel: true,
} }
const props = {
treeData: this.data,
expandedKeys: this.expandedKeys,
autoExpandParent: this.autoExpandParent,
}
const on = {
expand: this.onExpand,
select: this.onSelect
}
const scopedSlots = { const scopedSlots = {
title: ({ title }) => { title: ({ title }) => {
return ( return (
@@ -155,17 +168,13 @@ export default {
</div> </div>
</a-layout-header> </a-layout-header>
<swiper options={swiperOptions}> <swiper options={swiperOptions}>
<a-alert banner type="error">
<template slot="message">顶部菜单-深色模式下搜索背景随头部变为深色</template>
</a-alert>
<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-tree <a-tree {...{ props, on, scopedSlots }} />
treeData={this.data}
expandedKeys={this.expandedKeys}
autoExpandParent={this.autoExpandParent}
onExpand={this.onExpand}
onSelect={this.onSelect}
{...{ scopedSlots }}
/>
</swiper-slide> </swiper-slide>
</a-spin> </a-spin>
</swiper> </swiper>

View File

@@ -0,0 +1,8 @@
<template>
<container>
<br />
<a-alert banner closable type="error">
<template slot="message">当前页面无法满足多层字典,设置后端接口目前也无法支持</template>
</a-alert>
</container>
</template>

View File

@@ -0,0 +1,3 @@
<template>
<div></div>
</template>

View File

@@ -14,14 +14,7 @@
<a-form-model-item> <a-form-model-item>
<a-button-group> <a-button-group>
<a-button @click="onQuery" type="primary">查询</a-button> <a-button @click="onQuery" type="primary">查询</a-button>
<a-button <a-button @click="() => {(query = {}), onQuery();}">重置</a-button>
@click="
() => {
(query = {}), onQuery();
}
"
>重置</a-button
>
</a-button-group> </a-button-group>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
@@ -40,32 +33,26 @@
<Auth auth="sysApp:edit"> <Auth auth="sysApp:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="[sysApp:grantMenu],[sysApp:grantData],[sysRole:delete]"> <Auth auth="sysApp:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a>
</a-popconfirm>
</Auth>
<Auth :auth="{ sysApp: [['grantMenu'], ['grantData']] }">
<a-dropdown> <a-dropdown>
<a class="ant-dropdown-link"> 更多 <a-icon type="down" /> </a> <a class="ant-dropdown-link">
授权
<a-icon type="down" />
</a>
<a-menu slot="overlay"> <a-menu slot="overlay">
<Auth auth="sysApp:grantMenu"> <Auth auth="sysApp:grantMenu">
<a-menu-item> <a-menu-item>
<a style="color:#005cb1;" @click="$refs.roleMenuForm.roleMenu(record)" <a @click="$refs.roleMenuForm.roleMenu(record)">授权菜单</a>
>授权菜单</a
>
</a-menu-item> </a-menu-item>
</Auth> </Auth>
<Auth auth="sysApp:grantData"> <Auth auth="sysApp:grantData">
<a-menu-item> <a-menu-item>
<a style="color:#005cb1;" @click="$refs.roleOrgForm.roleOrg(record)">授权数据</a> <a @click="$refs.roleOrgForm.roleOrg(record)">授权数据</a>
</a-menu-item>
</Auth>
<Auth auth="sysApp:delete">
</a-menu-item>
<a-menu-item>
<a-popconfirm
@confirm="onDelete(record)"
placement="topRight"
title="是否确认删除"
>
<a style="color:#005cb1;">删除</a>
</a-popconfirm>
</a-menu-item> </a-menu-item>
</Auth> </Auth>
</a-menu> </a-menu>
@@ -78,15 +65,15 @@
<br /> <br />
<add-form @ok="onReloadData" ref="add-form" /> <add-form @ok="onReloadData" ref="add-form" />
<edit-form @ok="onReloadData" ref="edit-form" /> <edit-form @ok="onReloadData" ref="edit-form" />
<role-menu-form ref="roleMenuForm" @ok="onReloadData"/> <role-menu-form @ok="onReloadData" ref="roleMenuForm" />
<role-org-form ref="roleOrgForm" @ok="onReloadData"/> <role-org-form @ok="onReloadData" ref="roleOrgForm" />
</container> </container>
</template> </template>
<script> <script>
import AddForm from './addForm'; import AddForm from './addForm';
import editForm from "./editForm"; import editForm from './editForm';
import roleMenuForm from "./roleMenuForm"; import roleMenuForm from './roleMenuForm';
import roleOrgForm from "./roleOrgForm"; import roleOrgForm from './roleOrgForm';
export default { export default {
components: { components: {
AddForm, AddForm,
@@ -99,23 +86,23 @@ export default {
query: {}, query: {},
columns: [ columns: [
{ {
title: "角色名", title: '角色名',
dataIndex: "name", dataIndex: 'name',
}, },
{ {
title: "唯一编码", title: '唯一编码',
dataIndex: "code", dataIndex: 'code',
}, },
{ {
title: "排序", title: '排序',
dataIndex: "sort", dataIndex: 'sort',
}, },
{ {
title: "操作", title: '操作',
width: "200px", width: '200px',
dataIndex: "action", dataIndex: 'action',
scopedSlots: { scopedSlots: {
customRender: "action", customRender: 'action',
}, },
}, },
], ],
@@ -172,9 +159,7 @@ export default {
// }); // });
// }, // },
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes const c = this.codes.find((p) => p.code == name).values.find((p) => p.code == code);
.find((p) => p.code == name)
.values.find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
@@ -201,17 +186,15 @@ export default {
onSetDefault(record) { onSetDefault(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api this.$api.sysAppSetAsDefault({ id: record.id }).then(({ success, message }) => {
.sysAppSetAsDefault({ id: record.id }) this.onResult(success, message, '设置成功');
.then(({ success, message }) => {
this.onResult(success, message, "设置成功");
}); });
}, },
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api.sysRoleDel(record).then(({ success, message }) => { this.$api.sysRoleDel(record).then(({ success, message }) => {
this.onResult(success, message, "删除成功"); this.onResult(success, message, '删除成功');
}); });
}, },
}, },

View File

@@ -10,29 +10,7 @@
> >
<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="请输入检索关键字" /> --> <search :menus="nav.menus" />
<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">
@@ -54,29 +32,7 @@
<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="请输入检索关键字" /> --> <search :menus="nav.menus" />
<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>
@@ -93,13 +49,17 @@
</a-layout-header> </a-layout-header>
</template> </template>
<script> <script>
import Logo from './logo'; import Logo from '../logo';
import Sider from './sider'; import Sider from '../sider';
import Search from './search';
export default { export default {
components: { components: {
Logo, Logo,
Sider, Sider,
Search,
}, },
props: { props: {
nav: { nav: {
@@ -118,9 +78,6 @@ export default {
searchResult: [], searchResult: [],
}; };
}, },
created() {
window._ = this.$_;
},
methods: { methods: {
onSearch(value) { onSearch(value) {
const menus = this.$_.cloneDeep(this.nav.menus); const menus = this.$_.cloneDeep(this.nav.menus);

View File

@@ -0,0 +1,134 @@
export default {
props: {
menus: {
type: Array,
require: true
}
},
data() {
return {
searchText: '',
searchResult: [],
};
},
methods: {
renderSelect(menu) {
return menu.map((p) => {
return p.children ? this.renderSelectGroup(p) : this.renderSelectOption(p)
})
},
renderSelectGroup(menu) {
return (
<a-select-opt-group key={menu.parents}>
<span slot="label">{menu.parents}</span>
{this.renderSelect(menu.children)}
</a-select-opt-group>
)
},
renderSelectOption(menu) {
return (<a-select-option key={menu.id} value={
JSON.stringify(menu)
}>
{menu.meta.title}
<small style={{ display: 'block', color: '#aaa' }}>{menu.component}</small>
</a-select-option>)
},
onSearch(value) {
this.searchText = value
const menus = this.$_.cloneDeep(this.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 || (p.component || '').toLowerCase().indexOf(value.toLowerCase()) > -1
}
return p.children.length
})
}
/**
* 拆分层级,只留下 [父级-父级-...] [子级]
* *******在更为复杂的目录下会出现父级联动错误的问题
*/
const unzip = (m) => {
const getSeed = (parent, seed) => {
if (parent.children) {
seed.parents.push(parent.meta.title)
seed.children = parent.children
parent.children.forEach(p => {
getSeed(p, seed)
})
}
return seed
}
const result = []
m.forEach(p => {
const r = { parents: [], children: [] }
result.push(getSeed(p, r))
})
return result
}
this.searchResult = unzip(search(menus)).map(p => {
return {
parents: p.parents.join('-'),
children: p.children
}
})
},
onSearchSelect(value, node) {
this.searchText = '';
this.onSearch(this.searchText);
const menu = JSON.parse(node.componentOptions.propsData.value)
this.openContentWindow({
key: menu.id,
title: menu.meta.title,
icon: menu.meta.icon,
path: menu.component,
});
},
},
render() {
const props = {
dropdownMatchSelectWidth: false,
dropdownStyle: { width: '300px' },
optionLabelProp: 'value',
placeholder: '请输入检索关键字',
value: this.searchText
}
const on = {
search: this.onSearch,
select: this.onSearchSelect
}
return (
<a-auto-complete {...{ props, on }}>
<template slot="dataSource">
{this.renderSelect(this.searchResult)}
</template>
<a-input>
<a-icon slot="suffix" type="search" class="certain-category-icon" />
</a-input>
</a-auto-complete>
)
}
}