From b96ea0753bfd769693a368cf1e3d8316688c0dcb Mon Sep 17 00:00:00 2001 From: 无木 <netfan@foxmail.com> Date: 星期六, 03 七月 2021 23:12:54 +0800 Subject: [PATCH] feat(avatar-cropper): more props added --- src/components/Cropper/src/CropperAvatar.vue | 76 +++++++++++++++++++++++-- src/views/demo/page/account/setting/BaseSetting.vue | 34 +++++++--- src/views/demo/comp/cropper/index.vue | 11 ++- CHANGELOG.zh_CN.md | 5 + 4 files changed, 104 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md index e95797b..7b53e80 100644 --- a/CHANGELOG.zh_CN.md +++ b/CHANGELOG.zh_CN.md @@ -7,6 +7,11 @@ - 澧炲姞`ignoreRoute`鐢ㄤ簬鍦╜ROUTE_MAPPING`鎴朻BACK`鏉冮檺妯″紡涓嬩粎鐢熸垚鑿滃崟 - 澧炲姞`hidePathForChildren`閰嶇疆锛屾爣璇嗕负瀛愰」鐩敓鎴愯彍鍗曟椂蹇界暐鏈骇`path` - **TableAction** 鏂板`tooltip`閰嶇疆锛屽彲浠ヤ负鎸夐挳澧炲姞 tooltip 鎻愮ず +- **CropperAvatar** + - 鏂板`value`鐢ㄤ簬璁剧疆褰撳墠澶村儚 + - 鏂板`onChange`鐢ㄤ簬鎺ュ彈澶村儚鍓骞朵笂浼犳垚鍔熶簨浠� + - 鏂板`btnText`銆乣btnProps` 鐢ㄤ簬鑷畾涔変笂浼犳寜閽枃妗堝拰灞炴�� + - 涓哄壀瑁乣Modal`鍐呯殑鎿嶄綔鎸夐挳娣诲姞宸ュ叿鎻愮ず ### 馃悰 Bug Fixes diff --git a/src/components/Cropper/src/CropperAvatar.vue b/src/components/Cropper/src/CropperAvatar.vue index 54744ac..6739be0 100644 --- a/src/components/Cropper/src/CropperAvatar.vue +++ b/src/components/Cropper/src/CropperAvatar.vue @@ -1,33 +1,59 @@ <template> <div :class="getClass" :style="getStyle"> <div :class="`${prefixCls}-image-wrapper`" :style="getImageWrapperStyle" @click="openModal"> + <div :class="`${prefixCls}-image-mask`" :style="getImageWrapperStyle"> + <Icon + icon="ant-design:cloud-upload-outlined" + :size="getIconWidth" + :style="getImageWrapperStyle" + color="#d6d6d6" + /> + </div> <img :src="sourceValue" v-if="sourceValue" alt="avatar" /> </div> - <a-button :class="`${prefixCls}-upload-btn`" @click="openModal"> - {{ t('component.cropper.selectImage') }} + <a-button + :class="`${prefixCls}-upload-btn`" + @click="openModal" + v-if="showBtn" + v-bind="btnProps" + > + {{ btnText ? btnText : t('component.cropper.selectImage') }} </a-button> - <CopperModal @register="register" @uploadSuccess="handleUploadSuccess" :uploadApi="uploadApi" /> + + <CopperModal + @register="register" + @uploadSuccess="handleUploadSuccess" + :uploadApi="uploadApi" + :src="sourceValue" + /> </div> </template> <script lang="ts"> - import { defineComponent, computed, CSSProperties, unref, ref } from 'vue'; + import { defineComponent, computed, CSSProperties, unref, ref, watchEffect, watch } 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'; + import Icon from '/@/components/Icon'; const props = { width: { type: [String, Number], default: '200px' }, + value: { type: String }, + showBtn: { type: Boolean, default: true }, + btnProps: { type: Object as ButtonProps }, + btnText: { type: String, default: '' }, uploadApi: { type: Function as PropType<({ file: Blob, name: string }) => Promise<void>> }, }; export default defineComponent({ name: 'CropperAvatar', - components: { CopperModal }, + components: { CopperModal, Icon }, props, - setup(props) { - const sourceValue = ref(''); + emits: ['update:value', 'change'], + setup(props, { emit }) { + const sourceValue = ref(props.value || ''); const { prefixCls } = useDesign('cropper-avatar'); const [register, { openModal }] = useModal(); const { createMessage } = useMessage(); @@ -37,14 +63,28 @@ 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 }) { sourceValue.value = source; + emit('change', source); createMessage.success(t('component.cropper.uploadSuccess')); } @@ -53,6 +93,7 @@ prefixCls, register, openModal, + getIconWidth, sourceValue, getClass, getImageWrapperStyle, @@ -82,6 +123,27 @@ } } + &-image-mask { + opacity: 0; + position: absolute; + width: inherit; + height: inherit; + border-radius: inherit; + border: inherit; + background: rgba(0, 0, 0, 0.4); + cursor: pointer; + -webkit-transition: opacity 0.4s; + transition: opacity 0.4s; + + ::v-deep(svg) { + margin: auto; + } + } + + &-image-mask:hover { + opacity: 40; + } + &-upload-btn { margin: 10px auto; } diff --git a/src/views/demo/comp/cropper/index.vue b/src/views/demo/comp/cropper/index.vue index 416a296..fda0f33 100644 --- a/src/views/demo/comp/cropper/index.vue +++ b/src/views/demo/comp/cropper/index.vue @@ -1,7 +1,7 @@ <template> <PageWrapper title="鍥剧墖瑁佸壀绀轰緥" content="闇�瑕佸紑鍚祴璇曟帴鍙f湇鍔℃墠鑳借繘琛屼笂浼犳祴璇曪紒"> <CollapseContainer title="澶村儚瑁佸壀"> - <CropperAvatar :uploadApi="uploadApi" /> + <CropperAvatar :uploadApi="uploadApi" :value="avatar" /> </CollapseContainer> <CollapseContainer title="鐭╁舰瑁佸壀" class="my-4"> @@ -9,7 +9,7 @@ <div class="cropper-container mr-10"> <CropperImage ref="refCropper" :src="img" @cropend="handleCropend" style="width: 40vw" /> </div> - <img :src="cropperImg" class="croppered" v-if="cropperImg" /> + <img :src="cropperImg" class="croppered" v-if="cropperImg" alt="" /> </div> <p v-if="cropperImg">瑁佸壀鍚庡浘鐗囦俊鎭細{{ info }}</p> </CollapseContainer> @@ -34,10 +34,11 @@ <script lang="ts"> import { defineComponent, ref } from 'vue'; import { PageWrapper } from '/@/components/Page'; - import { CollapseContainer } from '/@/components/Container/index'; + import { CollapseContainer } from '/@/components/Container'; import { CropperImage, CropperAvatar } from '/@/components/Cropper'; import { uploadApi } from '/@/api/sys/upload'; import img from '/@/assets/images/header.jpg'; + import { useUserStore } from '/@/store/modules/user'; export default defineComponent({ components: { @@ -51,7 +52,8 @@ const cropperImg = ref(''); const circleInfo = ref(''); const circleImg = ref(''); - + const userStore = useUserStore(); + const avatar = ref(userStore.getUserInfo?.avatar || ''); function handleCropend({ imgBase64, imgInfo }) { info.value = imgInfo; cropperImg.value = imgBase64; @@ -70,6 +72,7 @@ circleImg, handleCropend, handleCircleCropend, + avatar, uploadApi, }; }, diff --git a/src/views/demo/page/account/setting/BaseSetting.vue b/src/views/demo/page/account/setting/BaseSetting.vue index 87c546b..2968a96 100644 --- a/src/views/demo/page/account/setting/BaseSetting.vue +++ b/src/views/demo/page/account/setting/BaseSetting.vue @@ -7,10 +7,14 @@ <a-col :span="10"> <div class="change-avatar"> <div class="mb-2"> 澶村儚 </div> - <img width="140" :src="avatar" /> - <Upload :showUploadList="false"> - <Button class="ml-5"> <Icon icon="feather:upload" />鏇存崲澶村儚 </Button> - </Upload> + <CropperAvatar + :uploadApi="uploadApi" + :value="avatar" + btnText="鏇存崲澶村儚" + :btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }" + @change="updateAvatar" + width="150" + /> </div> </a-col> </a-row> @@ -18,11 +22,11 @@ </CollapseContainer> </template> <script lang="ts"> - import { Button, Upload, Row, Col } from 'ant-design-vue'; + import { Button, Row, Col } from 'ant-design-vue'; import { computed, defineComponent, onMounted } from 'vue'; import { BasicForm, useForm } from '/@/components/Form/index'; - import { CollapseContainer } from '/@/components/Container/index'; - import Icon from '/@/components/Icon/index'; + import { CollapseContainer } from '/@/components/Container'; + import { CropperAvatar } from '/@/components/Cropper'; import { useMessage } from '/@/hooks/web/useMessage'; @@ -30,16 +34,16 @@ import { accountInfoApi } from '/@/api/demo/account'; import { baseSetschemas } from './data'; import { useUserStore } from '/@/store/modules/user'; + import { uploadApi } from '/@/api/sys/upload'; export default defineComponent({ components: { BasicForm, CollapseContainer, Button, - Upload, - Icon, - [Row.name]: Row, - [Col.name]: Col, + ARow: Row, + ACol: Col, + CropperAvatar, }, setup() { const { createMessage } = useMessage(); @@ -61,9 +65,17 @@ return avatar || headerImg; }); + function updateAvatar(src: string) { + const userinfo = userStore.getUserInfo; + userinfo.avatar = src; + userStore.setUserInfo(userinfo); + } + return { avatar, register, + uploadApi, + updateAvatar, handleSubmit: () => { createMessage.success('鏇存柊鎴愬姛锛�'); }, -- Gitblit v1.8.0