feat: 菜单搜索功能支持拼音搜索,比如搜图片裁剪,输入tptupian等对应拼音即可

This commit is contained in:
xiaoxian521 2023-06-22 00:31:25 +08:00
parent 5873caf596
commit 5f71e0aad7
2 changed files with 21 additions and 11 deletions

View File

@ -1,11 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { match } from "pinyin-pro";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { cloneDeep } from "@pureadmin/utils";
import SearchResult from "./SearchResult.vue"; import SearchResult from "./SearchResult.vue";
import SearchFooter from "./SearchFooter.vue"; import SearchFooter from "./SearchFooter.vue";
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from "@/layout/hooks/useNav";
import { transformI18n } from "@/plugins/i18n"; import { transformI18n } from "@/plugins/i18n";
import { ref, computed, shallowRef } from "vue"; import { ref, computed, shallowRef } from "vue";
import { cloneDeep, isAllEmpty } from "@pureadmin/utils";
import { useDebounceFn, onKeyStroke } from "@vueuse/core"; import { useDebounceFn, onKeyStroke } from "@vueuse/core";
import { usePermissionStoreHook } from "@/store/modules/permission"; import { usePermissionStoreHook } from "@/store/modules/permission";
import Search from "@iconify-icons/ri/search-line"; import Search from "@iconify-icons/ri/search-line";
@ -23,6 +25,7 @@ const { device } = useNav();
const emit = defineEmits<Emits>(); const emit = defineEmits<Emits>();
const props = withDefaults(defineProps<Props>(), {}); const props = withDefaults(defineProps<Props>(), {});
const router = useRouter(); const router = useRouter();
const { locale } = useI18n();
const keyword = ref(""); const keyword = ref("");
const scrollbarRef = ref(); const scrollbarRef = ref();
@ -62,12 +65,19 @@ function flatTree(arr) {
/** 查询 */ /** 查询 */
function search() { function search() {
const flatMenusData = flatTree(menusData.value); const flatMenusData = flatTree(menusData.value);
resultOptions.value = flatMenusData.filter( resultOptions.value = flatMenusData.filter(menu =>
menu => keyword.value
keyword.value && ? transformI18n(menu.meta?.title)
transformI18n(menu.meta?.title)
.toLocaleLowerCase() .toLocaleLowerCase()
.includes(keyword.value.toLocaleLowerCase().trim()) .includes(keyword.value.toLocaleLowerCase().trim()) ||
(locale.value === "zh" &&
!isAllEmpty(
match(
transformI18n(menu.meta?.title).toLocaleLowerCase(),
keyword.value.toLocaleLowerCase().trim()
)
))
: false
); );
if (resultOptions.value?.length > 0) { if (resultOptions.value?.length > 0) {
activePath.value = resultOptions.value[0].path; activePath.value = resultOptions.value[0].path;

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from "vue-i18n"; import { transformI18n } from "@/plugins/i18n";
import { useResizeObserver } from "@vueuse/core"; import { useResizeObserver } from "@vueuse/core";
import { useEpThemeStoreHook } from "@/store/modules/epTheme"; import { useEpThemeStoreHook } from "@/store/modules/epTheme";
import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { useRenderIcon } from "@/components/ReIcon/src/hooks";
@ -7,8 +7,6 @@ import { ref, computed, getCurrentInstance, onMounted } from "vue";
import enterOutlined from "@/assets/svg/enter_outlined.svg?component"; import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
import Bookmark2Line from "@iconify-icons/ri/bookmark-2-line"; import Bookmark2Line from "@iconify-icons/ri/bookmark-2-line";
const { t } = useI18n();
interface optionsItem { interface optionsItem {
path: string; path: string;
meta?: { meta?: {
@ -98,7 +96,9 @@ defineExpose({ handleScroll });
@mouseenter="handleMouse(item)" @mouseenter="handleMouse(item)"
> >
<component :is="useRenderIcon(item.meta?.icon ?? Bookmark2Line)" /> <component :is="useRenderIcon(item.meta?.icon ?? Bookmark2Line)" />
<span class="result-item-title">{{ t(item.meta?.title) }}</span> <span class="result-item-title">
{{ transformI18n(item.meta?.title) }}
</span>
<enterOutlined /> <enterOutlined />
</div> </div>
</div> </div>