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