【更新】优化菜单搜索功能,感谢CcSimple兄弟送来的PR

pull/56/head
小诺 2 years ago committed by 俞宝山
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,

@ -188,9 +188,10 @@ a, button, input, textarea {
}
.snowy-header-logo {
height: 49px;
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…
Cancel
Save