兰宝车间质量管理系统-前端
LiuHao
2023-04-19 b2639184261f59279c98611f775f3fe821449e15
update searchMenu style
已修改3个文件
已添加1个文件
185 ■■■■■ 文件已修改
.eslintrc.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/HeaderSearch/index.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Navbar.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/topBar/search.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintrc.js
@@ -29,7 +29,8 @@
        // å…³é—­ç©ºç±»åž‹æ£€æŸ¥ {}
        extendDefaults: true,
        types: {
          '{}': false
          '{}': false,
          'Function': false
        }
      }
    ]
src/components/HeaderSearch/index.vue
@@ -17,7 +17,7 @@
  </div>
</template>
<script setup lang="ts">
<script setup lang="ts" name="HeaderSearch">
import Fuse from 'fuse.js'
import { getNormalPath } from '@/utils/ruoyi'
import { isHttp } from '@/utils/validate'
@@ -123,9 +123,9 @@
    searchPool.value = generateRoutes(routes.value);
})
watchEffect(() => {
    searchPool.value = generateRoutes(routes.value)
})
// watchEffect(() => {
//     searchPool.value = generateRoutes(routes.value)
// })
watch(show, (value) => {
    if (value) {
src/layout/components/Navbar.vue
@@ -20,8 +20,13 @@
          <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
        </el-select>
        <header-search id="header-search" class="right-menu-item" />
        <!-- <header-search id="header-search" class="right-menu-item" /> -->
        <search-menu ref="searchMenuRef" />
        <el-tooltip content="搜索" effect="dark" placement="bottom">
          <div class="right-menu-item hover-effect" @click="openSearchMenu">
            <svg-icon class-name="search-icon" icon-class="search" />
          </div>
        </el-tooltip>
        <el-tooltip content="Github" effect="dark" placement="bottom">
          <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
        </el-tooltip>
@@ -68,6 +73,7 @@
</template>
<script setup lang="ts">
import SearchMenu from './topBar/search.vue'
import useAppStore from '@/store/modules/app'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
@@ -89,6 +95,12 @@
const dynamic = ref(false);
// ç§Ÿæˆ·å¼€å…³
const tenantEnabled = ref(true);
// æœç´¢èœå•
const searchMenuRef = ref<InstanceType<typeof SearchMenu>>();
const openSearchMenu = () => {
  searchMenuRef.value?.openSearch()
}
// åŠ¨æ€åˆ‡æ¢
const dynamicTenantEvent = async (tenantId: string) => {
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>