基本完成

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:
liyang
2018-08-28 17:00:09 +08:00
parent 34d2191bbc
commit 61cffc8e43
6 changed files with 208 additions and 12 deletions

View File

@@ -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)

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 () {
// 展示系统信息

View File

@@ -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作为验证是否登陆的条件

View File

@@ -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
}
}
}