菜单优化

This commit is contained in:
吕金泽 2022-01-07 01:08:42 +08:00
parent bbb1c5ccc7
commit 02cd4e7986
8 changed files with 162 additions and 82 deletions

View File

@ -4,11 +4,11 @@
"script" : null,
"groupId" : "67b2ce258e24491194b74992958c74aa",
"name" : "修改是否显示",
"createTime" : 1634724871168,
"updateTime" : 1634724871168,
"createTime" : null,
"updateTime" : 1641482987357,
"lock" : "0",
"method" : "GET",
"path" : "/change/show",
"path" : "/change",
"parameters" : [ ],
"option" : "[{\"name\":\"wrap_request_parameter\",\"value\":\"data\",\"description\":\"包装请求参数到一个变量中\"}]",
"requestBody" : "",

View File

@ -5,7 +5,7 @@
"groupId" : "67b2ce258e24491194b74992958c74aa",
"name" : "当前用户菜单",
"createTime" : null,
"updateTime" : 1641279378685,
"updateTime" : 1641482674575,
"lock" : "0",
"method" : "POST",
"path" : "/current/menus",
@ -453,7 +453,8 @@ var menus = db.select("""
sm.is_show,
sm.url,
sm.sort,
sm.icon
sm.icon,
sm.keep_alive
from sys_menu sm where 1=1
?{userId != '1',
and sm.id in (
@ -470,6 +471,7 @@ for(menu in menus){
menu.meta = {}
menu.meta.title = menu.name
menu.meta.icon = menu.icon
menu.meta.keepAlive = (menu.keepAlive == '1' ? true : false)
}
var nodes = menus.toMap(it => it.id)
nodes.each((key, node) => {

View File

@ -5,7 +5,7 @@
"groupId" : "67b2ce258e24491194b74992958c74aa",
"name" : "获取菜单tree",
"createTime" : null,
"updateTime" : 1641016870466,
"updateTime" : 1641483087321,
"lock" : "0",
"method" : "GET",
"path" : "/tree",
@ -94,7 +94,7 @@
}
================================
var toTree = (list,pid) => select t.*,toTree(list,t.id) children from list t where t.pid = pid
var list = toTree(db.select('select id,name,pid,is_show,url,sort,permission,desc_ribe,icon from sys_menu where is_del = 0 order by sort'),'0')
var list = toTree(db.select('select id,name,pid,is_show,url,sort,permission,desc_ribe,icon,keep_alive from sys_menu where is_del = 0 order by sort'),'0')
return {
list: list,

View File

@ -1,10 +1,9 @@
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<router-view :key="key" />
</keep-alive>
</transition>
<keep-alive>
<router-view v-if="$route.meta.keepAlive" :key="key" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" :key="key" />
</section>
</template>
@ -12,9 +11,6 @@
export default {
name: 'AppMain',
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews
},
key() {
return this.$route.path
}

View File

@ -1,3 +1,19 @@
<template>
<router-view />
<div>
<keep-alive>
<router-view v-if="$route.meta.keepAlive" :key="key" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" :key="key" />
</div>
</template>
<script>
export default {
name: 'None',
computed: {
key() {
return this.$route.path
}
}
}
</script>

View File

@ -14,9 +14,9 @@ export const constantRoutes = [
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: '首页',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: '首页', icon: 'home' }
meta: { title: '首页', icon: 'home', noCache: false }
}]
},

View File

@ -3,50 +3,83 @@
<div class="filter-container">
<el-form :inline="true">
<el-form-item label="搜索菜单名称">
<el-input v-model="searchValue" @input="searchMenu"></el-input>
<el-form-item label="菜单搜索">
<el-input v-model="searchValue" @input="searchMenu" placeholder="菜单名称、链接、权限标识" style="width: 200px"></el-input>
</el-form-item>
<el-button class="filter-item" style="margin-bottom:10px;" type="primary" icon="el-icon-edit" @click="addSubMenu('0')">
添加菜单
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="searchMenu">
搜索
</el-button>
<el-button class="filter-item" icon="el-icon-delete" @click="() => { this.searchValue = ''; searchMenu() }">
清空
</el-button>
</el-form>
</div>
<el-row style="margin-bottom: 5px">
<el-button class="filter-item" style="margin-bottom:10px;" type="primary" icon="el-icon-edit" @click="addSubMenu('0')">
添加菜单
</el-button>
</el-row>
<pd-table ref="table" v-bind="tableOptions" v-if="menuData && menuData.length > 0" />
<pd-dialog ref="menuFormDialog" width="800px" :title="textMap[dialogStatus]" @confirm-click="save()">
<template #content>
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="100px" style="width: 600px; margin-left:50px;">
<el-form-item label="上级菜单" prop="pid">
<treeselect v-model="temp.pid" :options="menuTree" />
</el-form-item>
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="right" label-width="80px" style="width: 600px; margin-left:50px;">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="菜单类型" prop="type">
<el-radio-group v-model="temp.type" size="small">
<el-radio-button label="menu">菜单</el-radio-button>
<el-radio-button label="button">按钮</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上级菜单" prop="pid">
<treeselect v-model="temp.pid" :options="menuTree" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="菜单名称" prop="name">
<el-input v-model="temp.name" />
</el-form-item>
<el-form-item label="菜单链接" prop="url">
<el-form-item label="菜单链接" prop="url" v-if="temp.type == 'menu'">
<el-input v-model="temp.url" />
</el-form-item>
<el-form-item label="权限标识" prop="permission">
<el-input v-model="temp.permission" />
</el-form-item>
<el-form-item label="图标" prop="icon">
<a @click="openIcons">
<el-input placeholder="请选择图标" v-model="temp.icon" class="input-with-select">
<el-button class="icon-btn" slot="append">
<i v-html="generateIconCode(temp.icon)"></i>
</el-button>
</el-input>
</a>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="temp.sort" />
</el-form-item>
<el-form-item label="描述">
<el-input v-model="temp.descRibe" :autosize="{ minRows: 4, maxRows: 6}" type="textarea" />
</el-form-item>
<el-form-item label="是否显示">
<el-checkbox v-model="temp.isShow">显示</el-checkbox>
</el-form-item>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="图标" prop="icon" v-if="temp.type == 'menu'">
<a @click="openIcons">
<el-input placeholder="请选择图标" v-model="temp.icon" class="input-with-select">
<el-button class="icon-btn" slot="append">
<i v-html="generateIconCode(temp.icon)"></i>
</el-button>
</el-input>
</a>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序" prop="sort">
<el-input-number v-model="temp.sort" controls-position="right" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="是否显示" v-if="temp.type == 'menu'">
<el-switch v-model="temp.isShow" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否缓存" v-if="temp.type == 'menu'">
<el-switch v-model="temp.keepAlive" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
</pd-dialog>
@ -90,13 +123,15 @@ export default {
{
field: 'url',
title: '路径',
align: 'left'
align: 'left',
type: 'html'
},
{
field: 'permission',
title: '权限标识',
width: 150,
align: 'left'
align: 'left',
type: 'html'
},
{
field: 'icon',
@ -118,12 +153,24 @@ export default {
type: 'switch',
width: 100,
change: (row) => {
this.$get('menu/change/show', {
this.$get('menu/change', {
id: row.id,
isShow: row.isShow
})
}
},
{
field: 'keepAlive',
title: '是否缓存',
type: 'switch',
width: 100,
change: (row) => {
this.$get('menu/change', {
id: row.id,
keepAlive: row.keepAlive
})
}
},
{
title: '操作',
type: 'btns',
@ -172,13 +219,26 @@ export default {
rules: {
pid: [{ required: true, message: '请选择上级菜单', trigger: 'change' }],
name: [{ required: true, message: '请输入菜单名称', trigger: 'change' }]
}
},
searchTimeout: ''
}
},
mounted() {
this.reloadTable()
},
watch: {
'temp.type'(type) {
for (var t in this.getTemp()) {
if(t != 'type'){
this.temp[t] = row[t]
}
}
if(type == 'menu'){
this.temp.isShow = 1
}else{
this.temp.isShow = 0
}
},
menuData() {
this.menuTree = [{
label: '根节点',
@ -234,11 +294,15 @@ export default {
return menuTree
},
searchMenu() {
if(this.searchValue){
this.$set(this.tableOptions, 'data', this.recursionSearch(this.$common.copyNew(this.menuData), this.searchValue))
}else{
this.$set(this.tableOptions, 'data', this.menuData)
}
var _this = this
clearTimeout(this.searchTimeout)
this.searchTimeout = setTimeout(() => {
if(_this.searchValue){
_this.$set(_this.tableOptions, 'data', _this.recursionSearch(_this.$common.copyNew(_this.menuData), _this.searchValue))
}else{
_this.$set(_this.tableOptions, 'data', _this.menuData)
}
},1000)
},
recursionSearch(data, text){
var searchData = []
@ -248,21 +312,28 @@ export default {
if(children && children.length > 0){
var childrenSearch = this.recursionSearch(children, text)
treeNode.children = childrenSearch && childrenSearch.length > 0 ? childrenSearch : treeNode.children
if(treeNode.name.indexOf(text) != -1 || childrenSearch.length > 0){
treeNode.name = treeNode.name.replace(text, `<font color="#FAA353">${text}</font>`)
searchData.push(treeNode)
}
this.treeNodeReplace(searchData, treeNode, text, childrenSearch)
}else{
if(treeNode.name.indexOf(text) != -1){
treeNode.name = treeNode.name.replace(text, `<font color="#FAA353">${text}</font>`)
searchData.push(treeNode)
}
this.treeNodeReplace(searchData, treeNode, text)
}
}
return searchData
},
treeNodeReplace(searchData, treeNode, text, childrenSearch){
var exist = false
var fields = ['name', 'url', 'permission']
fields.forEach((f) => {
if(treeNode[f] && treeNode[f].indexOf(text) != -1){
treeNode[f] = treeNode[f].replace(text, `<font color="#FAA353">${text}</font>`)
exist = true
}
})
if(exist || (childrenSearch && childrenSearch.length > 0)){
searchData.push(treeNode)
}
},
generateIconCode(symbol) {
return `<svg style="width: 20px;height: 20px" aria-hidden="true" class="svg-icon disabled"><use href="#icon-${symbol}"></use></svg>`
return `<svg style="width: 20px;height: 20px;fill: #999" aria-hidden="true" class="svg-icon disabled"><use href="#icon-${symbol}"></use></svg>`
},
selectIcon(symbol) {
this.$set(this.temp, 'icon', symbol)
@ -279,9 +350,11 @@ export default {
permission: '',
sort: 0,
descRibe: '',
isShow: true,
isShow: 1,
pid: '',
icon: ''
icon: '',
type: 'menu',
keepAlive: 1
}
},
resetTemp() {
@ -324,7 +397,6 @@ export default {
})
return
}
this.temp.isShow = this.temp.isShow === true ? 1 : 0
this.$post('menu/save', this.temp).then(() => {
this.reloadTable()
this.$refs.menuFormDialog.hide()
@ -346,16 +418,9 @@ export default {
},
handleUpdate(row) {
for (var t in this.temp) {
if (t === 'isShow') {
if (row[t] === 1) {
this.temp[t] = true
} else {
this.temp[t] = false
}
} else {
this.temp[t] = row[t]
}
this.temp[t] = row[t]
}
this.temp.type = this.temp.url ? 'menu' : 'button'
this.temp.name = this.temp.name.replaceAll(/<font.*?>(.*?)<\/font>/g,'$1')
this.dialogStatus = 'update'
this.$refs.menuFormDialog.show()

View File

@ -11,20 +11,21 @@
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="reloadTable">
搜索
</el-button>
<el-button v-permission="'user:save'" class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
添加
<el-button :loading="downloadLoading" class="filter-item" icon="el-icon-delete" @click="tableOptions.where = {}">
清空
</el-button>
<el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
<el-button :loading="downloadLoading" class="filter-item" icon="el-icon-download" @click="handleDownload">
导出
</el-button>
</el-form>
</div>
<hr>
<el-row style="margin-bottom: 6px">
<pd-button plain :request-url="'user/delete'" :btn-type="'delete'" :request-data="{ id: ids }" :after-handler="reloadTable" />
<el-row style="margin-bottom: 15px">
<el-button v-permission="'user:save'" class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">
添加
</el-button>
<pd-button :el="{ plain: true }" :request-url="'user/delete'" :btn-type="'delete'" :request-data="{ id: ids }" :after-handler="reloadTable" />
</el-row>
<hr>
<pd-table ref="table" v-bind="tableOptions" @selection-change="selectionChange" />