Commit 7eb0fb1655b38387991f3a9d00658fcba961881e

Authored by xingyu
1 parent 91abae88

fix: close modal

yudao-ui-admin-vue3/src/components/Cropper/src/CopperModal.vue
1 <template> 1 <template>
2 - <Dialog  
3 - v-model="dialogVisible"  
4 - :title="t('cropper.modalTitle')"  
5 - width="800px"  
6 - maxHeight="380px"  
7 - :canFullscreen="false"  
8 - >  
9 - <div :class="prefixCls">  
10 - <div :class="`${prefixCls}-left`">  
11 - <div :class="`${prefixCls}-cropper`">  
12 - <CropperImage  
13 - v-if="src"  
14 - :src="src"  
15 - height="300px"  
16 - :circled="circled"  
17 - @cropend="handleCropend"  
18 - @ready="handleReady"  
19 - />  
20 - </div> 2 + <div>
  3 + <Dialog
  4 + v-model="dialogVisible"
  5 + :title="t('cropper.modalTitle')"
  6 + width="800px"
  7 + maxHeight="380px"
  8 + :canFullscreen="false"
  9 + >
  10 + <div :class="prefixCls">
  11 + <div :class="`${prefixCls}-left`">
  12 + <div :class="`${prefixCls}-cropper`">
  13 + <CropperImage
  14 + v-if="src"
  15 + :src="src"
  16 + height="300px"
  17 + :circled="circled"
  18 + @cropend="handleCropend"
  19 + @ready="handleReady"
  20 + />
  21 + </div>
21 22
22 - <div :class="`${prefixCls}-toolbar`">  
23 - <el-upload :fileList="[]" accept="image/*" :beforeUpload="handleBeforeUpload">  
24 - <el-tooltip :content="t('cropper.selectImage')" placement="bottom">  
25 - <XButton preIcon="ant-design:upload-outlined" type="primary" />  
26 - </el-tooltip>  
27 - </el-upload>  
28 - <el-space>  
29 - <el-tooltip :content="t('cropper.btn_reset')" placement="bottom">  
30 - <XButton  
31 - type="primary"  
32 - preIcon="ant-design:reload-outlined"  
33 - size="small"  
34 - :disabled="!src"  
35 - @click="handlerToolbar('reset')"  
36 - />  
37 - </el-tooltip>  
38 - <el-tooltip :content="t('cropper.btn_rotate_left')" placement="bottom">  
39 - <XButton  
40 - type="primary"  
41 - preIcon="ant-design:rotate-left-outlined"  
42 - size="small"  
43 - :disabled="!src"  
44 - @click="handlerToolbar('rotate', -45)"  
45 - />  
46 - </el-tooltip>  
47 - <el-tooltip :content="t('cropper.btn_rotate_right')" placement="bottom">  
48 - <XButton  
49 - type="primary"  
50 - preIcon="ant-design:rotate-right-outlined"  
51 - size="small"  
52 - :disabled="!src"  
53 - @click="handlerToolbar('rotate', 45)"  
54 - />  
55 - </el-tooltip>  
56 - <el-tooltip :content="t('cropper.btn_scale_x')" placement="bottom">  
57 - <XButton  
58 - type="primary"  
59 - preIcon="vaadin:arrows-long-h"  
60 - size="small"  
61 - :disabled="!src"  
62 - @click="handlerToolbar('scaleX')"  
63 - />  
64 - </el-tooltip>  
65 - <el-tooltip :content="t('cropper.btn_scale_y')" placement="bottom">  
66 - <XButton  
67 - type="primary"  
68 - preIcon="vaadin:arrows-long-v"  
69 - size="small"  
70 - :disabled="!src"  
71 - @click="handlerToolbar('scaleY')"  
72 - />  
73 - </el-tooltip>  
74 - <el-tooltip :content="t('cropper.btn_zoom_in')" placement="bottom">  
75 - <XButton  
76 - type="primary"  
77 - preIcon="ant-design:zoom-in-outlined"  
78 - size="small"  
79 - :disabled="!src"  
80 - @click="handlerToolbar('zoom', 0.1)"  
81 - />  
82 - </el-tooltip>  
83 - <el-tooltip :content="t('cropper.btn_zoom_out')" placement="bottom">  
84 - <XButton  
85 - type="primary"  
86 - preIcon="ant-design:zoom-out-outlined"  
87 - size="small"  
88 - :disabled="!src"  
89 - @click="handlerToolbar('zoom', -0.1)"  
90 - />  
91 - </el-tooltip>  
92 - </el-space>  
93 - </div>  
94 - </div>  
95 - <div :class="`${prefixCls}-right`">  
96 - <div :class="`${prefixCls}-preview`">  
97 - <img :src="previewSource" v-if="previewSource" :alt="t('cropper.preview')" /> 23 + <div :class="`${prefixCls}-toolbar`">
  24 + <el-upload :fileList="[]" accept="image/*" :beforeUpload="handleBeforeUpload">
  25 + <el-tooltip :content="t('cropper.selectImage')" placement="bottom">
  26 + <XButton preIcon="ant-design:upload-outlined" type="primary" />
  27 + </el-tooltip>
  28 + </el-upload>
  29 + <el-space>
  30 + <el-tooltip :content="t('cropper.btn_reset')" placement="bottom">
  31 + <XButton
  32 + type="primary"
  33 + preIcon="ant-design:reload-outlined"
  34 + size="small"
  35 + :disabled="!src"
  36 + @click="handlerToolbar('reset')"
  37 + />
  38 + </el-tooltip>
  39 + <el-tooltip :content="t('cropper.btn_rotate_left')" placement="bottom">
  40 + <XButton
  41 + type="primary"
  42 + preIcon="ant-design:rotate-left-outlined"
  43 + size="small"
  44 + :disabled="!src"
  45 + @click="handlerToolbar('rotate', -45)"
  46 + />
  47 + </el-tooltip>
  48 + <el-tooltip :content="t('cropper.btn_rotate_right')" placement="bottom">
  49 + <XButton
  50 + type="primary"
  51 + preIcon="ant-design:rotate-right-outlined"
  52 + size="small"
  53 + :disabled="!src"
  54 + @click="handlerToolbar('rotate', 45)"
  55 + />
  56 + </el-tooltip>
  57 + <el-tooltip :content="t('cropper.btn_scale_x')" placement="bottom">
  58 + <XButton
  59 + type="primary"
  60 + preIcon="vaadin:arrows-long-h"
  61 + size="small"
  62 + :disabled="!src"
  63 + @click="handlerToolbar('scaleX')"
  64 + />
  65 + </el-tooltip>
  66 + <el-tooltip :content="t('cropper.btn_scale_y')" placement="bottom">
  67 + <XButton
  68 + type="primary"
  69 + preIcon="vaadin:arrows-long-v"
  70 + size="small"
  71 + :disabled="!src"
  72 + @click="handlerToolbar('scaleY')"
  73 + />
  74 + </el-tooltip>
  75 + <el-tooltip :content="t('cropper.btn_zoom_in')" placement="bottom">
  76 + <XButton
  77 + type="primary"
  78 + preIcon="ant-design:zoom-in-outlined"
  79 + size="small"
  80 + :disabled="!src"
  81 + @click="handlerToolbar('zoom', 0.1)"
  82 + />
  83 + </el-tooltip>
  84 + <el-tooltip :content="t('cropper.btn_zoom_out')" placement="bottom">
  85 + <XButton
  86 + type="primary"
  87 + preIcon="ant-design:zoom-out-outlined"
  88 + size="small"
  89 + :disabled="!src"
  90 + @click="handlerToolbar('zoom', -0.1)"
  91 + />
  92 + </el-tooltip>
  93 + </el-space>
  94 + </div>
