| | |
| | | <template> |
| | | <div :class="getClass" :style="getStyle"> |
| | | <div :class="`${prefixCls}-image-wrapper`" :style="getImageWrapperStyle" @click="openModal"> |
| | | <div :class="`${prefixCls}-image-wrapper`" :style="getImageWrapperStyle" @click="openModal()"> |
| | | <div :class="`${prefixCls}-image-mask`" :style="getImageWrapperStyle"> |
| | | <Icon |
| | | icon="ant-design:cloud-upload-outlined" |
| | |
| | | {{ btnText ? btnText : t('component.cropper.selectImage') }} |
| | | </a-button> |
| | | |
| | | <CopperModal |
| | | <CropperModal |
| | | @register="register" |
| | | @upload-success="handleUploadSuccess" |
| | | :uploadApi="uploadApi" |
| | | :src="sourceValue" |
| | | :size="size" |
| | | /> |
| | | </div> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { |
| | | defineComponent, |
| | | computed, |
| | | CSSProperties, |
| | | unref, |
| | | ref, |
| | | watchEffect, |
| | | watch, |
| | | PropType, |
| | | } from 'vue'; |
| | | import CopperModal from './CopperModal.vue'; |
| | | import { useDesign } from '/@/hooks/web/useDesign'; |
| | | import { useModal } from '/@/components/Modal'; |
| | | import { useMessage } from '/@/hooks/web/useMessage'; |
| | | import { useI18n } from '/@/hooks/web/useI18n'; |
| | | import type { ButtonProps } from '/@/components/Button'; |
| | | <script lang="ts" setup> |
| | | import { computed, CSSProperties, unref, ref, watchEffect, watch, PropType } from 'vue'; |
| | | import CropperModal from './CropperModal.vue'; |
| | | import { useDesign } from '@/hooks/web/useDesign'; |
| | | import { useModal } from '@/components/Modal'; |
| | | import { useMessage } from '@/hooks/web/useMessage'; |
| | | import { useI18n } from '@/hooks/web/useI18n'; |
| | | import type { ButtonProps } from '@/components/Button'; |
| | | import Icon from '@/components/Icon/Icon.vue'; |
| | | |
| | | const props = { |
| | | defineOptions({ name: 'CropperAvatar' }); |
| | | |
| | | const props = defineProps({ |
| | | width: { type: [String, Number], default: '200px' }, |
| | | value: { type: String }, |
| | | showBtn: { type: Boolean, default: true }, |
| | | btnProps: { type: Object as PropType<ButtonProps> }, |
| | | btnText: { type: String, default: '' }, |
| | | uploadApi: { type: Function as PropType<({ file: Blob, name: string }) => Promise<void>> }, |
| | | }; |
| | | |
| | | export default defineComponent({ |
| | | name: 'CropperAvatar', |
| | | components: { CopperModal, Icon }, |
| | | props, |
| | | emits: ['update:value', 'change'], |
| | | setup(props, { emit, expose }) { |
| | | const sourceValue = ref(props.value || ''); |
| | | const { prefixCls } = useDesign('cropper-avatar'); |
| | | const [register, { openModal, closeModal }] = useModal(); |
| | | const { createMessage } = useMessage(); |
| | | const { t } = useI18n(); |
| | | |
| | | const getClass = computed(() => [prefixCls]); |
| | | |
| | | const getWidth = computed(() => `${props.width}`.replace(/px/, '') + 'px'); |
| | | |
| | | const getIconWidth = computed(() => parseInt(`${props.width}`.replace(/px/, '')) / 2 + 'px'); |
| | | |
| | | const getStyle = computed((): CSSProperties => ({ width: unref(getWidth) })); |
| | | |
| | | const getImageWrapperStyle = computed( |
| | | (): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) }), |
| | | ); |
| | | |
| | | watchEffect(() => { |
| | | sourceValue.value = props.value || ''; |
| | | }); |
| | | |
| | | watch( |
| | | () => sourceValue.value, |
| | | (v: string) => { |
| | | emit('update:value', v); |
| | | }, |
| | | ); |
| | | |
| | | function handleUploadSuccess({ source, data }) { |
| | | sourceValue.value = source; |
| | | emit('change', { source, data }); |
| | | createMessage.success(t('component.cropper.uploadSuccess')); |
| | | } |
| | | |
| | | expose({ openModal: openModal.bind(null, true), closeModal }); |
| | | |
| | | return { |
| | | t, |
| | | prefixCls, |
| | | register, |
| | | openModal: openModal as any, |
| | | getIconWidth, |
| | | sourceValue, |
| | | getClass, |
| | | getImageWrapperStyle, |
| | | getStyle, |
| | | handleUploadSuccess, |
| | | }; |
| | | uploadApi: { |
| | | type: Function as PropType<({ file, name }: { file: Blob; name: string }) => Promise<void>>, |
| | | }, |
| | | |
| | | size: { type: Number, default: 5 }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:value', 'change']); |
| | | |
| | | const sourceValue = ref(props.value || ''); |
| | | const { prefixCls } = useDesign('cropper-avatar'); |
| | | const [register, { openModal, closeModal }] = useModal(); |
| | | const { createMessage } = useMessage(); |
| | | const { t } = useI18n(); |
| | | |
| | | const getClass = computed(() => [prefixCls]); |
| | | |
| | | const getWidth = computed(() => `${props.width}`.replace(/px/, '') + 'px'); |
| | | |
| | | const getIconWidth = computed(() => parseInt(`${props.width}`.replace(/px/, '')) / 2 + 'px'); |
| | | |
| | | const getStyle = computed((): CSSProperties => ({ width: unref(getWidth) })); |
| | | |
| | | const getImageWrapperStyle = computed( |
| | | (): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) }), |
| | | ); |
| | | |
| | | watchEffect(() => { |
| | | sourceValue.value = props.value || ''; |
| | | }); |
| | | |
| | | watch( |
| | | () => sourceValue.value, |
| | | (v: string) => { |
| | | emit('update:value', v); |
| | | }, |
| | | ); |
| | | |
| | | function handleUploadSuccess({ source, data }) { |
| | | sourceValue.value = source; |
| | | emit('change', { source, data }); |
| | | createMessage.success(t('component.cropper.uploadSuccess')); |
| | | } |
| | | |
| | | defineExpose({ openModal: openModal.bind(null, true), closeModal }); |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |