mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2025-12-31 09:05:27 +08:00
前端和后端源码,合并到一个git仓库中,方便用户下载,避免前后端不匹配的问题
This commit is contained in:
7
jeecgboot-vue3/src/components/Page/index.ts
Normal file
7
jeecgboot-vue3/src/components/Page/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { withInstall } from '/@/utils';
|
||||
|
||||
import pageFooter from './src/PageFooter.vue';
|
||||
import pageWrapper from './src/PageWrapper.vue';
|
||||
|
||||
export const PageFooter = withInstall(pageFooter);
|
||||
export const PageWrapper = withInstall(pageWrapper);
|
||||
1
jeecgboot-vue3/src/components/Page/injectionKey.ts
Normal file
1
jeecgboot-vue3/src/components/Page/injectionKey.ts
Normal file
@ -0,0 +1 @@
|
||||
export const PageWrapperFixedHeightKey = 'PageWrapperFixedHeight';
|
||||
49
jeecgboot-vue3/src/components/Page/src/PageFooter.vue
Normal file
49
jeecgboot-vue3/src/components/Page/src/PageFooter.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div :class="prefixCls" :style="{ width: getCalcContentWidth }">
|
||||
<div :class="`${prefixCls}__left`">
|
||||
<slot name="left"></slot>
|
||||
</div>
|
||||
<slot></slot>
|
||||
<div :class="`${prefixCls}__right`">
|
||||
<slot name="right"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PageFooter',
|
||||
inheritAttrs: false,
|
||||
setup() {
|
||||
const { prefixCls } = useDesign('page-footer');
|
||||
const { getCalcContentWidth } = useMenuSetting();
|
||||
return { prefixCls, getCalcContentWidth };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-page-footer';
|
||||
|
||||
.@{prefix-cls} {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: @page-footer-z-index;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
padding: 0 24px;
|
||||
line-height: 44px;
|
||||
background-color: @component-background;
|
||||
border-top: 1px solid @border-color-base;
|
||||
box-shadow: 0 -6px 16px -8px rgba(0, 0, 0, 0.08), 0 -9px 28px 0 rgba(0, 0, 0, 0.05), 0 -12px 48px 16px rgba(0, 0, 0, 0.03);
|
||||
transition: width 0.2s;
|
||||
|
||||
&__left {
|
||||
flex: 1 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
186
jeecgboot-vue3/src/components/Page/src/PageWrapper.vue
Normal file
186
jeecgboot-vue3/src/components/Page/src/PageWrapper.vue
Normal file
@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<div :class="getClass" ref="wrapperRef">
|
||||
<PageHeader
|
||||
:ghost="ghost"
|
||||
:title="title"
|
||||
v-bind="omit($attrs, 'class')"
|
||||
ref="headerRef"
|
||||
v-if="content || $slots.headerContent || title || getHeaderSlots.length"
|
||||
>
|
||||
<template #default>
|
||||
<template v-if="content">
|
||||
{{ content }}
|
||||
</template>
|
||||
<slot name="headerContent" v-else></slot>
|
||||
</template>
|
||||
<template #[item]="data" v-for="item in getHeaderSlots">
|
||||
<slot :name="item" v-bind="data || {}"></slot>
|
||||
</template>
|
||||
</PageHeader>
|
||||
|
||||
<div class="overflow-hidden" :class="getContentClass" :style="getContentStyle" ref="contentRef">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<PageFooter v-if="getShowFooter" ref="footerRef">
|
||||
<template #left>
|
||||
<slot name="leftFooter"></slot>
|
||||
</template>
|
||||
<template #right>
|
||||
<slot name="rightFooter"></slot>
|
||||
</template>
|
||||
</PageFooter>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { CSSProperties, PropType, provide } from 'vue';
|
||||
|
||||
import { defineComponent, computed, watch, ref, unref } from 'vue';
|
||||
import PageFooter from './PageFooter.vue';
|
||||
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { omit } from 'lodash-es';
|
||||
import { PageHeader } from 'ant-design-vue';
|
||||
import { useContentHeight } from '/@/hooks/web/useContentHeight';
|
||||
import { PageWrapperFixedHeightKey } from '../injectionKey';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PageWrapper',
|
||||
components: { PageFooter, PageHeader },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
title: propTypes.string,
|
||||
dense: propTypes.bool,
|
||||
ghost: propTypes.bool,
|
||||
content: propTypes.string,
|
||||
contentStyle: {
|
||||
type: Object as PropType<CSSProperties>,
|
||||
},
|
||||
contentBackground: propTypes.bool,
|
||||
contentFullHeight: propTypes.bool,
|
||||
contentClass: propTypes.string,
|
||||
fixedHeight: propTypes.bool,
|
||||
upwardSpace: propTypes.oneOfType([propTypes.number, propTypes.string]).def(0),
|
||||
},
|
||||
setup(props, { slots, attrs }) {
|
||||
const wrapperRef = ref(null);
|
||||
const headerRef = ref(null);
|
||||
const contentRef = ref(null);
|
||||
const footerRef = ref(null);
|
||||
const { prefixCls } = useDesign('page-wrapper');
|
||||
|
||||
provide(
|
||||
PageWrapperFixedHeightKey,
|
||||
computed(() => props.fixedHeight)
|
||||
);
|
||||
|
||||
const getIsContentFullHeight = computed(() => {
|
||||
return props.contentFullHeight;
|
||||
});
|
||||
|
||||
const getUpwardSpace = computed(() => props.upwardSpace);
|
||||
const { redoHeight, setCompensation, contentHeight } = useContentHeight(
|
||||
getIsContentFullHeight,
|
||||
wrapperRef,
|
||||
[headerRef, footerRef],
|
||||
[contentRef],
|
||||
getUpwardSpace
|
||||
);
|
||||
setCompensation({ useLayoutFooter: true, elements: [footerRef] });
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--dense`]: props.dense,
|
||||
},
|
||||
attrs.class ?? {},
|
||||
];
|
||||
});
|
||||
|
||||
const getShowFooter = computed(() => slots?.leftFooter || slots?.rightFooter);
|
||||
|
||||
const getHeaderSlots = computed(() => {
|
||||
return Object.keys(omit(slots, 'default', 'leftFooter', 'rightFooter', 'headerContent'));
|
||||
});
|
||||
|
||||
const getContentStyle = computed((): CSSProperties => {
|
||||
const { contentFullHeight, contentStyle, fixedHeight } = props;
|
||||
if (!contentFullHeight) {
|
||||
return { ...contentStyle };
|
||||
}
|
||||
|
||||
const height = `${unref(contentHeight)}px`;
|
||||
return {
|
||||
...contentStyle,
|
||||
minHeight: height,
|
||||
...(fixedHeight ? { height } : {}),
|
||||
};
|
||||
});
|
||||
|
||||
const getContentClass = computed(() => {
|
||||
const { contentBackground, contentClass } = props;
|
||||
return [
|
||||
`${prefixCls}-content`,
|
||||
contentClass,
|
||||
{
|
||||
[`${prefixCls}-content-bg`]: contentBackground,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [getShowFooter.value],
|
||||
() => {
|
||||
redoHeight();
|
||||
},
|
||||
{
|
||||
flush: 'post',
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
getContentStyle,
|
||||
wrapperRef,
|
||||
headerRef,
|
||||
contentRef,
|
||||
footerRef,
|
||||
getClass,
|
||||
getHeaderSlots,
|
||||
prefixCls,
|
||||
getShowFooter,
|
||||
omit,
|
||||
getContentClass,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
@prefix-cls: ~'@{namespace}-page-wrapper';
|
||||
|
||||
.@{prefix-cls} {
|
||||
position: relative;
|
||||
|
||||
.@{prefix-cls}-content {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
.ant-page-header {
|
||||
&:empty {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-content-bg {
|
||||
background-color: @component-background;
|
||||
}
|
||||
|
||||
&--dense {
|
||||
.@{prefix-cls}-content {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user