From c13c622eac5551c6f099f148feb5256711ca34de Mon Sep 17 00:00:00 2001
From: 疯狂的狮子Li <15040126243@163.com>
Date: 星期二, 11 七月 2023 21:03:01 +0800
Subject: [PATCH] !25 部分优化以及新增功能 Merge pull request !25 from ahaos/tspr

---
 src/layout/components/topBar/search.vue |  158 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 158 insertions(+), 0 deletions(-)

diff --git a/src/layout/components/topBar/search.vue b/src/layout/components/topBar/search.vue
new file mode 100644
index 0000000..9dee360
--- /dev/null
+++ b/src/layout/components/topBar/search.vue
@@ -0,0 +1,158 @@
+<template>
+  <div class="layout-search-dialog">
+    <el-dialog v-model="state.isShowSearch" destroy-on-close :show-close="false">
+      <template #footer>
+        <el-autocomplete
+          v-model="state.menuQuery"
+          :fetch-suggestions="menuSearch"
+          placeholder="鎼滅储"
+          ref="layoutMenuAutocompleteRef"
+          @select="onHandleSelect"
+          :fit-input-width="true"
+        >
+          <template #prefix>
+            <svg-icon class-name="search-icon" icon-class="search" />
+          </template>
+          <template #default="{ item }">
+            <div>
+              <svg-icon :icon-class="item.icon" class="mr5" />
+              {{ item.title }}
+            </div>
+          </template>
+        </el-autocomplete>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts" name="layoutBreadcrumbSearch">
+import { getNormalPath } from '@/utils/ruoyi';
+import { isHttp } from '@/utils/validate';
+import usePermissionStore from '@/store/modules/permission';
+import { RouteOption } from 'vue-router';
+type Router = Array<{
+	path: string;
+	icon: string;
+	title: string[];
+}>
+type SearchState<T = any> = {
+	isShowSearch: boolean;
+	menuQuery: string;
+	menuList: T[];
+};
+// 瀹氫箟鍙橀噺鍐呭
+const layoutMenuAutocompleteRef = ref();
+const router = useRouter();
+const routes = computed(() => usePermissionStore().routes);
+const state = reactive<SearchState>({
+	isShowSearch: false,
+	menuQuery: '',
+	menuList: [],
+});
+
+// 鎼滅储寮圭獥鎵撳紑
+const openSearch = () => {
+	state.menuQuery = '';
+	state.isShowSearch = true;
+	state.menuList = generateRoutes(routes.value);
+	nextTick(() => {
+		setTimeout(() => {
+			layoutMenuAutocompleteRef.value.focus();
+		});
+	});
+};
+// 鎼滅储寮圭獥鍏抽棴
+const closeSearch = () => {
+	state.isShowSearch = false;
+};
+// 鑿滃崟鎼滅储鏁版嵁杩囨护
+const menuSearch = (queryString: string, cb: Function) => {
+	let options = state.menuList.filter((item) => {
+		return item.title.indexOf(queryString) > -1;
+	});
+	cb(options);
+};
+
+// Filter out the routes that can be displayed in the sidebar
+// And generate the internationalized title
+const generateRoutes = (routes: RouteOption[], basePath = '', prefixTitle: string[] = []) => {
+	let res: Router = []
+	routes.forEach(r => {
+        // skip hidden router
+		if (!r.hidden) {
+			const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path;
+				const data: any = {
+					path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path,
+					icon: r.meta?.icon,
+					title: [...prefixTitle]
+				}
+				if (r.meta && r.meta.title) {
+					data.title = [...data.title, r.meta.title];
+					if (r.redirect !== 'noRedirect') {
+						// only push the routes with title
+						// special case: need to exclude parent router without redirect
+            res.push(data);
+					}
+				}
+				// recursive child routes
+				if (r.children) {
+						const tempRoutes = generateRoutes(r.children, data.path, data.title);
+						if (tempRoutes.length >= 1) {
+								res = [...res, ...tempRoutes];
+						}
+				}
+		}
+	})
+	res.forEach((item: any) => {
+		if (item.title instanceof Array) {
+			item.title = item.title.join('/');
+		}
+	});
+	return res;
+}
+// 褰撳墠鑿滃崟閫変腑鏃�
+const onHandleSelect = (val: any) => {
+	const paths = val.path;
+	if (isHttp(paths)) {
+		// http(s):// 璺緞鏂扮獥鍙f墦寮�
+		const pindex = paths.indexOf("http");
+		window.open(paths.substring(pindex, paths.length), "_blank");
+	} else {
+		router.push(paths);
+	}
+	state.menuQuery = ''
+	closeSearch();
+
+};
+
+// 鏆撮湶鍙橀噺
+defineExpose({
+	openSearch
+});
+</script>
+
+<style scoped lang="scss">
+.layout-search-dialog {
+	position: relative;
+	:deep(.el-dialog) {
+		.el-dialog__header,
+		.el-dialog__body {
+			display: none;
+		}
+		.el-dialog__footer {
+			width: 100%;
+			position: absolute;
+			left: 50%;
+			transform: translateX(-50%);
+			top: -53vh;
+		}
+	}
+	:deep(.el-autocomplete) {
+		width: 560px;
+		position: absolute;
+		top: 150px;
+		left: 50%;
+		transform: translateX(-50%);
+	}
+}
+</style>

--
Gitblit v1.9.3