Unverified Commit a53c40ae authored by 言肆's avatar 言肆 Committed by GitHub

Merge branch 'next' into next

parents fdc90545 f834b2b3
<template> <template>
<a-config-provider :getPopupContainer="getPopupContainer"> <a-config-provider :get-popup-container="getPopupContainer">
<router-view /> <router-view />
</a-config-provider> </a-config-provider>
</template> </template>
...@@ -12,15 +12,14 @@ export default defineComponent({ ...@@ -12,15 +12,14 @@ export default defineComponent({
setup() { setup() {
const getPopupContainer = (el: Element, dialogContext: any) => { const getPopupContainer = (el: Element, dialogContext: any) => {
if (dialogContext) { if (dialogContext) {
return dialogContext.getDialogWrap(); return dialogContext.getDialogWrap();
} else { }
return document.body; return document.body;
} };
}
return { return {
getPopupContainer, getPopupContainer,
} };
} },
}); });
</script> </script>
......
...@@ -5,14 +5,30 @@ ...@@ -5,14 +5,30 @@
v-model:openKeys="baseState.openKeys" v-model:openKeys="baseState.openKeys"
v-bind="state" v-bind="state"
:loading="loading" :loading="loading"
:collapsed-button-render="false"
:breadcrumb="{ routes: breadcrumb }"
> >
<template #collapsedButtonRender> <!-- only work layout `Side` -->
<a-button>abc</a-button> <template #headerContentRender>
<a :style="{ margin: '0 8px', fontSize: '20px' }" @click="handleCollapsed">
<MenuUnfoldOutlined v-if="baseState.collapsed" />
<MenuFoldOutlined v-else />
</a>
<span>some..</span>
</template> </template>
<!-- custom right-content --> <!-- custom right-content -->
<template #rightContentRender> <template #rightContentRender>
<span style="color: #0f0">right</span> <span style="color: #0f0">right</span>
</template> </template>
<!-- custom breadcrumb itemRender -->
<template #breadcrumbRender="{ route, params, routes }">
<span v-if="routes.indexOf(route) === routes.length - 1">
{{ route.breadcrumbName }}
</span>
<router-link v-else :to="{ path: route.path, params }">
{{ route.breadcrumbName }}
</router-link>
</template>
<!-- content begin --> <!-- content begin -->
<router-view /> <router-view />
<!-- content end --> <!-- content end -->
...@@ -43,7 +59,7 @@ ...@@ -43,7 +59,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, ref, watchEffect } from 'vue'; import { computed, defineComponent, reactive, ref, watchEffect } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { Button, Switch, Select, Space } from 'ant-design-vue'; import { Button, Switch, Select, Space } from 'ant-design-vue';
import { getMenuData, clearMenuItem, FooterToolbar } from '@ant-design-vue/pro-layout'; import { getMenuData, clearMenuItem, FooterToolbar } from '@ant-design-vue/pro-layout';
...@@ -76,16 +92,32 @@ export default defineComponent({ ...@@ -76,16 +92,32 @@ export default defineComponent({
const state = reactive({ const state = reactive({
menuData, menuData,
splitMenus: false, splitMenus: true,
title: 'ProLayout', title: 'ProLayout',
logo: 'https://alicdn.antdv.com/v2/assets/logo.1ef800a8.svg', logo: 'https://alicdn.antdv.com/v2/assets/logo.1ef800a8.svg',
navTheme: 'light', navTheme: 'dark',
layout: 'mix', layout: 'mix',
}); });
const breadcrumb = computed(() =>
router.currentRoute.value.matched.concat().map(item => {
return {
path: item.path,
breadcrumbName: item.meta.title || '',
};
}),
);
const handleCollapsed = () => {
baseState.collapsed = !baseState.collapsed;
};
watchEffect(() => { watchEffect(() => {
if (router.currentRoute) { if (router.currentRoute) {
baseState.selectedKeys = router.currentRoute.value.matched.concat().map(r => r.path); const matched = router.currentRoute.value.matched.concat();
console.log('matched', matched);
baseState.selectedKeys = matched.filter(r => r.name !== 'index').map(r => r.path);
baseState.openKeys = matched
.filter(r => r.path !== router.currentRoute.value.path)
.map(r => r.path);
} }
}); });
...@@ -101,7 +133,10 @@ export default defineComponent({ ...@@ -101,7 +133,10 @@ export default defineComponent({
baseState, baseState,
state, state,
loading, loading,
breadcrumb,
handlePageLoadingClick, handlePageLoadingClick,
handleCollapsed,
}; };
}, },
}); });
......
<template>
<router-view />
</template>
import 'ant-design-vue/es/style';
import { ConfigProvider } from 'ant-design-vue';
import { createApp } from 'vue'; import { createApp } from 'vue';
import router from './router'; import router from './router';
import icons from './icons'; import icons from './icons';
import App from './App.vue'; import App from './App.vue';
import { ConfigProvider }from 'ant-design-vue';
import ProLayout, { PageContainer } from '../src';
import 'ant-design-vue/es/style'; import '../dist/style.less';
import ProLayout, { PageContainer } from '../src'; // '../dist/pro-layout.es';
const app = createApp(App); const app = createApp(App);
app.use(router); app.use(router);
......
import { createRouter, createWebHistory } from 'vue-router'; import { createRouter, createWebHistory } from 'vue-router';
import type { RouteRecordRaw } from 'vue-router'; import type { RouteRecordRaw } from 'vue-router';
import BasicLayout from './layouts/BasicLayout.vue'; import BasicLayout from './layouts/BasicLayout.vue';
import RouteView from './layouts/RouteView.vue';
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
{ {
path: '/', path: '/',
name: 'index', name: 'index',
meta: { title: '' }, meta: { title: 'Home' },
component: BasicLayout, component: BasicLayout,
redirect: '/monitor', redirect: '/dashboard',
children: [ children: [
{ {
path: '/dashboard', path: '/dashboard',
name: 'dashboard', name: 'dashboard',
meta: { title: 'Dashboard', icon: 'SettingOutlined' }, meta: { title: 'Dashboard' },
component: () => import('./views/page1.vue'), redirect: '/dashboard/monitor',
component: RouteView,
children: [
{
path: 'workspace',
name: 'workspace',
meta: { title: 'Dashboard', icon: 'SettingOutlined' },
component: () => import('./views/page1.vue'),
},
{
path: 'monitor',
name: 'monitor',
meta: { title: 'Monitor', icon: 'DatabaseOutlined' },
component: () => import('./views/page2.vue'),
},
],
}, },
{ {
path: '/monitor', path: '/form',
name: 'monitor', name: 'form',
meta: { title: 'Monitor', icon: 'DatabaseOutlined' }, meta: { title: 'Form' },
component: () => import('./views/page2.vue'), redirect: '/form/basic-form',
component: RouteView,
children: [
{
path: 'basic-form',
name: 'basic-form',
meta: { title: 'Basic Form', icon: 'SettingOutlined' },
component: () => import('./views/page1.vue'),
},
],
}, },
], ],
}, },
...@@ -28,6 +53,5 @@ const routes: RouteRecordRaw[] = [ ...@@ -28,6 +53,5 @@ const routes: RouteRecordRaw[] = [
export default createRouter({ export default createRouter({
history: createWebHistory(), history: createWebHistory(),
routes: routes, routes,
}); });
declare module '*.vue' { declare module '*.vue' {
import { DefineComponent } from 'vue' import { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>
export default component const component: DefineComponent<{}, {}, any>;
export default component;
} }
{ {
"name": "@ant-design-vue/pro-layout", "name": "@ant-design-vue/pro-layout",
"version": "3.1.0-alpha.4", "version": "3.1.0-alpha.5",
"license": "MIT", "license": "MIT",
"files": [ "files": [
"dist", "dist",
...@@ -29,7 +29,8 @@ ...@@ -29,7 +29,8 @@
"dev": "vite", "dev": "vite",
"build": "vue-tsc --noEmit && vite build", "build": "vue-tsc --noEmit && vite build",
"serve": "vite preview", "serve": "vite preview",
"build:types": "tsc -b --force tsconfig.esm.json" "build:types": "tsc -b --force tsconfig.esm.json",
"prepublish": "yarn build && yarn build:types"
}, },
"peerDependencies": { "peerDependencies": {
"ant-design-vue": ">=2.2.0", "ant-design-vue": ">=2.2.0",
......
...@@ -4,9 +4,9 @@ import type { CSSProperties, PropType, ExtractPropTypes } from 'vue'; ...@@ -4,9 +4,9 @@ import type { CSSProperties, PropType, ExtractPropTypes } from 'vue';
import 'ant-design-vue/es/layout/style'; import 'ant-design-vue/es/layout/style';
import Layout from 'ant-design-vue/es/layout'; import Layout from 'ant-design-vue/es/layout';
import omit from 'omit.js'; import omit from 'omit.js';
import { withInstall } from 'ant-design-vue/es/_util/type';
import useMediaQuery from './hooks/useMediaQuery'; import useMediaQuery from './hooks/useMediaQuery';
import { withInstall } from 'ant-design-vue/es/_util/type';
import { defaultSettingProps } from './defaultSettings'; import { defaultSettingProps } from './defaultSettings';
import { getPrefixCls, defaultRouteContext } from './RouteContext'; import { getPrefixCls, defaultRouteContext } from './RouteContext';
import type { BreadcrumbProps } from './RouteContext'; import type { BreadcrumbProps } from './RouteContext';
...@@ -56,6 +56,10 @@ export const basicLayoutProps = { ...@@ -56,6 +56,10 @@ export const basicLayoutProps = {
type: [Object, Function, Boolean] as PropType<WithFalse<BreadcrumbProps['itemRender']>>, type: [Object, Function, Boolean] as PropType<WithFalse<BreadcrumbProps['itemRender']>>,
default: () => {}, default: () => {},
}, },
headerContentRender: {
type: [Function, Object, Boolean] as PropType<WithFalse<() => CustomRender>>,
default: () => undefined,
},
headerRender: { headerRender: {
type: [Object, Function, Boolean] as PropType< type: [Object, Function, Boolean] as PropType<
WithFalse<(props: any /* HeaderProps */) => CustomRender> WithFalse<(props: any /* HeaderProps */) => CustomRender>
...@@ -76,6 +80,7 @@ export type BasicLayoutProps = Partial<ExtractPropTypes<typeof basicLayoutProps> ...@@ -76,6 +80,7 @@ export type BasicLayoutProps = Partial<ExtractPropTypes<typeof basicLayoutProps>
const ProLayout = defineComponent({ const ProLayout = defineComponent({
name: 'ProLayout', name: 'ProLayout',
props: basicLayoutProps,
// inheritAttrs: false, // inheritAttrs: false,
emits: [ emits: [
'update:collapsed', 'update:collapsed',
...@@ -87,7 +92,6 @@ const ProLayout = defineComponent({ ...@@ -87,7 +92,6 @@ const ProLayout = defineComponent({
'menuHeaderClick', 'menuHeaderClick',
'menuClick', 'menuClick',
], ],
props: basicLayoutProps,
setup(props, { emit, slots }) { setup(props, { emit, slots }) {
const refProps = toRefs(props); const refProps = toRefs(props);
const isTop = computed(() => props.layout === 'top'); const isTop = computed(() => props.layout === 'top');
...@@ -149,7 +153,7 @@ const ProLayout = defineComponent({ ...@@ -149,7 +153,7 @@ const ProLayout = defineComponent({
const headerRender = ( const headerRender = (
p: BasicLayoutProps & { p: BasicLayoutProps & {
hasSiderMenu: boolean; hasSiderMenu: boolean;
customHeaderRender: WithFalse<CustomRender>; headerRender: WithFalse<CustomRender>;
rightContentRender: WithFalse<CustomRender>; rightContentRender: WithFalse<CustomRender>;
}, },
matchMenuKeys?: string[], matchMenuKeys?: string[],
...@@ -159,14 +163,18 @@ const ProLayout = defineComponent({ ...@@ -159,14 +163,18 @@ const ProLayout = defineComponent({
} }
return <Header {...p} matchMenuKeys={matchMenuKeys || []} />; return <Header {...p} matchMenuKeys={matchMenuKeys || []} />;
}; };
const collapsedButtonRender =
const collapsedButtonRender = getPropsSlot(slots, props, 'collapsedButtonRender'); props.collapsedButtonRender === false
? false
: getPropsSlot(slots, props, 'collapsedButtonRender');
const headerContentRender = getPropsSlot(slots, props, 'headerContentRender');
const rightContentRender = getPropsSlot(slots, props, 'rightContentRender'); const rightContentRender = getPropsSlot(slots, props, 'rightContentRender');
const customHeaderRender = getPropsSlot(slots, props, 'headerRender'); const customHeaderRender = getPropsSlot(slots, props, 'headerRender');
const menuHeaderRender = getPropsSlot(slots, props, 'menuHeaderRender'); const menuHeaderRender = getPropsSlot(slots, props, 'menuHeaderRender');
const footerRender = getPropsSlot(slots, props, 'footerRender'); const footerRender = getPropsSlot(slots, props, 'footerRender');
// const menuRender = getPropsSlot(slots, props, 'menuRender'); // const menuRender = getPropsSlot(slots, props, 'menuRender');
const breadcrumbRender = props['breadcrumbRender'] || slots['breadcrumbRender']; const breadcrumbRender = props.breadcrumbRender || slots.breadcrumbRender;
const headerDom = computed(() => const headerDom = computed(() =>
headerRender( headerRender(
{ {
...@@ -178,9 +186,10 @@ const ProLayout = defineComponent({ ...@@ -178,9 +186,10 @@ const ProLayout = defineComponent({
onOpenKeys, onOpenKeys,
onSelect, onSelect,
onMenuHeaderClick, onMenuHeaderClick,
customHeaderRender,
rightContentRender, rightContentRender,
headerTitleRender: menuHeaderRender, headerTitleRender: menuHeaderRender,
headerContentRender,
headerRender: customHeaderRender,
theme: (props.navTheme || 'dark').toLocaleLowerCase().includes('dark') ? 'dark' : 'light', theme: (props.navTheme || 'dark').toLocaleLowerCase().includes('dark') ? 'dark' : 'light',
}, },
props.matchMenuKeys, props.matchMenuKeys,
...@@ -193,7 +202,7 @@ const ProLayout = defineComponent({ ...@@ -193,7 +202,7 @@ const ProLayout = defineComponent({
locale: refProps.locale.value || defaultRouteContext.locale, locale: refProps.locale.value || defaultRouteContext.locale,
breadcrumb: computed(() => { breadcrumb: computed(() => {
return { return {
...refProps.breadcrumb, ...props.breadcrumb,
itemRender: breadcrumbRender, itemRender: breadcrumbRender,
}; };
}), }),
......
@import 'ant-design-vue/es/style/themes/default.less';
@pro-layout-grid-content-prefix-cls: ~'@{ant-prefix}-pro-grid-content';
.@{pro-layout-grid-content-prefix-cls} {
width: 100%;
&.wide {
max-width: 1200px;
margin: 0 auto;
}
}
\ No newline at end of file
...@@ -58,6 +58,7 @@ export const HeaderView = defineComponent({ ...@@ -58,6 +58,7 @@ export const HeaderView = defineComponent({
const needFixedHeader = computed( const needFixedHeader = computed(
() => fixedHeader.value || context.fixedHeader || layout.value === 'mix', () => fixedHeader.value || context.fixedHeader || layout.value === 'mix',
); );
const isMix = computed(() => layout.value === 'mix');
const isTop = computed(() => layout.value === 'top'); const isTop = computed(() => layout.value === 'top');
const needSettingWidth = computed( const needSettingWidth = computed(
() => needFixedHeader.value && hasSiderMenu.value && !isTop.value && !isMobile.value, () => needFixedHeader.value && hasSiderMenu.value && !isTop.value && !isMobile.value,
...@@ -76,7 +77,11 @@ export const HeaderView = defineComponent({ ...@@ -76,7 +77,11 @@ export const HeaderView = defineComponent({
const renderContent = () => { const renderContent = () => {
let defaultDom = ( let defaultDom = (
<GlobalHeader {...props} onCollapse={onCollapse.value} menuData={clearMenuData.value}> <GlobalHeader {...props} onCollapse={onCollapse.value} menuData={clearMenuData.value}>
{props.headerContentRender && props.headerContentRender(props)} {!isMix.value
? props.headerContentRender && typeof props.headerContentRender === 'function'
? props.headerContentRender(props)
: props.headerContentRender
: null}
</GlobalHeader> </GlobalHeader>
); );
if (isTop.value && !isMobile.value) { if (isTop.value && !isMobile.value) {
......
...@@ -210,7 +210,7 @@ const defaultPageHeaderRender = ( ...@@ -210,7 +210,7 @@ const defaultPageHeaderRender = (
} }
const breadcrumb = restProps.breadcrumb || { const breadcrumb = restProps.breadcrumb || {
routes: unref(value.breadcrumb?.routes), routes: value.breadcrumb?.routes,
itemRender: value.breadcrumb?.itemRender, itemRender: value.breadcrumb?.itemRender,
}; };
// inject value // inject value
......
...@@ -190,12 +190,12 @@ class MenuUtil { ...@@ -190,12 +190,12 @@ class MenuUtil {
}; };
getMenuItem = (item: MenuDataItem) => { getMenuItem = (item: MenuDataItem) => {
const meta = Object.assign({}, item.meta); const meta = { ...item.meta };
const target = (meta.target || null) as string | null; const target = (meta.target || null) as string | null;
const hasUrl = isUrl(item.path); const hasUrl = isUrl(item.path);
const CustomTag: any = (target && 'a') || resolveComponent('router-link'); const CustomTag: any = (target && 'a') || resolveComponent('router-link');
const props = { to: { name: item.name } }; const props = { to: { name: item.name } };
const attrs = hasUrl || target ? { ...item.meta, href: item.path, target: target } : {}; const attrs = hasUrl || target ? { ...item.meta, href: item.path, target } : {};
const { prefixCls, locale } = this.props; const { prefixCls, locale } = this.props;
const menuTitle = (locale && locale(item.meta?.title)) || item.meta?.title; const menuTitle = (locale && locale(item.meta?.title)) || item.meta?.title;
......
...@@ -9,11 +9,11 @@ import 'ant-design-vue/es/layout/style'; ...@@ -9,11 +9,11 @@ import 'ant-design-vue/es/layout/style';
import Layout from 'ant-design-vue/es/layout'; import Layout from 'ant-design-vue/es/layout';
import 'ant-design-vue/es/menu/style'; import 'ant-design-vue/es/menu/style';
import Menu from 'ant-design-vue/es/menu'; import Menu from 'ant-design-vue/es/menu';
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue';
import BaseMenu, { baseMenuProps } from './BaseMenu'; import BaseMenu, { baseMenuProps } from './BaseMenu';
import { WithFalse, CustomRender } from '../typings'; import { WithFalse, CustomRender } from '../typings';
import { SiderProps } from './typings'; import { SiderProps } from './typings';
import { defaultSettingProps } from '../defaultSettings'; import { defaultSettingProps } from '../defaultSettings';
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue';
import { useRouteContext } from '../RouteContext'; import { useRouteContext } from '../RouteContext';
import { PropTypes, getMenuFirstChildren } from '../utils'; import { PropTypes, getMenuFirstChildren } from '../utils';
import './index.less'; import './index.less';
...@@ -124,7 +124,8 @@ export const defaultRenderLogoAndTitle = ( ...@@ -124,7 +124,8 @@ export const defaultRenderLogoAndTitle = (
if (typeof renderFunction === 'function') { if (typeof renderFunction === 'function') {
// when collapsed, no render title // when collapsed, no render title
return renderFunction(logoDom, props.collapsed ? null : titleDom, props); return renderFunction(logoDom, props.collapsed ? null : titleDom, props);
} else if (Array.isArray(renderFunction)) { }
if (Array.isArray(renderFunction)) {
return <>{renderFunction}</>; return <>{renderFunction}</>;
} }
if (layout === 'mix' && renderKey === 'menuHeaderRender') { if (layout === 'mix' && renderKey === 'menuHeaderRender') {
...@@ -172,8 +173,11 @@ const SiderMenu: FC<SiderMenuProps> = (props: SiderMenuProps) => { ...@@ -172,8 +173,11 @@ const SiderMenu: FC<SiderMenuProps> = (props: SiderMenuProps) => {
[`${baseClassName}-fixed`]: context.fixSiderbar, [`${baseClassName}-fixed`]: context.fixSiderbar,
}; };
}); });
const hasSide = computed(() => (props.layout === 'mix' && props.splitMenus) || false); const hasSide = computed(
() => ((props.layout === 'mix' || props.layout === 'side') && props.splitMenus) || false,
);
const flatMenuData = computed(() => { const flatMenuData = computed(() => {
console.log('context.selectedKeys[0]', context.selectedKeys[0]);
return (hasSide.value && getMenuFirstChildren(context.menuData, context.selectedKeys[0])) || []; return (hasSide.value && getMenuFirstChildren(context.menuData, context.selectedKeys[0])) || [];
}); });
// call menuHeaderRender // call menuHeaderRender
......
declare module '*.vue' { declare module '*.vue' {
import { DefineComponent } from 'vue' import { DefineComponent } from 'vue';
const component: DefineComponent<{}, {}, any>
export default component const component: DefineComponent<{}, {}, any>;
export default component;
} }
...@@ -13,9 +13,6 @@ const formatRelativePath = ( ...@@ -13,9 +13,6 @@ const formatRelativePath = (
): RouteRecordRaw[] => { ): RouteRecordRaw[] => {
// 计算路由绝对路径 // 计算路由绝对路径
return routes.map(route => { return routes.map(route => {
if (route.path.startsWith('/')) {
return route;
}
if (parent) { if (parent) {
route.path = `${parent.path || ''}/${route.path}`; route.path = `${parent.path || ''}/${route.path}`;
} else { } else {
...@@ -24,7 +21,7 @@ const formatRelativePath = ( ...@@ -24,7 +21,7 @@ const formatRelativePath = (
route.path = route.path.replace('//', '/'); route.path = route.path.replace('//', '/');
// format children routes // format children routes
if (route.children && route.children.length > 0) { if (route.children && route.children.length > 0) {
route.children = formatRelativePath(route.children, route); route.children = formatRelativePath(route.children, breadcrumb, route);
} }
breadcrumb[`${route.path}`] = route; breadcrumb[`${route.path}`] = route;
return route; return route;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment