基本完成
Former-commit-id: 4d9b039cac8205ae66e7c0189ba6c8ca0ee69068 [formerly 4d9b039cac8205ae66e7c0189ba6c8ca0ee69068 [formerly 4d9b039cac8205ae66e7c0189ba6c8ca0ee69068 [formerly 4d9b039cac8205ae66e7c0189ba6c8ca0ee69068 [formerly ef07da1feaee3062a8b597c01abe8676ec8fee1f [formerly 735ab19a7fa3c151c317952e38198c5803cdacad]]]]] Former-commit-id: 5ad5a87bb45c1a1ed8b63d80cf868339daceb31f Former-commit-id: 02ddcd34082c40f2e09ea08666912f8d6eb3fb65 Former-commit-id: 0b4940b7b5f60f5835f325da20923fb1caea05cf [formerly 47e09c5d46868279df43ca2a3d4fbdb6bbcd38ac] Former-commit-id: 9ac892cf0a29999a8560e45bd7a954f581efe1f8 Former-commit-id: a025b38832a9b326893545b422a7dea653c99f31 Former-commit-id: 4ce579cc6ca5cfd91ad3d1a25b59e74992256a3b Former-commit-id: 01eb489103d67ddabc90d711c42a3ccd39572e40 Former-commit-id: 8840285fb15925b1715f0983bb03119c8c0022d3
This commit is contained in:
@@ -3,7 +3,7 @@ import util from '@/libs/util.js'
|
|||||||
export default {
|
export default {
|
||||||
methods: {
|
methods: {
|
||||||
handleMenuSelect (index, indexPath) {
|
handleMenuSelect (index, indexPath) {
|
||||||
if (/^d2-menu-empty-\d+$/.test(index)) {
|
if (/^d2-menu-empty-\d+$/.test(index) || index === undefined) {
|
||||||
this.$message.warning('临时菜单')
|
this.$message.warning('临时菜单')
|
||||||
} else if (/^https:\/\/|http:\/\//.test(index)) {
|
} else if (/^https:\/\/|http:\/\//.test(index)) {
|
||||||
util.open(index)
|
util.open(index)
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<div class="d2-panel-search-item" :class="hoverMode ? 'can-hover' : ''" flex>
|
||||||
|
<div class="d2-panel-search-item__icon" flex-box="0">
|
||||||
|
<div class="d2-panel-search-item__icon-box" flex="main:center cross:center">
|
||||||
|
<d2-icon v-if="item.icon" :name="item.icon"/>
|
||||||
|
<d2-icon-svg v-else-if="item.iconSvg" :name="item.iconSvg"/>
|
||||||
|
<d2-icon v-else name="file-o"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d2-panel-search-item__info" flex-box="1" flex="dir:top">
|
||||||
|
<div class="d2-panel-search-item__info-title" flex-box="1" flex="cross:center">
|
||||||
|
<span>{{item.title}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="d2-panel-search-item__info-fullTitle" flex-box="0">
|
||||||
|
<span>{{item.fullTitle}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="d2-panel-search-item__info-path" flex-box="0">
|
||||||
|
<span>{{item.path}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
hoverMode: {
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~@/assets/style/public.scss';
|
||||||
|
.d2-panel-search-item {
|
||||||
|
height: 64px;
|
||||||
|
margin: 0px;
|
||||||
|
&.can-hover {
|
||||||
|
@extend %unable-select;
|
||||||
|
&:hover {
|
||||||
|
background-color: #F5F7FA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.d2-panel-search-item__icon {
|
||||||
|
width: 64px;
|
||||||
|
.d2-panel-search-item__icon-box {
|
||||||
|
height: 64px;
|
||||||
|
width: 64px;
|
||||||
|
border-right: 1px solid $color-border-3;
|
||||||
|
i {
|
||||||
|
font-size: 20px;
|
||||||
|
color: $color-text-sub;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.d2-panel-search-item__info {
|
||||||
|
margin-left: 10px;
|
||||||
|
.d2-panel-search-item__info-title {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $color-text-normal;
|
||||||
|
}
|
||||||
|
.d2-panel-search-item__info-fullTitle {
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 14px;
|
||||||
|
color: $color-text-placehoder;
|
||||||
|
}
|
||||||
|
.d2-panel-search-item__info-path {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 14px;
|
||||||
|
color: $color-text-placehoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,13 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="panel-search">
|
<div class="panel-search" flex="dir:top">
|
||||||
<div class="panel-search__input-group" flex="dir:top main:center cross:center">
|
<div class="panel-search__input-group" flex-box="0" flex="dir:top main:center cross:center">
|
||||||
<el-input
|
<el-autocomplete
|
||||||
class="panel-search__input"
|
class="panel-search__input"
|
||||||
ref="input"
|
ref="input"
|
||||||
v-model="input"
|
v-model="input"
|
||||||
suffix-icon="el-icon-search"
|
suffix-icon="el-icon-search"
|
||||||
placeholder="搜索页面"
|
placeholder="搜索页面"
|
||||||
@keydown.esc.native="handleEsc"/>
|
:fetch-suggestions="querySearch"
|
||||||
|
:trigger-on-focus="false"
|
||||||
|
:clearable="true"
|
||||||
|
@keydown.esc.native="handleEsc"
|
||||||
|
@select="handleSelect">
|
||||||
|
<d2-panel-search-item slot-scope="{ item }" :item="item"/>
|
||||||
|
</el-autocomplete>
|
||||||
<div class="panel-search__tip">
|
<div class="panel-search__tip">
|
||||||
您可以使用快捷键
|
您可以使用快捷键
|
||||||
<span class="panel-search__key">
|
<span class="panel-search__key">
|
||||||
@@ -20,31 +26,99 @@
|
|||||||
关闭
|
关闭
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="results.length > 0"
|
||||||
|
class="panel-search__results-group"
|
||||||
|
flex-box="1">
|
||||||
|
<el-card>
|
||||||
|
<div class="panel-search__results-group-inner">
|
||||||
|
<d2-panel-search-item
|
||||||
|
v-for="(item, index) in results"
|
||||||
|
:key="index"
|
||||||
|
:item="item"
|
||||||
|
:hover-mode="true"
|
||||||
|
@click.native="handleResultsGroupItemClick(item.path)"/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
|
import mixin from '../mixin/menu'
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [
|
||||||
|
mixin
|
||||||
|
],
|
||||||
|
components: {
|
||||||
|
'd2-panel-search-item': () => import('./components/panel-search-item/index.vue')
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
input: ''
|
input: '',
|
||||||
|
results: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState('d2admin/search', [
|
...mapState('d2admin/search', [
|
||||||
'hotkey'
|
'hotkey',
|
||||||
|
'pool'
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
querySearch (queryString, callback) {
|
||||||
|
var pool = this.pool
|
||||||
|
const results = (queryString ? pool : []).filter(item => {
|
||||||
|
const path = item.path || ''
|
||||||
|
const fullTitle = item.fullTitle || ''
|
||||||
|
return (`${fullTitle}${path}`.toLowerCase().indexOf(queryString.toLowerCase()) >= 0)
|
||||||
|
}).map(e => ({
|
||||||
|
value: e.fullTitle,
|
||||||
|
...e
|
||||||
|
}))
|
||||||
|
this.results = results
|
||||||
|
callback(results)
|
||||||
|
},
|
||||||
focus () {
|
focus () {
|
||||||
this.$nextTick(() => {
|
this.input = ''
|
||||||
this.input = ''
|
setTimeout(() => {
|
||||||
this.$refs.input.focus()
|
this.$refs.input.focus()
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
|
// 接收用户在列表中选择项目的事件
|
||||||
|
handleResultsGroupItemClick (path) {
|
||||||
|
// 如果用户选择的就是当前页面 就直接关闭搜索面板
|
||||||
|
if (path === this.$route.path) {
|
||||||
|
this.handleEsc()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 用户选择的是其它页面
|
||||||
|
this.handleMenuSelect(path)
|
||||||
|
},
|
||||||
|
// 接收用户在下拉菜单中选中事件
|
||||||
|
handleSelect ({ path }) {
|
||||||
|
// 如果用户选择的就是当前页面 就直接关闭搜索面板
|
||||||
|
if (path === this.$route.path) {
|
||||||
|
this.handleEsc()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 用户选择的是其它页面
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.handleMenuSelect(path)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
closeSuggestion () {
|
||||||
|
if (this.$refs.input.activated) {
|
||||||
|
this.$refs.input.suggestions = []
|
||||||
|
this.$refs.input.activated = false
|
||||||
|
}
|
||||||
|
},
|
||||||
handleEsc () {
|
handleEsc () {
|
||||||
this.$emit('close')
|
this.closeSuggestion()
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$emit('close')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,7 +131,7 @@ export default {
|
|||||||
.panel-search__input-group {
|
.panel-search__input-group {
|
||||||
height: 200px;
|
height: 200px;
|
||||||
.panel-search__input {
|
.panel-search__input {
|
||||||
width: 300px;
|
width: 500px;
|
||||||
}
|
}
|
||||||
.panel-search__tip {
|
.panel-search__tip {
|
||||||
@extend %unable-select;
|
@extend %unable-select;
|
||||||
@@ -73,5 +147,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.panel-search__results-group {
|
||||||
|
overflow: auto;
|
||||||
|
.panel-search__results-group-inner {
|
||||||
|
margin: -20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ new Vue({
|
|||||||
this.$store.commit('d2admin/page/init', frameInRoutes)
|
this.$store.commit('d2admin/page/init', frameInRoutes)
|
||||||
// 设置顶栏菜单
|
// 设置顶栏菜单
|
||||||
this.$store.commit('d2admin/menu/headerSet', menuHeader)
|
this.$store.commit('d2admin/menu/headerSet', menuHeader)
|
||||||
|
// 初始化菜单搜索功能
|
||||||
|
this.$store.commit('d2admin/search/init', menuHeader)
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
// 展示系统信息
|
// 展示系统信息
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import VueRouter from 'vue-router'
|
import VueRouter from 'vue-router'
|
||||||
|
|
||||||
|
import store from '@/store/index'
|
||||||
|
|
||||||
import util from '@/libs/util.js'
|
import util from '@/libs/util.js'
|
||||||
|
|
||||||
// 路由数据
|
// 路由数据
|
||||||
@@ -18,6 +20,8 @@ const router = new VueRouter({
|
|||||||
* 权限验证
|
* 权限验证
|
||||||
*/
|
*/
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
|
// 关闭搜索面板
|
||||||
|
store.commit('d2admin/search/set', false)
|
||||||
// 验证当前路由所有的匹配中是否需要有登陆验证的
|
// 验证当前路由所有的匹配中是否需要有登陆验证的
|
||||||
if (to.matched.some(r => r.meta.requiresAuth)) {
|
if (to.matched.some(r => r.meta.requiresAuth)) {
|
||||||
// 这里暂时将cookie里是否存有token作为验证是否登陆的条件
|
// 这里暂时将cookie里是否存有token作为验证是否登陆的条件
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ export default {
|
|||||||
state: {
|
state: {
|
||||||
// 搜索面板激活状态
|
// 搜索面板激活状态
|
||||||
active: true,
|
active: true,
|
||||||
|
// 快捷键
|
||||||
hotkey: {
|
hotkey: {
|
||||||
open: setting.hotkey.search.open,
|
open: setting.hotkey.search.open,
|
||||||
close: setting.hotkey.search.close
|
close: setting.hotkey.search.close
|
||||||
}
|
},
|
||||||
|
// 所有可以搜索的页面
|
||||||
|
pool: []
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
/**
|
/**
|
||||||
@@ -25,6 +28,28 @@ export default {
|
|||||||
*/
|
*/
|
||||||
set (state, active) {
|
set (state, active) {
|
||||||
state.active = active
|
state.active = active
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @description 初始化
|
||||||
|
* @param {Object} state vuex state
|
||||||
|
* @param {Array} menus menus
|
||||||
|
*/
|
||||||
|
init (state, menus) {
|
||||||
|
const pool = []
|
||||||
|
const push = function (menus, titlePrefix = []) {
|
||||||
|
menus.forEach(menu => {
|
||||||
|
if (menu.children) {
|
||||||
|
push(menu.children, [ ...titlePrefix, menu.title ])
|
||||||
|
} else {
|
||||||
|
pool.push({
|
||||||
|
...menu,
|
||||||
|
fullTitle: [ ...titlePrefix, menu.title ].join(' / ')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
push(menus)
|
||||||
|
state.pool = pool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user