| | |
| | | @close="onClose" |
| | | > |
| | | <template #titleToolbar> |
| | | <slot name="titleToolbar" /> |
| | | <slot name="titleToolbar"></slot> |
| | | </template> |
| | | </DrawerHeader> |
| | | </template> |
| | | <template v-else #title> |
| | | <slot name="title"></slot> |
| | | </template> |
| | | |
| | | <ScrollContainer |
| | | :style="getScrollContentStyle" |
| | | v-loading="getLoading" |
| | | :loading-tip="loadingText || t('component.drawer.loadingText')" |
| | | :loading-tip="loadingText || t('common.loadingText')" |
| | | > |
| | | <slot /> |
| | | <slot></slot> |
| | | </ScrollContainer> |
| | | <DrawerFooter v-bind="getProps" @close="onClose" @ok="handleOk" :height="getFooterHeight"> |
| | | <template #[item]="data" v-for="item in Object.keys($slots)"> |
| | | <slot :name="item" v-bind="data" /> |
| | | <slot :name="item" v-bind="data || {}"></slot> |
| | | </template> |
| | | </DrawerFooter> |
| | | </Drawer> |
| | | </template> |
| | | <script lang="ts"> |
| | | import type { DrawerInstance, DrawerProps } from './types'; |
| | | import type { DrawerInstance, DrawerProps } from './typing'; |
| | | import type { CSSProperties } from 'vue'; |
| | | |
| | | import { |
| | | defineComponent, |
| | | ref, |
| | | computed, |
| | | watchEffect, |
| | | watch, |
| | | unref, |
| | | nextTick, |
| | |
| | | getCurrentInstance, |
| | | } from 'vue'; |
| | | import { Drawer } from 'ant-design-vue'; |
| | | |
| | | import { useI18n } from '/@/hooks/web/useI18n'; |
| | | |
| | | import { isFunction, isNumber } from '/@/utils/is'; |
| | | import { deepMerge } from '/@/utils'; |
| | | import DrawerFooter from './components/DrawerFooter.vue'; |
| | | import DrawerHeader from './components/DrawerHeader.vue'; |
| | | import { ScrollContainer } from '/@/components/Container'; |
| | | |
| | | import { basicProps } from './props'; |
| | | import { useDesign } from '/@/hooks/web/useDesign'; |
| | | import { useAttrs } from '/@/hooks/core/useAttrs'; |
| | | |
| | | export default defineComponent({ |
| | | inheritAttrs: false, |
| | | components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader }, |
| | | inheritAttrs: false, |
| | | props: basicProps, |
| | | emits: ['visible-change', 'ok', 'close', 'register'], |
| | | setup(props, { emit }) { |
| | |
| | | |
| | | instance && emit('register', drawerInstance, instance.uid); |
| | | |
| | | const getMergeProps = computed( |
| | | (): DrawerProps => { |
| | | return deepMerge(toRaw(props), unref(propsRef)); |
| | | } |
| | | ); |
| | | const getMergeProps = computed((): DrawerProps => { |
| | | return deepMerge(toRaw(props), unref(propsRef)); |
| | | }); |
| | | |
| | | const getProps = computed( |
| | | (): DrawerProps => { |
| | | const opt = { |
| | | placement: 'right', |
| | | ...unref(attrs), |
| | | ...unref(getMergeProps), |
| | | visible: unref(visibleRef), |
| | | }; |
| | | opt.title = undefined; |
| | | const { isDetail, width, wrapClassName, getContainer } = opt; |
| | | if (isDetail) { |
| | | if (!width) { |
| | | opt.width = '100%'; |
| | | } |
| | | const detailCls = `${prefixCls}__detail`; |
| | | opt.wrapClassName = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls; |
| | | |
| | | if (!getContainer) { |
| | | // TODO type error? |
| | | opt.getContainer = `.${prefixVar}-layout-content` as any; |
| | | } |
| | | const getProps = computed((): DrawerProps => { |
| | | const opt = { |
| | | placement: 'right', |
| | | ...unref(attrs), |
| | | ...unref(getMergeProps), |
| | | visible: unref(visibleRef), |
| | | }; |
| | | opt.title = undefined; |
| | | const { isDetail, width, wrapClassName, getContainer } = opt; |
| | | if (isDetail) { |
| | | if (!width) { |
| | | opt.width = '100%'; |
| | | } |
| | | return opt as DrawerProps; |
| | | } |
| | | ); |
| | | const detailCls = `${prefixCls}__detail`; |
| | | opt.class = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls; |
| | | |
| | | const getBindValues = computed( |
| | | (): DrawerProps => { |
| | | return { |
| | | ...attrs, |
| | | ...unref(getProps), |
| | | }; |
| | | if (!getContainer) { |
| | | // TODO type error? |
| | | opt.getContainer = `.${prefixVar}-layout-content` as any; |
| | | } |
| | | } |
| | | ); |
| | | return opt as DrawerProps; |
| | | }); |
| | | |
| | | const getBindValues = computed((): DrawerProps => { |
| | | return { |
| | | ...attrs, |
| | | ...unref(getProps), |
| | | }; |
| | | }); |
| | | |
| | | // Custom implementation of the bottom button, |
| | | const getFooterHeight = computed(() => { |
| | |
| | | return `0px`; |
| | | }); |
| | | |
| | | const getScrollContentStyle = computed( |
| | | (): CSSProperties => { |
| | | const footerHeight = unref(getFooterHeight); |
| | | return { |
| | | position: 'relative', |
| | | height: `calc(100% - ${footerHeight})`, |
| | | }; |
| | | } |
| | | ); |
| | | const getScrollContentStyle = computed((): CSSProperties => { |
| | | const footerHeight = unref(getFooterHeight); |
| | | return { |
| | | position: 'relative', |
| | | height: `calc(100% - ${footerHeight})`, |
| | | }; |
| | | }); |
| | | |
| | | const getLoading = computed(() => { |
| | | return !!unref(getProps)?.loading; |
| | | }); |
| | | |
| | | watchEffect(() => { |
| | | visibleRef.value = props.visible; |
| | | }); |
| | | watch( |
| | | () => props.visible, |
| | | (newVal, oldVal) => { |
| | | if (newVal !== oldVal) visibleRef.value = newVal; |
| | | }, |
| | | { deep: true }, |
| | | ); |
| | | |
| | | watch( |
| | | () => visibleRef.value, |
| | |
| | | emit('visible-change', visible); |
| | | instance && drawerInstance.emitVisible?.(visible, instance.uid); |
| | | }); |
| | | } |
| | | }, |
| | | ); |
| | | |
| | | // Cancel event |
| | |
| | | |
| | | function setDrawerProps(props: Partial<DrawerProps>): void { |
| | | // Keep the last setDrawerProps |
| | | propsRef.value = deepMerge(unref(propsRef) || {}, props); |
| | | propsRef.value = deepMerge(unref(propsRef) || ({} as any), props); |
| | | |
| | | if (Reflect.has(props, 'visible')) { |
| | | visibleRef.value = !!props.visible; |
| | |
| | | onClose, |
| | | t, |
| | | prefixCls, |
| | | getMergeProps, |
| | | getMergeProps: getMergeProps as any, |
| | | getScrollContentStyle, |
| | | getProps, |
| | | getProps: getProps as any, |
| | | getLoading, |
| | | getBindValues, |
| | | getFooterHeight, |
| | |
| | | }); |
| | | </script> |
| | | <style lang="less"> |
| | | @import (reference) '../../../design/index.less'; |
| | | @header-height: 60px; |
| | | @detail-header-height: 40px; |
| | | @prefix-cls: ~'@{namespace}-basic-drawer'; |
| | |
| | | .ant-drawer-body { |
| | | height: calc(100% - @header-height); |
| | | padding: 0; |
| | | background-color: @background-color-dark; |
| | | background-color: @component-background; |
| | | |
| | | .scrollbar__wrap { |
| | | padding: 16px !important; |
| | | margin-bottom: 0 !important; |
| | | } |
| | | |
| | | > .scrollbar > .scrollbar__bar.is-horizontal { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | |