panhui 2 лет назад
Родитель
Сommit
085fe29c36

BIN
src/assets/png-tanchuang-huiyuan.png


BIN
src/assets/share-logo.png


BIN
src/assets/share1.png


BIN
src/assets/share2.png


BIN
src/assets/share3.png


BIN
src/assets/share4.png


BIN
src/assets/share5.png


BIN
src/assets/share6.png


BIN
src/assets/share7.png


BIN
src/assets/share8.png


+ 183 - 25
src/components/common/ShareModal.vue

@@ -1,36 +1,68 @@
 <template>
     <n-modal :show="show" @update:show="newValue => updateShow(newValue)" transform-origin="center">
         <div class="share-box">
-            <img :src="imgUrl" v-if="imgUrl" alt="" class="block w-5/6 max-w-md" />
-            <div class="share-img w-5/6 relative max-w-md" v-else ref="postRef">
-                <img src="@/assets/bg_share_card.png" class="block" alt="" />
+            <img :src="imgUrl" v-if="imgUrl" alt="" class="block share-canvas w-5/6 max-w-md" />
+            <div class="share-img w-5/6 relative max-w-md" :class="['share-img-' + shareType]" v-else ref="postRef">
+                <img :src="shareImgs[shareType]" class="block share-bg" alt="" />
                 <!-- <div class="absolute inset-x-0 top-0">
                     <user-avatar avatarType="small" onlyAvatar />
                 </div> -->
                 <div class="qrcode flex items-center justify-center">
                     <qrcode-vue :value="shareUrl" :size="300" renderAs="svg" level="M" />
+                    <img :src="shareLogo" alt="" class="share-logo" />
                 </div>
+
+                <div class="user flex items-center" v-if="shareType === 1">
+                    <template v-if="isString(userInfo.avatar) && userInfo.avatar.length > 0">
+                        <NAvatar :size="31" round :src="userInfo.avatar" :fallback-src="defaultAvatar" />
+                    </template>
+                    <template v-else>
+                        <NAvatar :size="31" round :src="defaultAvatar" />
+                    </template>
+                    <span class="text-xs ml-[7px]">{{ userInfo.name }}</span>
+                </div>
+            </div>
+            <div class="share-btns w-5/6 max-w-md flex">
+                <n-button text v-if="isMobile">长按保存图片</n-button>
+                <n-button text v-else @click="save">保存图片</n-button>
+                <n-button text :loading="loading" @click="changeType">换个样式</n-button>
+                <n-button text>复制邀请链接</n-button>
             </div>
 
-            <div class="tips" v-if="isMobile">长按保存图片</div>
+            <!-- <div class="tips" v-if="isMobile">长按保存图片</div>
             <div class="mt-16" v-else>
                 <n-button type="primary" @click="save">点击保存图片</n-button>
             </div>
 
-            <n-button text class="cancel" @click.stop="updateShow(false)"> 取消 </n-button>
+            <n-button text class="cancel" @click.stop="updateShow(false)"> 取消 </n-button> -->
         </div>
     </n-modal>
 </template>
 
 <script setup lang="ts">
-import { NModal, NButton } from 'naive-ui'
-import { ref, watch } from 'vue'
+import { NModal, NButton, NAvatar } from 'naive-ui'
+import { ref, watch, computed } from 'vue'
 import QrcodeVue from 'qrcode.vue'
 import html2canvas from 'html2canvas'
 import { useUserStore } from '@/store'
 import { useBasicLayout } from '@/hooks/useBasicLayout'
 import { Ref } from 'vue'
 import { fetchRedirectUrl } from '@/api'
