mirror of https://gitee.com/xiaonuobase/snowy
【更新】优化菜单搜索功能,感谢CcSimple兄弟送来的PR
parent
887fa9d735
commit
362b538bae
|
@ -1,5 +1,4 @@
|
|||
import { mapState, mapMutations } from 'vuex'
|
||||
|
||||
import hotkeys from 'hotkeys-js'
|
||||
|
||||
export default {
|
||||
|
@ -30,9 +29,7 @@ export default {
|
|||
searchToggle: 'search/toggle',
|
||||
searchSet: 'search/set'
|
||||
}),
|
||||
/**
|
||||
* 接收点击搜索按钮
|
||||
*/
|
||||
// 接收点击搜索按钮
|
||||
handleSearchClick() {
|
||||
this.searchToggle()
|
||||
if (this.searchActive) {
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
class="search-box"
|
||||
style="width: 100%"
|
||||
allowClear
|
||||
placeholder="搜索页面(支持拼音检索)"
|
||||
size="large"
|
||||
placeholder="搜索页面(支持拼音检索)"
|
||||
@change="querySearch"
|
||||
>
|
||||
<template #prefix>
|
||||
|
@ -15,7 +14,7 @@
|
|||
</template>
|
||||
</a-input>
|
||||
<a-card
|
||||
:body-style="{ padding: '4px 0' }"
|
||||
:body-style="{ padding: '0 0' }"
|
||||
hoverable
|
||||
@mouseenter="onCardIn"
|
||||
@mouseleave="onCardOut"
|
||||
|
@ -23,13 +22,13 @@
|
|||
@keypress.down="handleKeyDown"
|
||||
style="margin: 10px 0"
|
||||
>
|
||||
<div ref="cardList" class="search-card beauty-scroll" style="">
|
||||
<div ref="cardList" class="search-card beauty-scroll">
|
||||
<a-list size="small" :data-source="resultsList">
|
||||
<template #renderItem="{ item, index }">
|
||||
<a-list-item
|
||||
@click="handleSelect(item.fullPath)"
|
||||
@mouseover="onCardItemHover(index)"
|
||||
:class="{ active: index == cardIndex }"
|
||||
:class="{ active: index === cardIndex }"
|
||||
style="padding-right: 10px"
|
||||
>
|
||||
<template #actions>
|
||||
|
@ -42,7 +41,7 @@
|
|||
<a>{{ item.name }}</a>
|
||||
</template>
|
||||
<template #avatar>
|
||||
<a-avatar style="color: black; background-color: transparent" :type="item.icon">
|
||||
<a-avatar style="color: var(--text-color); background-color: transparent" :type="item.icon">
|
||||
<template #icon>
|
||||
<component :is="item.icon" />
|
||||
</template>
|
||||
|
@ -108,18 +107,14 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @description 过滤选项 这个方法在每次输入框的值发生变化时会触发
|
||||
*/
|
||||
// 过滤选项 这个方法在每次输入框的值发生变化时会触发
|
||||
querySearch(e) {
|
||||
let queryString = e.target.value || ''
|
||||
const results = queryString && this.fuse.search(queryString).map((e) => e.item)
|
||||
this.searchText = queryString
|
||||
this.results = results
|
||||
},
|
||||
/**
|
||||
* @description 聚焦输入框
|
||||
*/
|
||||
// 聚焦输入框
|
||||
focus() {
|
||||
this.searchText = ''
|
||||
setTimeout(() => {
|
||||
|
@ -178,9 +173,7 @@
|
|||
onCardItemHover(index) {
|
||||
this.cardIndex = index
|
||||
},
|
||||
/**
|
||||
* @description 接收用户在下拉菜单中选中事件
|
||||
*/
|
||||
// 接收用户在下拉菜单中选中事件
|
||||
handleSelect(path) {
|
||||
// 如果用户选择的就是当前页面 就直接关闭搜索面板
|
||||
if (path === this.$route.path) {
|
||||
|
@ -190,26 +183,20 @@
|
|||
this.$router.push({ path })
|
||||
this.handleEsc()
|
||||
},
|
||||
/**
|
||||
* @augments 关闭输入框的下拉菜单
|
||||
*/
|
||||
// 关闭输入框的下拉菜单
|
||||
closeSuggestion() {
|
||||
if (this.$refs.input.activated) {
|
||||
this.results = []
|
||||
this.$refs.input.activated = false
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @augments 接收用户点击空白区域的关闭
|
||||
*/
|
||||
// 接收用户点击空白区域的关闭
|
||||
handlePanelClick(e) {
|
||||
if ('INPUT' != e.target.tagName) {
|
||||
if ('INPUT' !== e.target.tagName) {
|
||||
this.handleEsc()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @augments 接收用户触发的关闭
|
||||
*/
|
||||
// 接收用户触发的关闭
|
||||
async handleEsc() {
|
||||
this.closeSuggestion()
|
||||
await this.$nextTick()
|
||||
|
@ -221,21 +208,23 @@
|
|||
|
||||
<style lang="less" scoped>
|
||||
/deep/ .ant-input {
|
||||
height: 48px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
/deep/ .ant-input:not(:first-child) {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/deep/ .ant-input-prefix {
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
}
|
||||
/deep/ .ant-list-sm .ant-list-item {
|
||||
padding: 4px 16px;
|
||||
}
|
||||
/deep/ .ant-list-item-meta {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.beauty-scroll {
|
||||
scrollbar-color: var(--primary-color) var(--primary-2);
|
||||
scrollbar-width: thin;
|
||||
|
@ -255,31 +244,22 @@
|
|||
background: var(--primary-3);
|
||||
}
|
||||
}
|
||||
|
||||
.search-card {
|
||||
height: 220px;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
/deep/ .ant-list-item.active {
|
||||
background-color: var(--primary-1);
|
||||
}
|
||||
|
||||
.search-tips {
|
||||
display: flex;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding-top: 6px;
|
||||
|
||||
border-top: 1px solid var(--component-background);
|
||||
padding-top: 10px;
|
||||
.tips {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.key {
|
||||
//display: flex;
|
||||
//flex-direction: row;
|
||||
//align-items: center;
|
||||
//justify-content: center;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
|
@ -287,7 +267,6 @@
|
|||
padding-bottom: 2px;
|
||||
margin: 0px 4px;
|
||||
border-radius: 2px;
|
||||
background-color: white;
|
||||
box-shadow: inset 0 -2px #cdcde6, inset 0 0 1px 1px #fff, 0 1px 2px 1px #1e235a66;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
.d2-panel-search-item__icon-box {
|
||||
i {
|
||||
font-size: 24px;
|
||||
color: @primary-color;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
style="overflow: hidden"
|
||||
destroyOnClose
|
||||
dialogClass="searchModal"
|
||||
:bodyStyle="{ maxHeight: '520px', overflow: 'auto', padding: '10px' }"
|
||||
:bodyStyle="{ maxHeight: '520px', overflow: 'auto', padding: '14px' }"
|
||||
@cancel="searchPanelClose"
|
||||
>
|
||||
<panel-search ref="panelSearch" @close="searchPanelClose" />
|
||||
|
|
|
@ -14,26 +14,15 @@ export default {
|
|||
pool: []
|
||||
},
|
||||
mutations: {
|
||||
/**
|
||||
* @description 切换激活状态
|
||||
* @param {Object} state state
|
||||
*/
|
||||
// 切换激活状态
|
||||
toggle(state) {
|
||||
state.active = !state.active
|
||||
},
|
||||
/**
|
||||
* @description 设置激活模式
|
||||
* @param {Object} state state
|
||||
* @param {Boolean} active active
|
||||
*/
|
||||
// 设置激活模式
|
||||
set(state, active) {
|
||||
state.active = active
|
||||
},
|
||||
/**
|
||||
* @description 初始化
|
||||
* @param {Object} state state
|
||||
* @param {Array} menu menu
|
||||
*/
|
||||
// 初始化
|
||||
init(state, menu) {
|
||||
const pool = []
|
||||
const getFullName = function (meta) {
|
||||
|
@ -48,10 +37,10 @@ export default {
|
|||
}
|
||||
const push = function (menu) {
|
||||
menu.forEach((m) => {
|
||||
if ('menu' == m.meta.type) {
|
||||
if ('menu' === m.meta.type) {
|
||||
if (m.children) {
|
||||
push(m.children)
|
||||
} else {
|
||||
} else if (m.children === null){
|
||||
pool.push({
|
||||
icon: m.meta.icon,
|
||||
path: m.path,
|
||||
|
|
|
@ -183,14 +183,15 @@ a, button, input, textarea {
|
|||
}
|
||||
|
||||
.snowy-header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.snowy-header-logo {
|
||||
height: 49px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
||||
}
|
||||
|
||||
.snowy-header-logo-primary-color {
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||
*/
|
||||
import { mapState } from 'vuex'
|
||||
import { DEVICE_TYPE, deviceEnquire } from '@/utils/device'
|
||||
|
||||
// const mixinsComputed = Vue.config.optionMergeStrategies.computed
|
||||
// const mixinsMethods = Vue.config.optionMergeStrategies.methods
|
||||
|
||||
const mixin = {
|
||||
computed: {
|
||||
...mapState({
|
||||
layoutMode: (state) => state.app.layout,
|
||||
navTheme: (state) => state.app.theme,
|
||||
primaryColor: (state) => state.app.color,
|
||||
colorWeak: (state) => state.app.weak,
|
||||
fixedHeader: (state) => state.app.fixedHeader,
|
||||
fixSiderbar: (state) => state.app.fixSiderbar,
|
||||
fixSidebar: (state) => state.app.fixSiderbar,
|
||||
contentWidth: (state) => state.app.contentWidth,
|
||||
autoHideHeader: (state) => state.app.autoHideHeader,
|
||||
sidebarOpened: (state) => state.app.sidebar,
|
||||
multiTab: (state) => state.app.multiTab
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
isTopMenu() {
|
||||
return this.layoutMode === 'topmenu'
|
||||
},
|
||||
isSideMenu() {
|
||||
return !this.isTopMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mixinDevice = {
|
||||
computed: {
|
||||
...mapState({
|
||||
device: (state) => state.app.device
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
isMobile() {
|
||||
return this.device === DEVICE_TYPE.MOBILE
|
||||
},
|
||||
isDesktop() {
|
||||
return this.device === DEVICE_TYPE.DESKTOP
|
||||
},
|
||||
isTablet() {
|
||||
return this.device === DEVICE_TYPE.TABLET
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AppDeviceEnquire = {
|
||||
mounted() {
|
||||
const { $store } = this
|
||||
deviceEnquire((deviceType) => {
|
||||
switch (deviceType) {
|
||||
case DEVICE_TYPE.DESKTOP:
|
||||
$store.commit('TOGGLE_DEVICE', 'desktop')
|
||||
$store.dispatch('setSidebar', true)
|
||||
break
|
||||
case DEVICE_TYPE.TABLET:
|
||||
$store.commit('TOGGLE_DEVICE', 'tablet')
|
||||
$store.dispatch('setSidebar', false)
|
||||
break
|
||||
case DEVICE_TYPE.MOBILE:
|
||||
default:
|
||||
$store.commit('TOGGLE_DEVICE', 'mobile')
|
||||
$store.dispatch('setSidebar', true)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { mixin, AppDeviceEnquire, mixinDevice }
|
|
@ -1,11 +1,6 @@
|
|||
import pinyin from 'js-pinyin'
|
||||
import store from '@/store/index'
|
||||
|
||||
/**
|
||||
* 中文转拼音
|
||||
* @param first 仅首字母
|
||||
* @returns {String}
|
||||
*/
|
||||
// 中文转拼音 传入仅首字母
|
||||
Object.defineProperty(String.prototype, 'toPinyin', {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
|
@ -19,11 +14,7 @@ Object.defineProperty(String.prototype, 'toPinyin', {
|
|||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 字符检索
|
||||
* @param input 检索值
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
// 字符检索 传入检索值
|
||||
Object.defineProperty(String.prototype, 'filter', {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
|
|
Loading…
Reference in New Issue