基本完成
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 {
|
||||
methods: {
|
||||
handleMenuSelect (index, indexPath) {
|
||||
if (/^d2-menu-empty-\d+$/.test(index)) {
|
||||
if (/^d2-menu-empty-\d+$/.test(index) || index === undefined) {
|
||||
this.$message.warning('临时菜单')
|
||||
} else if (/^https:\/\/|http:\/\//.test(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>
|
||||
<div class="panel-search">
|
||||
<div class="panel-search__input-group" flex="dir:top main:center cross:center">
|
||||
<el-input
|
||||
<div class="panel-search" flex="dir:top">
|
||||
<div class="panel-search__input-group" flex-box="0" flex="dir:top main:center cross:center">
|
||||
<el-autocomplete
|
||||
class="panel-search__input"
|
||||
ref="input"
|
||||
v-model="input"
|
||||
suffix-icon="el-icon-search"
|
||||
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">
|
||||
您可以使用快捷键
|
||||
<span class="panel-search__key">
|
||||
@@ -20,31 +26,99 @@
|
||||
关闭
|
||||
</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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import mixin from '../mixin/menu'
|
||||
export default {
|
||||
mixins: [
|
||||
mixin
|
||||
],
|
||||
components: {
|
||||
'd2-panel-search-item': () => import('./components/panel-search-item/index.vue')
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
input: ''
|
||||
input: '',
|
||||
results: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('d2admin/search', [
|
||||
'hotkey'
|
||||
'hotkey',
|
||||
'pool'
|
||||
])
|
||||
},
|
||||
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 () {
|
||||
this.$nextTick(() => {
|
||||
this.input = ''
|
||||
this.input = ''
|
||||
setTimeout(() => {
|
||||
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 () {
|
||||
this.$emit('close')
|
||||
this.closeSuggestion()
|
||||
this.$nextTick(() => {
|
||||
this.$emit('close')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +131,7 @@ export default {
|
||||
.panel-search__input-group {
|
||||
height: 200px;
|
||||
.panel-search__input {
|
||||
width: 300px;
|
||||
width: 500px;
|
||||
}
|
||||
.panel-search__tip {
|
||||
@extend %unable-select;
|
||||
@@ -73,5 +147,11 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.panel-search__results-group {
|
||||
overflow: auto;
|
||||
.panel-search__results-group-inner {
|
||||
margin: -20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -50,6 +50,8 @@ new Vue({
|
||||
this.$store.commit('d2admin/page/init', frameInRoutes)
|
||||
// 设置顶栏菜单
|
||||
this.$store.commit('d2admin/menu/headerSet', menuHeader)
|
||||
// 初始化菜单搜索功能
|
||||
this.$store.commit('d2admin/search/init', menuHeader)
|
||||
},
|
||||
mounted () {
|
||||
// 展示系统信息
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
|
||||
import store from '@/store/index'
|
||||
|
||||
import util from '@/libs/util.js'
|
||||
|
||||
// 路由数据
|
||||
@@ -18,6 +20,8 @@ const router = new VueRouter({
|
||||
* 权限验证
|
||||
*/
|
||||
router.beforeEach((to, from, next) => {
|
||||
// 关闭搜索面板
|
||||
store.commit('d2admin/search/set', false)
|
||||
// 验证当前路由所有的匹配中是否需要有登陆验证的
|
||||
if (to.matched.some(r => r.meta.requiresAuth)) {
|
||||
// 这里暂时将cookie里是否存有token作为验证是否登陆的条件
|
||||
|
||||
@@ -5,10 +5,13 @@ export default {
|
||||
state: {
|
||||
// 搜索面板激活状态
|
||||
active: true,
|
||||
// 快捷键
|
||||
hotkey: {
|
||||
open: setting.hotkey.search.open,
|
||||
close: setting.hotkey.search.close
|
||||
}
|
||||
},
|
||||
// 所有可以搜索的页面
|
||||
pool: []
|
||||
},
|
||||
mutations: {
|
||||
/**
|
||||
@@ -25,6 +28,28 @@ export default {
|
||||
*/
|
||||
set (state, 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