+import { isString } from '@/utils/is'
+import defaultAvatar from '@/assets/avatar.png'
+import shareImg1 from '@/assets/share1.png'
+import shareImg2 from '@/assets/share2.png'
+import shareImg3 from '@/assets/share3.png'
+import shareImg4 from '@/assets/share4.png'
+import shareImg5 from '@/assets/share5.png'
+import shareImg6 from '@/assets/share6.png'
+import shareImg7 from '@/assets/share7.png'
+import shareImg8 from '@/assets/share8.png'
+import shareLogo from '@/assets/share-logo.png'
+
+const shareImgs = [shareImg1, shareImg2, shareImg3, shareImg4, shareImg5, shareImg6, shareImg7, shareImg8]
+const shareType = ref(1)
+const loading = ref(true)
 
 const props = defineProps({
     show: {
@@ -51,27 +83,37 @@ const shareUrl = ref('')
 fetchRedirectUrl(location.origin + '/ui/home?invitor=' + userStore.userInfo.id).then((res: any) => {
     shareUrl.value = res.url
 })
+const userInfo = computed(() => userStore.userInfo)
 
 const postRef: Ref<HTMLElement | null> = ref(null)
 watch(
     () => props.show,
     val => {
         if (val) {
-            setTimeout(() => {
-                html2canvas(postRef.value!, {
-                    useCORS: true,
-                    allowTaint: true,
-                    backgroundColor: null,
-                    scale: 3
-                }).then(canvas => {
-                    console.log(canvas)
-                    imgUrl.value = canvas.toDataURL('image/png')
-                })
-            }, 500)
+            changeType()
         }
     }
 )
 
+function changeType() {
+    loading.value = true
+    imgUrl.value = ''
+    let type = Math.floor(Math.random() * 7)
+    shareType.value = type !== shareType.value ? type : (type + 1) % 7
+    setTimeout(() => {
+        html2canvas(postRef.value!, {
+            useCORS: true,
+            allowTaint: true,
+            backgroundColor: null,
+            scale: 3
+        }).then(canvas => {
+            console.log(canvas)
+            loading.value = false
+            imgUrl.value = canvas.toDataURL('image/png')
+        })
+    }, 500)
+}
+
 function save() {
     const tempLink = document.createElement('a')
     tempLink.style.display = 'none'
@@ -91,27 +133,143 @@ const { isMobile } = useBasicLayout()
 
 <style lang="less" scoped>
 .share-img {
+    position: relative;
+    z-index: 2;
     .qrcode {
         position: absolute;
-        top: 48%;
-        left: 30%;
+        z-index: 3;
+        bottom: 5.1%;
+        right: 10.6%;
         background-color: #fff;
-        box-shadow: 0px 0px 4px 0px rgba(163, 121, 255, 0.5);
-        padding: 6px;
-        border-radius: 8px;
-        width: 40%;
-        height: 29%;
+        padding: 1px;
+        border-radius: 0px;
+        width: 15.4%;
+        height: 14.5%;
+
         :deep(svg) {
             width: 100%;
             height: 100%;
+            z-index: 1;
+            position: relative;
+        }
+
+        .share-logo {
+            width: 20%;
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            z-index: 2;
         }
     }
+
+    .user {
+        position: absolute;
+        bottom: 3.5%;
+        left: 11.5%;
+        z-index: 3;
+        height: 13.1%;
+    }
+}
+
+.share-btns {
+    background-color: #fff;
+    padding-top: 20px;
+    transform: translateY(-20px);
+    border-radius: 0 0 14px 14px;
+    position: relative;
+    z-index: 1;
+    .n-button {
+        width: 33%;
+        height: 48px;
+        position: relative;
+
+        &:not(:last-child) {
+            &::after {
+                content: '';
+                width: 1px;
+                height: 14px;
+                background: #3b3b3b;
+                position: absolute;
+                right: 0;
+            }
+        }
+    }
+}
+.share-img-1 {
+    .qrcode {
+        bottom: 3.5%;
+        right: 11.5%;
+        background-color: #fff;
+        padding: 4px;
+        border-radius: 4px;
+        width: 14.1%;
+        height: 13.1%;
+    }
+}
+.share-img-4 {
+    .qrcode {
+        top: 30.3%;
+        left: 9.8%;
+        background-color: #fff;
+        // box-shadow: 0px 0px 4px 0px rgba(163, 121, 255, 0.5);
+        padding: 5px;
+        border-radius: 0px;
+        width: 25.5%;
+        height: 24.1%;
+    }
+}
+
+.share-img-5 {
+    .qrcode {
+        top: 24.2%;
+        left: 50%;
+        background-color: #fff;
+        // box-shadow: 0px 0px 4px 0px rgba(163, 121, 255, 0.5);
+        padding: 10px;
+        border-radius: 4px;
+        width: 43.4%;
+        height: 36%;
+        transform: translateX(-50%);
+    }
+}
+
+.share-img-6 {
+    .qrcode {
+        background-color: #fff;
+        bottom: 3.7%;
+        right: 10.8%;
+        padding: 3px;
+        border-radius: 0px;
+        width: 14.8%;
+        height: 9.9%;
+    }
+}
+
+.share-img-7 {
+    .qrcode {
+        background-color: #fff;
+        top: 5.3%;
+        right: 14.8%;
+        padding: 4px;
+        border-radius: 4px;
+        width: 14.8%;
+        height: 9.8%;
+    }
 }
 
 .share-box {
     .f-col();
     align-items: center;
     --n-box-shadow: none;
+    .share-bg {
+        position: relative;
+        z-index: 2;
+    }
+    .share-canvas {
+        position: relative;
+        z-index: 2;
+    }
 }
 
 .tips {