/** * * @author Ray * * @date 2023-04-16 * * @workspace ray-template * * @remark 今天也是元气满满撸代码的一天 */ import './index.scss' import { NInput, NModal, NResult, NScrollbar, NSpace } from 'naive-ui' import RayIcon from '@/components/RayIcon/index' import { on, off } from '@/utils/element' import { debounce } from 'lodash-es' import { useMenu } from '@/store' import { validMenuItemShow } from '@/router/helper/routerCopilot' import type { MenuOption } from 'naive-ui' import type { AppRouteMeta } from '@/router/type' const GlobalSeach = defineComponent({ name: 'GlobalSeach', props: { show: { type: Boolean, default: false, }, }, emits: ['update:show'], setup(props, { emit }) { const menuStore = useMenu() const { menuModelValueChange } = menuStore const modelShow = computed({ get: () => props.show, set: (val) => { emit('update:show', val) if (!val) { state.searchOptions = [] state.searchValue = null } }, }) const modelMenuOptions = computed(() => menuStore.options) const state = reactive({ searchValue: null, searchOptions: [] as IMenuOptions[], }) const tiptextOptions = [ { icon: 'cmd / ctrl + k', label: '唤起', plain: true, }, { icon: 'esc', label: '关闭', plain: true, }, ] /** 按下 ctrl + k 或者 command + k 激活搜索栏 */ const registerKeyboard = (e: Event) => { const _e = e as KeyboardEvent if ((_e.ctrlKey || _e.metaKey) && _e.key === 'k') { modelShow.value = true } } /** 根据输入值模糊检索菜单 */ const handleSearchMenuOptions = (value: string) => { const arr: IMenuOptions[] = [] const filterArr = (options: IMenuOptions[]) => { options.forEach((curr) => { if (curr.children?.length) { filterArr(curr.children) } /** 处理菜单名与输入值, 不区分大小写 */ const _breadcrumbLabel = curr.breadcrumbLabel?.toLocaleLowerCase() const _value = String(value).toLocaleLowerCase() if ( _breadcrumbLabel?.includes(_value) && validMenuItemShow(curr) && !curr.children?.length ) { arr.push(curr) } }) } if (value) { filterArr(modelMenuOptions.value) state.searchOptions = arr } else { state.searchOptions = [] } } const handleSearchItemClick = (option: MenuOption) => { const meta = option.meta as AppRouteMeta /** 如果配置站外跳转则不会关闭搜索框 */ if (meta.windowOpen) { window.open(meta.windowOpen) } else { modelShow.value = false menuModelValueChange(option.key as string, option) } } /** 渲染搜索菜单前缀图标, 如果没有则用 icon table 代替 */ const RenderPreIcon = (meta: AppRouteMeta) => { const { icon } = meta if (typeof icon === 'string') { return } else if (typeof icon === 'function') { return () => icon } else { return } } onMounted(() => { on(window, 'keydown', registerKeyboard) }) onBeforeUnmount(() => { off(window, 'keydown', registerKeyboard) }) return { ...toRefs(state), modelShow, tiptextOptions, handleSearchMenuOptions: debounce(handleSearchMenuOptions, 300), handleSearchItemClick, RenderPreIcon, } }, render() { return (
{{ prefix: () => , }}
{this.searchOptions.length ? ( {this.searchOptions.map((curr) => (
{this.RenderPreIcon(curr.meta)}
{curr.breadcrumbLabel}
))}
) : ( {{ icon: () => '', }} )}
) }, }) export default GlobalSeach