feat:搜索新增常用菜单&移除常用菜单
This commit is contained in:
parent
5e0cacb556
commit
b9ad9522b1
@ -116,3 +116,15 @@
|
||||
.el-menu--horizontal .el-sub-menu .el-sub-menu__icon-arrow {
|
||||
right: calc(0px - var(--el-menu-base-level-padding)) !important;
|
||||
}
|
||||
|
||||
// 弹出搜索框
|
||||
.header-search-select {
|
||||
.el-select-dropdown__item {
|
||||
height: unset !important;
|
||||
line-height: unset !important;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,8 @@
|
||||
filterable
|
||||
default-first-option
|
||||
remote
|
||||
class="header_search_select"
|
||||
popper-class="header-search-select"
|
||||
placement="bottom"
|
||||
placeholder="菜单搜索,支持标题、URL模糊查询"
|
||||
@change="change">
|
||||
<template #prefix>
|
||||
@ -20,8 +21,13 @@
|
||||
</el-icon>
|
||||
</template>
|
||||
<el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')">
|
||||
<span style="float: left">{{ option.item.title.join(' > ') }}</span>
|
||||
<span style="float: right; color: var(--el-text-color-secondary); font-size: 13px">{{ option.item.path }}</span>
|
||||
<span style="float: left">
|
||||
<div>
|
||||
{{ option.item.title.join(' > ') }}
|
||||
<div class="path">{{ option.item.path }}</div>
|
||||
</div>
|
||||
</span>
|
||||
<span style="float: right" @click.stop="handleLove(option.item)"> <svg-icon color="#ccc" name="star" /></span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-dialog>
|
||||
@ -33,7 +39,8 @@ import Fuse from 'fuse.js'
|
||||
import { getNormalPath } from '@/utils/ruoyi'
|
||||
import { isHttp } from '@/utils/validate'
|
||||
import usePermissionStore from '@/store/modules/permission'
|
||||
|
||||
import { findItem, color16 } from '@/utils/ruoyi'
|
||||
const { proxy } = getCurrentInstance()
|
||||
const search = ref('')
|
||||
const options = ref([])
|
||||
const searchPool = ref([])
|
||||
@ -108,12 +115,15 @@ function generateRoutes(routes, basePath = '', prefixTitle = []) {
|
||||
const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path
|
||||
const data = {
|
||||
path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path,
|
||||
title: [...prefixTitle]
|
||||
title: [...prefixTitle],
|
||||
icon: 'menu',
|
||||
menuTitle: ''
|
||||
}
|
||||
|
||||
if (r.meta && r.meta.title) {
|
||||
data.title = [...data.title, r.meta.title]
|
||||
|
||||
data.icon = r.meta.icon
|
||||
data.menuTitle = r.meta.title
|
||||
if (r.redirect !== 'noRedirect') {
|
||||
// only push the routes with title
|
||||
// special case: need to exclude parent router without redirect
|
||||
@ -138,6 +148,28 @@ function querySearch(query) {
|
||||
options.value = []
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 添加快捷菜单
|
||||
* @param {*} item
|
||||
*/
|
||||
function handleLove(item) {
|
||||
var arraryObjectLocal = proxy.$cache.local.getJSON('commonlyUseMenu') || []
|
||||
|
||||
var len = 12
|
||||
if (arraryObjectLocal.length >= len) {
|
||||
proxy.$modal.msgError(`最多可添加${len}个常用菜单`)
|
||||
return
|
||||
}
|
||||
let index = findItem(arraryObjectLocal, 'path', item.path)
|
||||
if (index <= -1) {
|
||||
arraryObjectLocal.push({ ...item, color: color16() })
|
||||
proxy.$cache.local.setJSON('commonlyUseMenu', arraryObjectLocal)
|
||||
proxy.$modal.msgSuccess('添加成功')
|
||||
usePermissionStore().setCommonlyUsedRoutes()
|
||||
} else {
|
||||
proxy.$modal.msgError('该菜单已存在')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
searchPool.value = generateRoutes(routes.value)
|
||||
@ -178,18 +210,14 @@ watch(searchPool, (list) => {
|
||||
}
|
||||
}
|
||||
|
||||
.header_search_select {
|
||||
height: 50px;
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.path {
|
||||
color: #ccc;
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -31,9 +31,13 @@
|
||||
<el-switch v-model="isDark" class="mt-2" inline-prompt />
|
||||
</span>
|
||||
</div> -->
|
||||
<!-- <h3 class="drawer-title">
|
||||
{{ $t('layout.themeColor') }}
|
||||
</h3> -->
|
||||
<div class="drawer-item">
|
||||
<span>{{ $t('layout.themeColor') }}</span>
|
||||
<span class="comp-style">
|
||||
<span class="comp-style quick-color-wrap">
|
||||
<!-- <span :style="{ 'background-color': item }" v-for="item in predefineColors" @change="themeChange(item)"></span> -->
|
||||
<el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange" />
|
||||
</span>
|
||||
</div>
|
||||
@ -329,5 +333,16 @@ defineExpose({
|
||||
float: right;
|
||||
margin: -3px 8px 0px 0px;
|
||||
}
|
||||
.quick-color-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,6 +3,7 @@ import { getRouters } from '@/api/system/menu'
|
||||
import Layout from '@/layout/index'
|
||||
import ParentView from '@/components/ParentView'
|
||||
import InnerLink from '@/layout/components/InnerLink'
|
||||
import cache from '@/plugins/cache'
|
||||
|
||||
// 匹配views里面所有的.vue文件
|
||||
const modules = import.meta.glob('./../../views/**/*.vue')
|
||||
@ -12,7 +13,8 @@ const usePermissionStore = defineStore('permission', {
|
||||
routes: [],
|
||||
defaultRoutes: [],
|
||||
topbarRouters: [],
|
||||
sidebarRouters: []
|
||||
sidebarRouters: [],
|
||||
commonlyUsedRoutes: [] //常用路由
|
||||
}),
|
||||
actions: {
|
||||
setRoutes(routes) {
|
||||
@ -43,9 +45,23 @@ const usePermissionStore = defineStore('permission', {
|
||||
this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
|
||||
this.setDefaultRoutes(sidebarRoutes)
|
||||
this.setTopbarRoutes(defaultRoutes)
|
||||
this.setCommonlyUsedRoutes()
|
||||
resolve(rewriteRoutes)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 设置常用路由
|
||||
setCommonlyUsedRoutes() {
|
||||
var arraryObjectLocal = cache.local.getJSON('commonlyUseMenu') || []
|
||||
this.commonlyUsedRoutes = arraryObjectLocal
|
||||
},
|
||||
// 移除常用路由
|
||||
removeCommonlyUsedRoutes(item) {
|
||||
var routes = this.commonlyUsedRoutes
|
||||
|
||||
const fi = routes.findIndex((v) => v.path === item.path)
|
||||
routes.splice(fi, 1)
|
||||
cache.local.setJSON('commonlyUseMenu', routes)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -84,7 +84,7 @@ service.interceptors.response.use(
|
||||
} else if (message.includes('Request failed with status code 429')) {
|
||||
message = '请求过于频繁,请稍后再试'
|
||||
} else if (message.includes('Request failed with status code')) {
|
||||
message = '系统接口' + message.substr(message.length - 3) + '异常'
|
||||
message = '系统接口' + message.substr(message.length - 3) + '异常,请联系管理员'
|
||||
}
|
||||
ElMessage({
|
||||
message: message,
|
||||
|
||||
@ -257,3 +257,28 @@ export function isEmpty(obj) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找对象的唯一键值对(比如id)去判断是否存在某个数据中
|
||||
* @param {*} arr 数组
|
||||
* @param {*} key 对象键值名
|
||||
* @param {*} val
|
||||
* @returns
|
||||
*/
|
||||
export function findItem(arr, key, val) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i][key] == val) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
export function color16() {
|
||||
//十六进制颜色随机
|
||||
const r = Math.floor(Math.random() * 256)
|
||||
const g = Math.floor(Math.random() * 256)
|
||||
const b = Math.floor(Math.random() * 256)
|
||||
const color = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`
|
||||
return color
|
||||
}
|
||||
|
||||
@ -1,33 +1,60 @@
|
||||
<template>
|
||||
<div class="tool-wrap">
|
||||
<template v-for="item in menuList">
|
||||
<div class="tool-item" v-if="checkPermi(item)">
|
||||
<template v-for="item in commonRouters">
|
||||
<div class="tool-item">
|
||||
<span class="close-used" @click="removeRoute(item)" v-if="showRemove">
|
||||
<el-icon><CloseBold /></el-icon>
|
||||
</span>
|
||||
<router-link :to="item.path">
|
||||
<svg-icon :name="item.name" class-name="card-panel-icon mb10" :color="item.color" />
|
||||
<div>{{ item.title }}</div>
|
||||
<svg-icon :name="item.icon" class-name="card-panel-icon mb10" :color="item.color" />
|
||||
<div class="title">{{ item.menuTitle }}</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
<el-empty :image-size="80" v-if="commonRouters && commonRouters.length <= 0" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const { proxy } = getCurrentInstance()
|
||||
const menuList = ref([
|
||||
{ path: '/dashboard', title: '控制台', color: '#40c9c6', name: 'dashboard' },
|
||||
{ path: '/tool/gen', title: '代码生成', color: '#40c9c6', name: 'code', perms: ['tool:gen:list'] },
|
||||
{ path: '/tool/file', title: '文件存储', color: '#6A5ACD', name: 'upload', perms: ['tool:file:list'] },
|
||||
// // { path: '/system/user', title: '角色管理', color: '#7FFF00', name: 'peoples' },
|
||||
{ path: '/system/dict', title: '字典管理', color: '#B0E0E6', name: 'dict', perms: ['system:dict:list'] },
|
||||
{ path: '/monitor/job', title: '定时任务', color: '#D2691E', name: 'job', perms: ['monitor:job:list'] },
|
||||
{ path: '/system/log/operlog', title: '操作日志', color: '#D2691E', name: 'form', perms: ['monitor:operlog:list'] }
|
||||
// { path: '/system/log/logininfor', title: '登录日志', color: '#D2691E', name: 'logininfor' }
|
||||
])
|
||||
import usePermissionStore from '@/store/modules/permission'
|
||||
|
||||
function checkPermi(v) {
|
||||
if (v && v.perms) {
|
||||
return proxy.$auth.hasPermiOr(v.perms)
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
return true
|
||||
})
|
||||
const showRemove = ref(false)
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
showRemove.value = val
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
const commonRouters = computed(() => usePermissionStore().commonlyUsedRoutes)
|
||||
|
||||
// const { proxy } = getCurrentInstance()
|
||||
// const menuList = ref([
|
||||
// { path: '/dashboard', title: '控制台', color: '#40c9c6', name: 'dashboard' },
|
||||
// { path: '/tool/gen', title: '代码生成', color: '#40c9c6', name: 'code', perms: ['tool:gen:list'] },
|
||||
// { path: '/tool/file', title: '文件存储', color: '#6A5ACD', name: 'upload', perms: ['tool:file:list'] },
|
||||
// // // { path: '/system/user', title: '角色管理', color: '#7FFF00', name: 'peoples' },
|
||||
// { path: '/system/dict', title: '字典管理', color: '#B0E0E6', name: 'dict', perms: ['system:dict:list'] },
|
||||
// { path: '/monitor/job', title: '定时任务', color: '#D2691E', name: 'job', perms: ['monitor:job:list'] },
|
||||
// { path: '/system/log/operlog', title: '操作日志', color: '#D2691E', name: 'form', perms: ['monitor:operlog:list'] }
|
||||
// // { path: '/system/log/logininfor', title: '登录日志', color: '#D2691E', name: 'logininfor' }
|
||||
// ])
|
||||
|
||||
// function checkPermi(v) {
|
||||
// if (v && v.perms) {
|
||||
// return proxy.$auth.hasPermiOr(v.perms)
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
function removeRoute(item) {
|
||||
usePermissionStore().removeCommonlyUsedRoutes(item)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@ -40,11 +67,22 @@ function checkPermi(v) {
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
margin-bottom: 30px;
|
||||
position: relative;
|
||||
|
||||
.card-panel-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
.title {
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.close-used {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -51,9 +51,10 @@
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span><svg-icon name="tool" /> 常用功能</span>
|
||||
<el-button class="home-card-more" text @click="showEdit = !showEdit">{{ $t('btn.edit') }}</el-button>
|
||||
</template>
|
||||
<div class="info">
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper"> <CommonMenu></CommonMenu></el-scrollbar>
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper"> <CommonMenu v-model="showEdit"></CommonMenu></el-scrollbar>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
@ -108,7 +109,7 @@ import dayjs from 'dayjs'
|
||||
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import useSocketStore from '@/store/modules/socket'
|
||||
|
||||
const showEdit = ref(false)
|
||||
const data = {
|
||||
newVisitis: {
|
||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user