Skip to content

Commit

Permalink
fix: 面包屑导航和弹窗拖拽后宽度问题
Browse files Browse the repository at this point in the history
  • Loading branch information
buqiyuan committed Dec 31, 2021
1 parent 15aec11 commit f4a24ef
Show file tree
Hide file tree
Showing 22 changed files with 221 additions and 97 deletions.
4 changes: 2 additions & 2 deletions .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
ENV = 'production'

# base api
VUE_APP_BASE_API = 'http://175.24.200.3:7001/admin/'
VUE_APP_BASE_API = 'http://buqiyuan.site:7001/admin/'
VUE_APP_BASE_SOCKET_PATH = '/ws-api'
VUE_APP_BASE_SOCKET_NSP = 'ws://175.24.200.3:7002/admin'
VUE_APP_BASE_SOCKET_NSP = 'ws://buqiyuan.site:7002/admin'

# 网站前缀
BASE_URL = /vue3-antd-admin/
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"test prod gzip": "http-server dist --cors --gzip -c-1"
},
"dependencies": {
"@vueuse/core": "^7.4.1",
"@vueuse/core": "^7.4.3",
"ant-design-vue": "3.0.0-beta.4",
"axios": "^0.24.0",
"core-js": "^3.20.1",
Expand Down
4 changes: 2 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<template>
<config-provider :locale="zhCN">
<ConfigProvider :locale="zhCN">
<router-view v-slot="{ Component }">
<Suspense>
<component :is="Component" />
</Suspense>
</router-view>
<LockScreen />
</config-provider>
</ConfigProvider>
</template>

<script setup lang="ts">
Expand Down
3 changes: 3 additions & 0 deletions src/components/a-custom-modal/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
v-model:visible="visibleModel"
:maskClosable="false"
:getContainer="() => modalWrapRef"
:width="innerWidth || width"
@ok="emit('ok')"
@cancel="emit('cancel')"
>
Expand Down Expand Up @@ -65,6 +66,7 @@
const visibleModel = useVModel(props, 'visible');
const fullscreenModel = ref(props.fullscreen);
const innerWidth = ref('');
const cursorStyle = {
top: 'n-resize',
Expand Down Expand Up @@ -234,6 +236,7 @@
modalEl.style.width = event.clientX - iParentLeft + 'px';
modalEl.style.height = event.clientY - iParentTop + 'px';
}
innerWidth.value = modalEl.style.width;
};
const mouseup = () => {
Expand Down
81 changes: 66 additions & 15 deletions src/layout/header/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
<component :is="collapsed ? MenuUnfoldOutlined : MenuFoldOutlined" />
</span>
<Breadcrumb>
<template v-for="(routeItem, rotueIndex) in $route.matched" :key="routeItem.name">
<template v-for="(routeItem, rotueIndex) in menus" :key="routeItem.name">
<Breadcrumb.Item>
<span>{{ getTitle(routeItem.meta.title) }}</span>
<template v-if="routeItem.children.length" #overlay>
<a-menu :selectedKeys="[$route.matched[rotueIndex + 1]?.name]" @click="clickMenuItem">
<template v-for="childItem in routeItem.children">
<a-menu-item v-if="!childItem.meta?.hideInMenu" :key="childItem.name">
<span>{{ getTitle(routeItem?.meta?.title) }}</span>
<template v-if="routeItem?.children?.length" #overlay>
<Menu :selectedKeys="[menus[rotueIndex + 1]?.name]">
<template v-for="childItem in routeItem?.children" :key="childItem.name">
<Menu.Item
v-if="!childItem.meta?.hideInMenu"
:key="childItem.name"
@click="clickMenuItem(childItem)"
>
<span>{{ getTitle(childItem.meta?.title) }}</span>
</a-menu-item>
</Menu.Item>
</template>
</a-menu>
</Menu>
</template>
</Breadcrumb.Item>
</template>
Expand Down Expand Up @@ -52,7 +56,7 @@

<script lang="tsx" setup>
import { ref, computed } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { useRouter, useRoute, RouteRecordRaw } from 'vue-router';
import {
Layout,
message,
Expand Down Expand Up @@ -92,14 +96,61 @@
const router = useRouter();
const route = useRoute();
const userInfo = computed(() => userStore.userInfo);
const menus = computed(() => {
console.log('route', route, userStore.menus);
if (route.meta?.namePath) {
let children = userStore.menus;
const paths = route.meta?.namePath?.map((item) => {
const a = children.find((n) => n.name === item);
children = a?.children || [];
return a;
});
return [
{
name: '__index',
meta: {
title: '首页',
},
children: userStore.menus,
},
...paths,
];
}
return route.matched;
});
const findLastChild = (route?: RouteRecordRaw) => {
if (typeof route?.redirect === 'object') {
const redirectValues = Object.values(route.redirect);
if (route?.children?.length) {
const target = route.children.find((n) =>
redirectValues.some((m) => [n.name, n.path, n.meta?.fullPath].some((v) => v === m)),
);
return findLastChild(target);
}
return redirectValues.find((n) => typeof n === 'string');
} else if (typeof route?.redirect === 'string') {
if (route?.children?.length) {
const target = route.children.find((n) =>
[n.name, n.path, n.meta?.fullPath].some((m) => m === route?.redirect),
);
return findLastChild(target);
}
return route?.redirect;
}
return route;
};
// 点击菜单
const clickMenuItem = ({ key }) => {
if (key === route.name) return;
if (/http(s)?:/.test(key)) {
window.open(key);
} else {
router.push({ name: key });
const clickMenuItem = (menuItem: RouteRecordRaw) => {
const lastChild = findLastChild(menuItem);
console.log('lastChild', menuItem, lastChild);
if (lastChild?.name === route.name) return;
if (/http(s)?:/.test(lastChild?.name)) {
window.open(lastChild?.name);
} else if (lastChild?.name) {
router.push({ name: lastChild.name });
}
};
Expand Down
14 changes: 8 additions & 6 deletions src/layout/menu/menu.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<template>
<a-menu
<Menu
v-model:open-keys="state.openKeys"
v-model:selected-keys="state.selectedKeys"
mode="inline"
theme="dark"
:inline-collapsed="props.collapsed"
:collapsed="props.collapsed"
collapsible
class="menu-container"
@click="clickMenuItem"
>
<template v-for="item in menus" :key="item.name">
<menu-item :menu-info="item" />
<MenuItem :menu-info="item" />
</template>
</a-menu>
</Menu>
</template>

<script setup lang="ts">
import { reactive, computed, watch } from 'vue';
import { Menu } from 'ant-design-vue';
import MenuItem from './menu-item.vue';
import { useUserStore } from '@/store/modules/user';
import { useRoute, useRouter } from 'vue-router';
Expand Down Expand Up @@ -43,9 +45,9 @@
const meta = currentRoute.meta;
if (meta?.activeMenu) {
const targetMenu = getTargetMenuByActiveMenuName(meta.activeMenu);
return targetMenu?.meta?.keyPath ?? meta?.activeMenu;
return targetMenu?.meta?.namePath ?? [meta?.activeMenu];
}
return currentRoute.meta?.keyPath ?? currentRoute.matched.slice(1).map((n) => n.name);
return currentRoute.meta?.namePath ?? currentRoute.matched.slice(1).map((n) => n.name);
};
const state = reactive({
Expand Down
2 changes: 1 addition & 1 deletion src/layout/tabs/tabs-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
<div class="tabs-view-content">
<router-view v-slot="{ Component }">
<template v-if="Component">
<transition name="zoom-fade" mode="out-in" appear>
<transition name="fade-transform" mode="out-in" appear>
<keep-alive :include="keepAliveComponents">
<suspense>
<component :is="Component" :key="route.fullPath" />
Expand Down
4 changes: 1 addition & 3 deletions src/plugins/assets.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import 'windi.css';
import '@/styles/global.less';
import '@/styles/common.less';
import '@/styles/antdv.override.less';
import '@/styles/index.less';

// 引入静态资源
export function setupAssets() {}
3 changes: 2 additions & 1 deletion src/router/asyncModules/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const prefix = 'shared/demos/';
export default {
'views/shared/demos/form/rule-form.vue': getAsyncPage(`${prefix}form/rule-form/index.vue`), // 验证表单
'views/shared/demos/icons/Iconfont.vue': getAsyncPage(`${prefix}icons/Iconfont.vue`), // 自定义图标
[`views/${prefix}tables/summary-table/index.vue`]: getAsyncPage(`${prefix}tables/summary-table`), // 合计表格
[`views/${prefix}tables/lol-table/index.vue`]: getAsyncPage(`${prefix}tables/lol-table`), // lol
[`views/${prefix}tables/wzry-table/index.vue`]: getAsyncPage(`${prefix}tables/wzry-table`), // wzry
'views/shared/demos/button.vue': getAsyncPage(`${prefix}button.vue`), // 自定义按钮
'views/shared/demos/custom-modal.vue': getAsyncPage(`${prefix}custom-modal.vue`), // 自定义模态框
};
Expand Down
38 changes: 26 additions & 12 deletions src/router/generator-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Result } from 'ant-design-vue';
import { type RouteRecordRaw } from 'vue-router';
import RouterView from '@/layout/routerView/index.vue';
import { isUrl } from '@/utils/is';
import { uniqueSlash } from '@/utils/urlUtils';
import { constantRouterComponents } from '@/router/asyncModules';
import NotFound from '@/views/shared/error/404.vue';
import router, { routes } from '.';
Expand All @@ -16,20 +17,20 @@ const endRoutes: RouteRecordRaw[] = [...shared, errorRoutes, notFound];
export function filterAsyncRoute(
routes: API.Menu[],
parentRoute: API.Menu | null = null,
lastKeyPath: string[] = [],
lastNamePath: string[] = [],
): RouteRecordRaw[] {
return routes
.filter((item) => item.type !== 2 && item.isShow && item.parentId == parentRoute?.id)
.map((item) => {
const { router, viewPath, name, icon, keepalive } = item;
let fullPath = '';
const pathPrefix = lastKeyPath.slice(-1)[0] || '';
const pathPrefix = lastNamePath.slice(-1)[0] || '';
if (isUrl(router)) {
fullPath = router;
} else {
fullPath = router.startsWith('/') ? router : '/' + router;
fullPath = router.startsWith(pathPrefix) ? fullPath : pathPrefix + fullPath;
fullPath = [...new Set(fullPath.split('/'))].join('/');
fullPath = [...new Set(uniqueSlash(fullPath).split('/'))].join('/');
}
let realRoutePath = router;
if (parentRoute) {
Expand All @@ -48,14 +49,14 @@ export function filterAsyncRoute(
title: name,
perms: [],
icon: icon,
keyPath: lastKeyPath.concat(fullPath),
namePath: lastNamePath.concat(fullPath),
keepAlive: keepalive,
},
};

if (item.type === 0) {
// 如果是目录
const children = filterAsyncRoute(routes, item, lastKeyPath.concat(fullPath));
const children = filterAsyncRoute(routes, item, lastNamePath.concat(fullPath));
if (children?.length) {
route.component = RouterView;
route.children = children;
Expand Down Expand Up @@ -100,7 +101,8 @@ export const generatorDynamicRouter = (asyncMenus: API.Menu[]) => {
const routeList = filterAsyncRoute(asyncMenus);
const layout = routes.find((item) => item.name == 'Layout')!;
// console.log(routeList, '根据后端返回的权限路由生成');
generatorKeyPath(common);
// 给公共路由添加namePath
generatorNamePath(common);
const menus = [...common, ...routeList];
layout.children = menus;
const removeRoute = router.addRoute(layout);
Expand Down Expand Up @@ -129,19 +131,31 @@ export const generatorDynamicRouter = (asyncMenus: API.Menu[]) => {

/**
* 主要方便于控制a-menu的open-keys,即控制左侧菜单应当展开哪些菜单
* @param {RouteRecordRaw[]} routes 需要添加keyPath的路由
* @param {string[]} keyPath
* @param {RouteRecordRaw[]} routes 需要添加namePath的路由
* @param {string[]} namePath
*/
export const generatorKeyPath = (routes: RouteRecordRaw[], keyPath?: string[]) => {
export const generatorNamePath = (
routes: RouteRecordRaw[],
namePath?: string[],
parent?: RouteRecordRaw,
) => {
routes.forEach((item) => {
if (item.children?.length) {
if (item.meta && typeof item.name === 'string') {
item.meta.keyPath = Array.isArray(keyPath) ? keyPath.concat(item.name) : [item.name];
generatorKeyPath(item.children, item.meta.keyPath);
item.meta.namePath = Array.isArray(namePath) ? namePath.concat(item.name) : [item.name];
item.meta.fullPath = parent?.meta?.fullPath
? [parent.meta.fullPath, item.path].join('/')
: item.path;
item.meta.fullPath = uniqueSlash(item.meta.fullPath);
generatorNamePath(item.children, item.meta.namePath, item);
}
} else {
if (item.meta && typeof item.name === 'string') {
item.meta.keyPath = Array.isArray(keyPath) ? keyPath.concat(item.name) : [item.name];
item.meta.namePath = Array.isArray(namePath) ? namePath.concat(item.name) : [item.name];
item.meta.fullPath = parent?.meta?.fullPath
? [parent.meta.fullPath, item.path].join('/')
: item.path;
item.meta.fullPath = uniqueSlash(item.meta.fullPath);
}
}
});
Expand Down
6 changes: 3 additions & 3 deletions src/router/staticModules/dashboard.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { type RouteRecordRaw } from 'vue-router';
import RouterView from '@/layout/routerView/index.vue';

const routeName = 'dashboard';
const moduleName = 'dashboard';

const routes: Array<RouteRecordRaw> = [
{
path: '/dashboard',
name: routeName,
name: moduleName,
redirect: '/dashboard/welcome',
component: RouterView,
meta: {
Expand All @@ -16,7 +16,7 @@ const routes: Array<RouteRecordRaw> = [
children: [
{
path: 'welcome',
name: `${routeName}-welcome`,
name: `${moduleName}-welcome`,
meta: {
title: '首页',
icon: 'icon-shouye',
Expand Down
Loading

0 comments on commit f4a24ef

Please sign in to comment.