Carson
2021-11-24 dc4b05272f67b5ea8a85cac15b11e14a76c2c1d6
提交 | 用户 | age
31ff05 1 <template>
4d8e39 2   <div :class="getClass" ref="wrapperRef">
551fe5 3     <PageHeader
V 4       :ghost="ghost"
9e3ada 5       :title="title"
8879ae 6       v-bind="omit($attrs, 'class')"
551fe5 7       ref="headerRef"
dc4b05 8       v-if="getShowHeader"
551fe5 9     >
31ff05 10       <template #default>
V 11         <template v-if="content">
12           {{ content }}
13         </template>
9edc28 14         <slot name="headerContent" v-else></slot>
31ff05 15       </template>
V 16       <template #[item]="data" v-for="item in getHeaderSlots">
b1f317 17         <slot :name="item" v-bind="data || {}"></slot>
31ff05 18       </template>
V 19     </PageHeader>
566280 20
4d8e39 21     <div class="overflow-hidden" :class="getContentClass" :style="getContentStyle" ref="contentRef">
9edc28 22       <slot></slot>
31ff05 23     </div>
566280 24
31ff05 25     <PageFooter v-if="getShowFooter" ref="footerRef">
V 26       <template #left>
9edc28 27         <slot name="leftFooter"></slot>
31ff05 28       </template>
V 29       <template #right>
9edc28 30         <slot name="rightFooter"></slot>
31ff05 31       </template>
V 32     </PageFooter>
33   </div>
34 </template>
35 <script lang="ts">
da12da 36   import { CSSProperties, PropType, provide } from 'vue';
31ff05 37
4d8e39 38   import { defineComponent, computed, watch, ref, unref } from 'vue';
31ff05 39   import PageFooter from './PageFooter.vue';
V 40
41   import { useDesign } from '/@/hooks/web/useDesign';
42   import { propTypes } from '/@/utils/propTypes';
43   import { omit } from 'lodash-es';
44   import { PageHeader } from 'ant-design-vue';
9de6ac 45   import { useContentHeight } from '/@/hooks/web/useContentHeight';
da12da 46   import { PageWrapperFixedHeightKey } from '..';
33cd8f 47
31ff05 48   export default defineComponent({
V 49     name: 'PageWrapper',
50     components: { PageFooter, PageHeader },
b93f20 51     inheritAttrs: false,
31ff05 52     props: {
9e3ada 53       title: propTypes.string,
31ff05 54       dense: propTypes.bool,
V 55       ghost: propTypes.bool,
56       content: propTypes.string,
57       contentStyle: {
58         type: Object as PropType<CSSProperties>,
59       },
de5bf7 60       contentBackground: propTypes.bool,
31ff05 61       contentFullHeight: propTypes.bool,
551fe5 62       contentClass: propTypes.string,
V 63       fixedHeight: propTypes.bool,
6717fe 64       upwardSpace: propTypes.oneOfType([propTypes.number, propTypes.string]).def(0),
31ff05 65     },
8879ae 66     setup(props, { slots, attrs }) {
9de6ac 67       const wrapperRef = ref(null);
L 68       const headerRef = ref(null);
69       const contentRef = ref(null);
70       const footerRef = ref(null);
4d8e39 71       const { prefixCls } = useDesign('page-wrapper');
L 72
da12da 73       provide(
74         PageWrapperFixedHeightKey,
56a966 75         computed(() => props.fixedHeight),
da12da 76       );
77
9de6ac 78       const getIsContentFullHeight = computed(() => {
L 79         return props.contentFullHeight;
4d8e39 80       });
L 81
6717fe 82       const getUpwardSpace = computed(() => props.upwardSpace);
9de6ac 83       const { redoHeight, setCompensation, contentHeight } = useContentHeight(
L 84         getIsContentFullHeight,
4d8e39 85         wrapperRef,
9de6ac 86         [headerRef, footerRef],
56a966 87         [contentRef],
6717fe 88         getUpwardSpace,
4d8e39 89       );
9de6ac 90       setCompensation({ useLayoutFooter: true, elements: [footerRef] });
31ff05 91
V 92       const getClass = computed(() => {
93         return [
94           prefixCls,
95           {
96             [`${prefixCls}--dense`]: props.dense,
97           },
8879ae 98           attrs.class ?? {},
31ff05 99         ];
V 100       });
101
dc4b05 102       const getShowHeader = computed(
C 103         () => props.content || slots?.headerContent || props.title || getHeaderSlots.value.length,
104       );
105
31ff05 106       const getShowFooter = computed(() => slots?.leftFooter || slots?.rightFooter);
V 107
108       const getHeaderSlots = computed(() => {
109         return Object.keys(omit(slots, 'default', 'leftFooter', 'rightFooter', 'headerContent'));
110       });
111
566280 112       const getContentStyle = computed((): CSSProperties => {
V 113         const { contentFullHeight, contentStyle, fixedHeight } = props;
114         if (!contentFullHeight) {
115           return { ...contentStyle };
31ff05 116         }
4d8e39 117
L 118         const height = `${unref(contentHeight)}px`;
566280 119         return {
V 120           ...contentStyle,
121           minHeight: height,
122           ...(fixedHeight ? { height } : {}),
123         };
124       });
5b8eb4 125
V 126       const getContentClass = computed(() => {
127         const { contentBackground, contentClass } = props;
128         return [
129           `${prefixCls}-content`,
130           contentClass,
131           {
132             [`${prefixCls}-content-bg`]: contentBackground,
133           },
134         ];
135       });
31ff05 136
V 137       watch(
9de6ac 138         () => [getShowFooter.value],
6392b7 139         () => {
4d8e39 140           redoHeight();
31ff05 141         },
V 142         {
53867a 143           flush: 'post',
31ff05 144           immediate: true,
56a966 145         },
31ff05 146       );
V 147
148       return {
149         getContentStyle,
4d8e39 150         wrapperRef,
31ff05 151         headerRef,
4d8e39 152         contentRef,
L 153         footerRef,
31ff05 154         getClass,
V 155         getHeaderSlots,
156         prefixCls,
dc4b05 157         getShowHeader,
31ff05 158         getShowFooter,
V 159         omit,
5b8eb4 160         getContentClass,
31ff05 161       };
V 162     },
163   });
164 </script>
165 <style lang="less">
166   @prefix-cls: ~'@{namespace}-page-wrapper';
167
168   .@{prefix-cls} {
169     position: relative;
170
fcff2c 171     .@{prefix-cls}-content {
8a1406 172       margin: 16px;
fcff2c 173     }
53867a 174
31ff05 175     .ant-page-header {
V 176       &:empty {
177         padding: 0;
178       }
179     }
180
5b8eb4 181     &-content-bg {
2cdf2c 182       background-color: @component-background;
5b8eb4 183     }
V 184
31ff05 185     &--dense {
V 186       .@{prefix-cls}-content {
187         margin: 0;
188       }
189     }
190   }
191 </style>