98 </div> 95 </div>
99 - <template v-if="previewSource">  
100 - <div :class="`${prefixCls}-group`">  
101 - <el-avatar :src="previewSource" size="large" />  
102 - <el-avatar :src="previewSource" :size="48" />  
103 - <el-avatar :src="previewSource" :size="64" />  
104 - <el-avatar :src="previewSource" :size="80" /> 96 + <div :class="`${prefixCls}-right`">
  97 + <div :class="`${prefixCls}-preview`">
  98 + <img :src="previewSource" v-if="previewSource" :alt="t('cropper.preview')" />
105 </div> 99 </div>
106 - </template> 100 + <template v-if="previewSource">
  101 + <div :class="`${prefixCls}-group`">
  102 + <el-avatar :src="previewSource" size="large" />
  103 + <el-avatar :src="previewSource" :size="48" />
  104 + <el-avatar :src="previewSource" :size="64" />
  105 + <el-avatar :src="previewSource" :size="80" />
  106 + </div>
  107 + </template>
  108 + </div>
107 </div> 109 </div>
108 - </div>  
109 - <template #footer>  
110 - <el-button type="primary" @click="handleOk">{{ t('cropper.okText') }}</el-button>  
111 - </template>  
112 - </Dialog> 110 + <template #footer>
  111 + <el-button type="primary" @click="handleOk">{{ t('cropper.okText') }}</el-button>
  112 + </template>
  113 + </Dialog>
  114 + </div>
