兰宝车间质量管理系统-前端
疯狂的狮子Li
2023-07-11 c13c622eac5551c6f099f148feb5256711ca34de
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):// è·¯å¾„新窗口打开
      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>