Commit 1c1755cf5b4ada7263c05ddf4105abb52a2abb2f
1 parent
639520ad
fix(modal): ensure that the full screen height is calculated correctly
Showing
25 changed files
with
116 additions
and
118 deletions
CHANGELOG.zh_CN.md
... | ... | @@ -2,9 +2,15 @@ |
2 | 2 | |
3 | 3 | ### ✨ Features |
4 | 4 | |
5 | -- `Cropper` 头像裁剪新增圆形裁剪功能 | |
6 | -- 新增头像上传组件 | |
7 | -- `useDrawer`新增`closeDrawer`函数 | |
5 | +- **CropperImage** `Cropper` 头像裁剪新增圆形裁剪功能 | |
6 | +- **CropperAvatar** 新增头像上传组件 | |
7 | +- **Drawer** `useDrawer`新增`closeDrawer`函数 | |
8 | + | |
9 | +### 🐛 Bug Fixes | |
10 | + | |
11 | +- **Modal** 修复全屏高度计算错误 | |
12 | +- **PageWrapper** 修复高度计算问题 | |
13 | +- 修复后台模式下,Iframe 路由错误 | |
8 | 14 | |
9 | 15 | ## 2.4.2(2021-06-10) |
10 | 16 | ... | ... |
src/components/Drawer/src/BasicDrawer.vue
... | ... | @@ -163,7 +163,7 @@ |
163 | 163 | |
164 | 164 | function setDrawerProps(props: Partial<DrawerProps>): void { |
165 | 165 | // Keep the last setDrawerProps |
166 | - propsRef.value = deepMerge((unref(propsRef) as any) || {}, props); | |
166 | + propsRef.value = deepMerge(unref(propsRef), props); | |
167 | 167 | |
168 | 168 | if (Reflect.has(props, 'visible')) { |
169 | 169 | visibleRef.value = !!props.visible; | ... | ... |
src/components/Drawer/src/useDrawer.ts
... | ... | @@ -5,7 +5,6 @@ import type { |
5 | 5 | DrawerProps, |
6 | 6 | UseDrawerInnerReturnType, |
7 | 7 | } from './typing'; |
8 | - | |
9 | 8 | import { |
10 | 9 | ref, |
11 | 10 | getCurrentInstance, |
... | ... | @@ -16,11 +15,9 @@ import { |
16 | 15 | toRaw, |
17 | 16 | computed, |
18 | 17 | } from 'vue'; |
19 | - | |
20 | 18 | import { isProdMode } from '/@/utils/env'; |
21 | 19 | import { isFunction } from '/@/utils/is'; |
22 | 20 | import { tryOnUnmounted } from '@vueuse/core'; |
23 | - | |
24 | 21 | import { isEqual } from 'lodash-es'; |
25 | 22 | import { error } from '/@/utils/log'; |
26 | 23 | ... | ... |
src/components/Modal/index.ts
1 | +import { withInstall } from '/@/utils'; | |
1 | 2 | import './src/index.less'; |
2 | -import BasicModal from './src/BasicModal.vue'; | |
3 | +import basicModal from './src/BasicModal.vue'; | |
3 | 4 | |
4 | -export { BasicModal }; | |
5 | +export const BasicModal = withInstall(basicModal); | |
5 | 6 | export { useModalContext } from './src/hooks/useModalContext'; |
6 | 7 | export { useModal, useModalInner } from './src/hooks/useModal'; |
7 | -export * from './src/types'; | |
8 | +export * from './src/typing'; | ... | ... |
src/components/Modal/src/BasicModal.vue
... | ... | @@ -49,7 +49,7 @@ |
49 | 49 | </Modal> |
50 | 50 | </template> |
51 | 51 | <script lang="ts"> |
52 | - import type { ModalProps, ModalMethods } from './types'; | |
52 | + import type { ModalProps, ModalMethods } from './typing'; | |
53 | 53 | |
54 | 54 | import { |
55 | 55 | defineComponent, |
... | ... | @@ -62,20 +62,17 @@ |
62 | 62 | getCurrentInstance, |
63 | 63 | nextTick, |
64 | 64 | } from 'vue'; |
65 | - | |
66 | 65 | import Modal from './components/Modal'; |
67 | 66 | import ModalWrapper from './components/ModalWrapper.vue'; |
68 | 67 | import ModalClose from './components/ModalClose.vue'; |
69 | 68 | import ModalFooter from './components/ModalFooter.vue'; |
70 | 69 | import ModalHeader from './components/ModalHeader.vue'; |
71 | - | |
72 | 70 | import { isFunction } from '/@/utils/is'; |
73 | 71 | import { deepMerge } from '/@/utils'; |
74 | - | |
75 | 72 | import { basicProps } from './props'; |
76 | 73 | import { useFullScreen } from './hooks/useModalFullScreen'; |
77 | - | |
78 | 74 | import { omit } from 'lodash-es'; |
75 | + | |
79 | 76 | export default defineComponent({ |
80 | 77 | name: 'BasicModal', |
81 | 78 | components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader }, |
... | ... | @@ -189,7 +186,7 @@ |
189 | 186 | */ |
190 | 187 | function setModalProps(props: Partial<ModalProps>): void { |
191 | 188 | // Keep the last setModalProps |
192 | - propsRef.value = deepMerge(unref(propsRef) || {}, props); | |
189 | + propsRef.value = deepMerge(unref(propsRef), props); | |
193 | 190 | if (!Reflect.has(props, 'visible')) return; |
194 | 191 | visibleRef.value = !!props.visible; |
195 | 192 | } | ... | ... |
src/components/Modal/src/components/Modal.tsx
src/components/Modal/src/components/ModalClose.vue
... | ... | @@ -2,7 +2,6 @@ |
2 | 2 | <div :class="getClass"> |
3 | 3 | <template v-if="canFullscreen"> |
4 | 4 | <FullscreenExitOutlined role="full" @click="handleFullScreen" v-if="fullScreen" /> |
5 | - | |
6 | 5 | <FullscreenOutlined role="close" @click="handleFullScreen" v-else /> |
7 | 6 | </template> |
8 | 7 | <CloseOutlined @click="handleCancel" /> |
... | ... | @@ -12,14 +11,13 @@ |
12 | 11 | import { defineComponent, computed } from 'vue'; |
13 | 12 | import { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined } from '@ant-design/icons-vue'; |
14 | 13 | import { useDesign } from '/@/hooks/web/useDesign'; |
15 | - import { propTypes } from '/@/utils/propTypes'; | |
16 | 14 | |
17 | 15 | export default defineComponent({ |
18 | 16 | name: 'ModalClose', |
19 | 17 | components: { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined }, |
20 | 18 | props: { |
21 | - canFullscreen: propTypes.bool.def(true), | |
22 | - fullScreen: propTypes.bool, | |
19 | + canFullscreen: { type: Boolean, default: true }, | |
20 | + fullScreen: { type: Boolean }, | |
23 | 21 | }, |
24 | 22 | emits: ['cancel', 'fullscreen'], |
25 | 23 | setup(props, { emit }) { |
... | ... | @@ -38,6 +36,7 @@ |
38 | 36 | function handleCancel(e: Event) { |
39 | 37 | emit('cancel', e); |
40 | 38 | } |
39 | + | |
41 | 40 | function handleFullScreen(e: Event) { |
42 | 41 | e?.stopPropagation(); |
43 | 42 | e?.preventDefault(); | ... | ... |
src/components/Modal/src/components/ModalFooter.vue
src/components/Modal/src/components/ModalHeader.vue
... | ... | @@ -8,7 +8,6 @@ |
8 | 8 | import { defineComponent } from 'vue'; |
9 | 9 | import { BasicTitle } from '/@/components/Basic'; |
10 | 10 | |
11 | - import { propTypes } from '/@/utils/propTypes'; | |
12 | 11 | export default defineComponent({ |
13 | 12 | name: 'BasicModalHeader', |
14 | 13 | components: { BasicTitle }, |
... | ... | @@ -16,7 +15,7 @@ |
16 | 15 | helpMessage: { |
17 | 16 | type: [String, Array] as PropType<string | string[]>, |
18 | 17 | }, |
19 | - title: propTypes.string, | |
18 | + title: { type: String }, | |
20 | 19 | }, |
21 | 20 | }); |
22 | 21 | </script> | ... | ... |
src/components/Modal/src/components/ModalWrapper.vue
... | ... | @@ -6,9 +6,7 @@ |
6 | 6 | </ScrollContainer> |
7 | 7 | </template> |
8 | 8 | <script lang="ts"> |
9 | - import type { ModalWrapperProps } from '../types'; | |
10 | 9 | import type { CSSProperties } from 'vue'; |
11 | - | |
12 | 10 | import { |
13 | 11 | defineComponent, |
14 | 12 | computed, |
... | ... | @@ -20,31 +18,31 @@ |
20 | 18 | nextTick, |
21 | 19 | onUnmounted, |
22 | 20 | } from 'vue'; |
23 | - | |
24 | 21 | import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn'; |
25 | 22 | import { ScrollContainer } from '/@/components/Container'; |
26 | - | |
27 | - import { propTypes } from '/@/utils/propTypes'; | |
28 | 23 | import { createModalContext } from '../hooks/useModalContext'; |
24 | + import { useMutationObserver } from '@vueuse/core'; | |
25 | + | |
26 | + const props = { | |
27 | + loading: { type: Boolean }, | |
28 | + useWrapper: { type: Boolean, default: true }, | |
29 | + modalHeaderHeight: { type: Number, default: 57 }, | |
30 | + modalFooterHeight: { type: Number, default: 74 }, | |
31 | + minHeight: { type: Number, default: 200 }, | |
32 | + height: { type: Number }, | |
33 | + footerOffset: { type: Number, default: 0 }, | |
34 | + visible: { type: Boolean }, | |
35 | + fullScreen: { type: Boolean }, | |
36 | + loadingTip: { type: String }, | |
37 | + }; | |
29 | 38 | |
30 | 39 | export default defineComponent({ |
31 | 40 | name: 'ModalWrapper', |
32 | 41 | components: { ScrollContainer }, |
33 | 42 | inheritAttrs: false, |
34 | - props: { | |
35 | - loading: propTypes.bool, | |
36 | - useWrapper: propTypes.bool.def(true), | |
37 | - modalHeaderHeight: propTypes.number.def(57), | |
38 | - modalFooterHeight: propTypes.number.def(74), | |
39 | - minHeight: propTypes.number.def(200), | |
40 | - height: propTypes.number, | |
41 | - footerOffset: propTypes.number.def(0), | |
42 | - visible: propTypes.bool, | |
43 | - fullScreen: propTypes.bool, | |
44 | - loadingTip: propTypes.string, | |
45 | - }, | |
43 | + props, | |
46 | 44 | emits: ['height-change', 'ext-height'], |
47 | - setup(props: ModalWrapperProps, { emit }) { | |
45 | + setup(props, { emit }) { | |
48 | 46 | const wrapperRef = ref<ComponentRef>(null); |
49 | 47 | const spinRef = ref<ElRef>(null); |
50 | 48 | const realHeightRef = ref(0); |
... | ... | @@ -56,6 +54,17 @@ |
56 | 54 | |
57 | 55 | useWindowSizeFn(setModalHeight.bind(null, false)); |
58 | 56 | |
57 | + useMutationObserver( | |
58 | + spinRef, | |
59 | + () => { | |
60 | + setModalHeight(); | |
61 | + }, | |
62 | + { | |
63 | + attributes: true, | |
64 | + subtree: true, | |
65 | + } | |
66 | + ); | |
67 | + | |
59 | 68 | createModalContext({ |
60 | 69 | redoModalHeight: setModalHeight, |
61 | 70 | }); |
... | ... | @@ -63,8 +72,7 @@ |
63 | 72 | const spinStyle = computed((): CSSProperties => { |
64 | 73 | return { |
65 | 74 | minHeight: `${props.minHeight}px`, |
66 | - // padding 28 | |
67 | - maxHeight: `${unref(realHeightRef)}px`, | |
75 | + [props.fullScreen ? 'height' : 'maxHeight']: `${unref(realHeightRef)}px`, | |
68 | 76 | }; |
69 | 77 | }); |
70 | 78 | |
... | ... | @@ -87,7 +95,6 @@ |
87 | 95 | onMounted(() => { |
88 | 96 | const { modalHeaderHeight, modalFooterHeight } = props; |
89 | 97 | emit('ext-height', modalHeaderHeight + modalFooterHeight); |
90 | - // listenElResize(); | |
91 | 98 | }); |
92 | 99 | |
93 | 100 | onUnmounted(() => { | ... | ... |
src/components/Modal/src/hooks/useModal.ts
... | ... | @@ -4,8 +4,7 @@ import type { |
4 | 4 | ModalProps, |
5 | 5 | ReturnMethods, |
6 | 6 | UseModalInnerReturnType, |
7 | -} from '../types'; | |
8 | - | |
7 | +} from '../typing'; | |
9 | 8 | import { |
10 | 9 | ref, |
11 | 10 | onUnmounted, |
... | ... | @@ -20,10 +19,10 @@ import { isProdMode } from '/@/utils/env'; |
20 | 19 | import { isFunction } from '/@/utils/is'; |
21 | 20 | import { isEqual } from 'lodash-es'; |
22 | 21 | import { tryOnUnmounted } from '@vueuse/core'; |
23 | - | |
24 | 22 | import { error } from '/@/utils/log'; |
25 | 23 | import { computed } from 'vue'; |
26 | -const dataTransferRef = reactive<any>({}); | |
24 | + | |
25 | +const dataTransfer = reactive<any>({}); | |
27 | 26 | |
28 | 27 | const visibleData = reactive<{ [key: number]: boolean }>({}); |
29 | 28 | |
... | ... | @@ -31,29 +30,31 @@ const visibleData = reactive<{ [key: number]: boolean }>({}); |
31 | 30 | * @description: Applicable to independent modal and call outside |
32 | 31 | */ |
33 | 32 | export function useModal(): UseModalReturnType { |
34 | - const modalRef = ref<Nullable<ModalMethods>>(null); | |
35 | - const loadedRef = ref<Nullable<boolean>>(false); | |
36 | - const uidRef = ref<string>(''); | |
33 | + const modal = ref<Nullable<ModalMethods>>(null); | |
34 | + const loaded = ref<Nullable<boolean>>(false); | |
35 | + const uid = ref<string>(''); | |
37 | 36 | |
38 | 37 | function register(modalMethod: ModalMethods, uuid: string) { |
39 | - uidRef.value = uuid; | |
40 | - | |
38 | + if (!getCurrentInstance()) { | |
39 | + throw new Error('useModal() can only be used inside setup() or functional components!'); | |
40 | + } | |
41 | + uid.value = uuid; | |
41 | 42 | isProdMode() && |
42 | 43 | onUnmounted(() => { |
43 | - modalRef.value = null; | |
44 | - loadedRef.value = false; | |
45 | - dataTransferRef[unref(uidRef)] = null; | |
44 | + modal.value = null; | |
45 | + loaded.value = false; | |
46 | + dataTransfer[unref(uid)] = null; | |
46 | 47 | }); |
47 | - if (unref(loadedRef) && isProdMode() && modalMethod === unref(modalRef)) return; | |
48 | + if (unref(loaded) && isProdMode() && modalMethod === unref(modal)) return; | |
48 | 49 | |
49 | - modalRef.value = modalMethod; | |
50 | + modal.value = modalMethod; | |
50 | 51 | modalMethod.emitVisible = (visible: boolean, uid: number) => { |
51 | 52 | visibleData[uid] = visible; |
52 | 53 | }; |
53 | 54 | } |
54 | 55 | |
55 | 56 | const getInstance = () => { |
56 | - const instance = unref(modalRef); | |
57 | + const instance = unref(modal); | |
57 | 58 | if (!instance) { |
58 | 59 | error('useModal instance is undefined!'); |
59 | 60 | } |
... | ... | @@ -66,7 +67,7 @@ export function useModal(): UseModalReturnType { |
66 | 67 | }, |
67 | 68 | |
68 | 69 | getVisible: computed((): boolean => { |
69 | - return visibleData[~~unref(uidRef)]; | |
70 | + return visibleData[~~unref(uid)]; | |
70 | 71 | }), |
71 | 72 | |
72 | 73 | redoModalHeight: () => { |
... | ... | @@ -79,15 +80,15 @@ export function useModal(): UseModalReturnType { |
79 | 80 | }); |
80 | 81 | |
81 | 82 | if (!data) return; |
82 | - | |
83 | + const id = unref(uid); | |
83 | 84 | if (openOnSet) { |
84 | - dataTransferRef[unref(uidRef)] = null; | |
85 | - dataTransferRef[unref(uidRef)] = toRaw(data); | |
85 | + dataTransfer[id] = null; | |
86 | + dataTransfer[id] = toRaw(data); | |
86 | 87 | return; |
87 | 88 | } |
88 | - const equal = isEqual(toRaw(dataTransferRef[unref(uidRef)]), toRaw(data)); | |
89 | + const equal = isEqual(toRaw(dataTransfer[id]), toRaw(data)); | |
89 | 90 | if (!equal) { |
90 | - dataTransferRef[unref(uidRef)] = toRaw(data); | |
91 | + dataTransfer[id] = toRaw(data); | |
91 | 92 | } |
92 | 93 | }, |
93 | 94 | |
... | ... | @@ -103,9 +104,6 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => { |
103 | 104 | const currentInstance = getCurrentInstance(); |
104 | 105 | const uidRef = ref<string>(''); |
105 | 106 | |
106 | - // currentInstall.type.emits = [...currentInstall.type.emits, 'register']; | |
107 | - // Object.assign(currentInstall.type.emits, ['register']); | |
108 | - | |
109 | 107 | const getInstance = () => { |
110 | 108 | const instance = unref(modalInstanceRef); |
111 | 109 | if (!instance) { |
... | ... | @@ -125,7 +123,7 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => { |
125 | 123 | }; |
126 | 124 | |
127 | 125 | watchEffect(() => { |
128 | - const data = dataTransferRef[unref(uidRef)]; | |
126 | + const data = dataTransfer[unref(uidRef)]; | |
129 | 127 | if (!data) return; |
130 | 128 | if (!callbackFn || !isFunction(callbackFn)) return; |
131 | 129 | nextTick(() => { | ... | ... |
src/components/Modal/src/hooks/useModalFullScreen.ts
... | ... | @@ -12,7 +12,6 @@ export function useFullScreen(context: UseFullScreenContext) { |
12 | 12 | |
13 | 13 | const getWrapClassName = computed(() => { |
14 | 14 | const clsName = unref(context.wrapClassName) || ''; |
15 | - | |
16 | 15 | return unref(fullScreenRef) ? `fullscreen-modal ${clsName} ` : unref(clsName); |
17 | 16 | }); |
18 | 17 | ... | ... |
src/components/Modal/src/props.ts
1 | 1 | import type { PropType, CSSProperties } from 'vue'; |
2 | +import type { ModalWrapperProps } from './typing'; | |
2 | 3 | import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'; |
3 | - | |
4 | 4 | import { useI18n } from '/@/hooks/web/useI18n'; |
5 | -import { propTypes, VueNode } from '/@/utils/propTypes'; | |
6 | -import type { ModalWrapperProps } from './types'; | |
5 | + | |
7 | 6 | const { t } = useI18n(); |
8 | 7 | |
9 | 8 | export const modalProps = { |
10 | - visible: propTypes.bool, | |
11 | - scrollTop: propTypes.bool.def(true), | |
12 | - height: propTypes.number, | |
13 | - minHeight: propTypes.number, | |
9 | + visible: { type: Boolean }, | |
10 | + scrollTop: { type: Boolean, default: true }, | |
11 | + height: { type: Number }, | |
12 | + minHeight: { type: Number }, | |
14 | 13 | // open drag |
15 | - draggable: propTypes.bool.def(true), | |
16 | - centered: propTypes.bool, | |
17 | - cancelText: propTypes.string.def(t('common.cancelText')), | |
18 | - okText: propTypes.string.def(t('common.okText')), | |
14 | + draggable: { type: Boolean, default: true }, | |
15 | + centered: { type: Boolean }, | |
16 | + cancelText: { type: String, default: t('common.cancelText') }, | |
17 | + okText: { type: String, default: t('common.okText') }, | |
19 | 18 | |
20 | 19 | closeFunc: Function as PropType<() => Promise<boolean>>, |
21 | 20 | }; |
22 | 21 | |
23 | 22 | export const basicProps = Object.assign({}, modalProps, { |
24 | - defaultFullscreen: propTypes.bool, | |
23 | + defaultFullscreen: { type: Boolean }, | |
25 | 24 | // Can it be full screen |
26 | - canFullscreen: propTypes.bool.def(true), | |
25 | + canFullscreen: { type: Boolean, default: true }, | |
27 | 26 | // After enabling the wrapper, the bottom can be increased in height |
28 | - wrapperFooterOffset: propTypes.number.def(0), | |
27 | + wrapperFooterOffset: { type: Number, default: 0 }, | |
29 | 28 | // Warm reminder message |
30 | 29 | helpMessage: [String, Array] as PropType<string | string[]>, |
31 | 30 | // Whether to setting wrapper |
32 | - useWrapper: propTypes.bool.def(true), | |
33 | - loading: propTypes.bool, | |
34 | - loadingTip: propTypes.string, | |
31 | + useWrapper: { type: Boolean, default: true }, | |
32 | + loading: { type: Boolean }, | |
33 | + loadingTip: { type: String }, | |
35 | 34 | /** |
36 | 35 | * @description: Show close button |
37 | 36 | */ |
38 | - showCancelBtn: propTypes.bool.def(true), | |
37 | + showCancelBtn: { type: Boolean, default: true }, | |
39 | 38 | /** |
40 | 39 | * @description: Show confirmation button |
41 | 40 | */ |
42 | - showOkBtn: propTypes.bool.def(true), | |
41 | + showOkBtn: { type: Boolean, default: true }, | |
43 | 42 | |
44 | 43 | wrapperProps: Object as PropType<Partial<ModalWrapperProps>>, |
45 | 44 | |
... | ... | @@ -47,38 +46,38 @@ export const basicProps = Object.assign({}, modalProps, { |
47 | 46 | |
48 | 47 | bodyStyle: Object as PropType<CSSProperties>, |
49 | 48 | |
50 | - closable: propTypes.bool.def(true), | |
49 | + closable: { type: Boolean, default: true }, | |
51 | 50 | |
52 | 51 | closeIcon: Object as PropType<VueNode>, |
53 | 52 | |
54 | - confirmLoading: propTypes.bool, | |
53 | + confirmLoading: { type: Boolean }, | |
55 | 54 | |
56 | - destroyOnClose: propTypes.bool, | |
55 | + destroyOnClose: { type: Boolean }, | |
57 | 56 | |
58 | 57 | footer: Object as PropType<VueNode>, |
59 | 58 | |
60 | 59 | getContainer: Function as PropType<() => any>, |
61 | 60 | |
62 | - mask: propTypes.bool.def(true), | |
61 | + mask: { type: Boolean, default: true }, | |
63 | 62 | |
64 | - maskClosable: propTypes.bool.def(true), | |
65 | - keyboard: propTypes.bool.def(true), | |
63 | + maskClosable: { type: Boolean, default: true }, | |
64 | + keyboard: { type: Boolean, default: true }, | |
66 | 65 | |
67 | 66 | maskStyle: Object as PropType<CSSProperties>, |
68 | 67 | |
69 | - okType: propTypes.string.def('primary'), | |
68 | + okType: { type: String, default: 'primary' }, | |
70 | 69 | |
71 | 70 | okButtonProps: Object as PropType<ButtonProps>, |
72 | 71 | |
73 | 72 | cancelButtonProps: Object as PropType<ButtonProps>, |
74 | 73 | |
75 | - title: propTypes.string, | |
74 | + title: { type: String }, | |
76 | 75 | |
77 | - visible: propTypes.bool, | |
76 | + visible: { type: Boolean }, | |
78 | 77 | |
79 | 78 | width: [String, Number] as PropType<string | number>, |
80 | 79 | |
81 | - wrapClassName: propTypes.string, | |
80 | + wrapClassName: { type: String }, | |
82 | 81 | |
83 | - zIndex: propTypes.number, | |
82 | + zIndex: { type: Number }, | |
84 | 83 | }); | ... | ... |
src/components/Modal/src/types.ts renamed to src/components/Modal/src/typing.ts
src/components/Qrcode/index.ts
src/components/Qrcode/src/Qrcode.vue
... | ... | @@ -8,7 +8,7 @@ |
8 | 8 | import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus'; |
9 | 9 | import { toDataURL } from 'qrcode'; |
10 | 10 | import { downloadByUrl } from '/@/utils/file/download'; |
11 | - import { QrcodeDoneEventParams } from './types'; | |
11 | + import { QrcodeDoneEventParams } from './typing'; | |
12 | 12 | |
13 | 13 | export default defineComponent({ |
14 | 14 | name: 'QrCode', | ... | ... |
src/components/Qrcode/src/drawCanvas.ts
1 | 1 | import { toCanvas } from 'qrcode'; |
2 | 2 | import type { QRCodeRenderersOptions } from 'qrcode'; |
3 | -import { RenderQrCodeParams, ContentType } from './types'; | |
3 | +import { RenderQrCodeParams, ContentType } from './typing'; | |
4 | 4 | export const renderQrCode = ({ canvas, content, width = 0, options = {} }: RenderQrCodeParams) => { |
5 | 5 | // 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率 |
6 | 6 | options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content); | ... | ... |
src/components/Qrcode/src/drawLogo.ts
1 | 1 | import { isString } from '/@/utils/is'; |
2 | -import { RenderQrCodeParams, LogoType } from './types'; | |
2 | +import { RenderQrCodeParams, LogoType } from './typing'; | |
3 | 3 | export const drawLogo = ({ canvas, logo }: RenderQrCodeParams) => { |
4 | 4 | if (!logo) { |
5 | 5 | return new Promise((resolve) => { |
6 | 6 | resolve((canvas as HTMLCanvasElement).toDataURL()); |
7 | 7 | }); |
8 | 8 | } |
9 | - | |
10 | 9 | const canvasWidth = (canvas as HTMLCanvasElement).width; |
11 | 10 | const { |
12 | 11 | logoSize = 0.15, | ... | ... |
src/components/Qrcode/src/qrcodePlus.ts
src/components/Qrcode/src/toCanvas.ts
1 | 1 | import { renderQrCode } from './drawCanvas'; |
2 | 2 | import { drawLogo } from './drawLogo'; |
3 | -import { RenderQrCodeParams } from './types'; | |
3 | +import { RenderQrCodeParams } from './typing'; | |
4 | 4 | export const toCanvas = (options: RenderQrCodeParams) => { |
5 | 5 | return renderQrCode(options) |
6 | 6 | .then(() => { | ... | ... |
src/components/Qrcode/src/types.ts renamed to src/components/Qrcode/src/typing.ts
src/layouts/default/header/components/lock/LockModal.vue
src/views/demo/comp/drawer/index.vue
... | ... | @@ -8,10 +8,7 @@ |
8 | 8 | <Alert message="自适应高度/显示footer" show-icon /> |
9 | 9 | <a-button type="primary" class="my-4" @click="openDrawer3(true)"> 打开Drawer </a-button> |
10 | 10 | |
11 | - <Alert | |
12 | - message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式" | |
13 | - show-icon | |
14 | - /> | |
11 | + <Alert message="内外数据交互" show-icon /> | |
15 | 12 | <a-button type="primary" class="my-4" @click="send"> 打开Drawer并传递数据 </a-button> |
16 | 13 | <Alert message="详情页模式" show-icon /> |
17 | 14 | <a-button type="primary" class="my-4" @click="openDrawer5(true)"> 打开详情Drawer </a-button> | ... | ... |
src/views/demo/comp/modal/index.vue
... | ... | @@ -14,10 +14,7 @@ |
14 | 14 | <Alert message="自适应高度" show-icon /> |
15 | 15 | <a-button type="primary" class="my-4" @click="openModal3"> 打开弹窗 </a-button> |
16 | 16 | |
17 | - <Alert | |
18 | - message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式" | |
19 | - show-icon | |
20 | - /> | |
17 | + <Alert message="内外数据交互" show-icon /> | |
21 | 18 | <a-button type="primary" class="my-4" @click="send"> 打开弹窗并传递数据 </a-button> |
22 | 19 | |
23 | 20 | <Modal1 @register="register1" :minHeight="100" /> | ... | ... |
types/global.d.ts
1 | 1 | import type { |
2 | 2 | ComponentRenderProxy, |
3 | 3 | VNode, |
4 | + VNodeChild, | |
4 | 5 | ComponentPublicInstance, |
5 | 6 | FunctionalComponent, |
6 | 7 | PropType as VuePropType, |
... | ... | @@ -23,6 +24,7 @@ declare global { |
23 | 24 | |
24 | 25 | // vue |
25 | 26 | declare type PropType<T> = VuePropType<T>; |
27 | + declare type VueNode = VNodeChild | JSX.Element; | |
26 | 28 | |
27 | 29 | export type Writable<T> = { |
28 | 30 | -readonly [P in keyof T]: T[P]; | ... | ... |