113 </template> 115 </template>
114 <script setup lang="ts"> 116 <script setup lang="ts">
115 import { useDesign } from '@/hooks/web/useDesign' 117 import { useDesign } from '@/hooks/web/useDesign'
@@ -173,7 +175,6 @@ function handlerToolbar(event: string, arg?: number) { @@ -173,7 +175,6 @@ function handlerToolbar(event: string, arg?: number) {
173 async function handleOk() { 175 async function handleOk() {
174 const blob = dataURLtoBlob(previewSource.value) 176 const blob = dataURLtoBlob(previewSource.value)
175 emit('uploadSuccess', { source: previewSource.value, data: blob, filename: filename }) 177 emit('uploadSuccess', { source: previewSource.value, data: blob, filename: filename })
176 - closeModal()  
177 } 178 }
178 function openModal() { 179 function openModal() {
179 dialogVisible.value = true 180 dialogVisible.value = true
yudao-ui-admin-vue3/src/components/Cropper/src/CropperAvatar.vue
@@ -4,7 +4,11 @@ @@ -4,7 +4,11 @@
4 <el-button :class="`${prefixCls}-upload-btn`" @click="open()" v-if="showBtn"> 4 <el-button :class="`${prefixCls}-upload-btn`" @click="open()" v-if="showBtn">
5 {{ btnText ? btnText : t('cropper.selectImage') }} 5 {{ btnText ? btnText : t('cropper.selectImage') }}
6 </el-button> 6 </el-button>
7 - <CopperModal ref="cropperModel" @upload-success="handleUploadSuccess" :srcValue="sourceValue" /> 7 + <CopperModal
  8 + ref="cropperModelRef"
  9 + @upload-success="handleUploadSuccess"
  10 + :srcValue="sourceValue"
  11 + />
8 </div> 12 </div>
9 </template> 13 </template>
10 <script setup lang="ts"> 14 <script setup lang="ts">
@@ -29,7 +33,7 @@ const prefixCls = getPrefixCls(&#39;cropper-avatar&#39;) @@ -29,7 +33,7 @@ const prefixCls = getPrefixCls(&#39;cropper-avatar&#39;)
29 const message = useMessage() 33 const message = useMessage()
30 const { t } = useI18n() 34 const { t } = useI18n()
31 35
32 -const cropperModel = ref() 36 +const cropperModelRef = ref()
33 37
34 watchEffect(() => { 38 watchEffect(() => {
35 sourceValue.value = props.value 39 sourceValue.value = props.value
@@ -49,8 +53,15 @@ function handleUploadSuccess({ source, data, filename }) { @@ -49,8 +53,15 @@ function handleUploadSuccess({ source, data, filename }) {
49 } 53 }
50 54
51 function open() { 55 function open() {
52 - cropperModel.value.openModal() 56 + cropperModelRef.value.openModal()
53 } 57 }
  58 +function close() {
  59 + cropperModelRef.value.closeModal()
  60 +}
  61 +defineExpose({
  62 + open,
  63 + close
  64 +})
54 </script> 65 </script>
55 <style lang="scss" scoped> 66 <style lang="scss" scoped>
56 $prefix-cls: #{$namespace}--cropper-avatar; 67 $prefix-cls: #{$namespace}--cropper-avatar;
yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue
1 <template> 1 <template>
2 <div class="change-avatar"> 2 <div class="change-avatar">
3 <CropperAvatar 3 <CropperAvatar
  4 + ref="cropperRef"
4 :value="avatar" 5 :value="avatar"
5 :showBtn="false" 6 :showBtn="false"
6 @change="handelUpload" 7 @change="handelUpload"
@@ -10,7 +11,7 @@ @@ -10,7 +11,7 @@
10 </div> 11 </div>
11 </template> 12 </template>
12 <script setup lang="ts"> 13 <script setup lang="ts">
13 -import { computed } from 'vue' 14 +import { computed, ref } from 'vue'
14 import { propTypes } from '@/utils/propTypes' 15 import { propTypes } from '@/utils/propTypes'
15 import { CropperAvatar } from '@/components/Cropper' 16 import { CropperAvatar } from '@/components/Cropper'
16 import { uploadAvatarApi } from '@/api/system/user/profile' 17 import { uploadAvatarApi } from '@/api/system/user/profile'
@@ -21,8 +22,10 @@ const avatar = computed(() =&gt; { @@ -21,8 +22,10 @@ const avatar = computed(() =&gt; {
21 return props.img 22 return props.img
22 }) 23 })
23 24
  25 +const cropperRef = ref()
24 const handelUpload = async ({ data }) => { 26 const handelUpload = async ({ data }) => {
25 await uploadAvatarApi({ avatarFile: data }) 27 await uploadAvatarApi({ avatarFile: data })
  28 + cropperRef.value.close()
26 } 29 }
27 </script> 30 </script>
28 31