uniapp开发,分享链接(下载二维码,复制链接,分享到微信)

735 阅读3分钟

一、业务需求

分享链接,包括:
下载二维码,保存到相册;
复制链接,可以复制链接内容;
分享到微信,可以唤起微信。

二、实现效果

image.png

三、核心

唤起微信

// data定义
wexinParam: {
    name: '微信',
    pname: 'com.tencent.mm',
    scheme: 'weixin://'
}

// 调用方法
this.launchApp(this.wexinParam)

// 打开外部应用-微信
launchApp(data) {
    if (plus.os.name == 'Android') {
        plus.runtime.launchApplication({ pname: e.pname }, function(e) {
            console.log('Open system default browser failed: ' + e.name)
        })
    } else if (plus.os.name == 'iOS') {
        plus.runtime.launchApplication({ action: e.scheme }, function(e) {
            console.log('Open system default browser failed: ' + e.name)
        })
    }
}

三、代码实现

1、分享链接弹框

shareLink.vue

<template>
    <my-popup
        ref="myPopup"
        type="bottom"
        title="分享链接"
        :topCancel="false"
        :isShowFooter="false"
        height="32vh">
        <view class="share-link">
            <view class="share-link-item" @click="downloadQRCode">
                <image src="../../../static/visitorMgt/download-qr-code.png" mode=""></image>
                <view class="share-link-item-title">下载二维码</view>
            </view>
            <view class="share-link-item" @click="copyLink">
                <image src="../../../static/visitorMgt/copy-link.png" mode=""></image>
                <view class="share-link-item-title">复制链接</view>
            </view>
            <view class="share-link-item" @click="shareOnWechat">
                <image src="../../../static/visitorMgt/share-on-wechat.png" mode=""></image>
                <view class="share-link-item-title">分享到微信</view>
            </view>
        </view>
        <view class="share-link-bottom">
            <view class="share-link-cancel" @click="cancel">
                取消
            </view>
        </view>
    </my-popup>
</template>

<script>
    import {
        getLinkVisitorInfo,
        getQRVisitorInfo,
    } from '@/api/visitorMgt/visitorMgt.js'
    import {
        getFullUrl,
        downLoadImg
    } from '@/utils/commonFun.js'
    export default {
        name: 'shareLink',
        props: {
            visitFormId: {
                type: Number,
                default: null
            }
        },
        data() {
            return {
                wexinParam: {
                    name: '微信',
                    pname: 'com.tencent.mm',
                    scheme: 'weixin://'
                }
            }
        },
        methods: {
            /**
             * 取消按钮
             */
            cancel() {
                this.$refs.myPopup.popupClose()
                this.$emit('shareCancel')
            },
            /**
             * 打开弹框
             */
            popupOpen() {
                this.$refs.myPopup.popupOpen()
            },
            /**
             * 下载二维码
             */
            downloadQRCode(){
                getQRVisitorInfo(this.visitFormId).then(res => {
                    let fileData = JSON.parse(res)
                    this.imageSrc = getFullUrl(fileData.fileUrl)
                    this.imageName = fileData.originalName
                    downLoadImg({
                        fileUrl: this.imageSrc,
                        originalName: this.imageName
                    })
                })
            },
            /**
             * 复制链接
             */
            copyLink() {
                getLinkVisitorInfo(this.visitFormId).then(res => {
                    uni.setClipboardData({
                        data: res.shortUrl
                    })
                })
            },
            /**
             * 分享到微信
             */
            shareOnWechat() {
                getLinkVisitorInfo(this.visitFormId).then(res => {
                    uni.setClipboardData({
                        data: res.shortUrl
                    })
                    uni.$u.toast('已复制,正在打开微信...')
                    setTimeout(() => {
                        // 打开微信
                        this.launchApp(this.wexinParam)
                    }, 1000)
                })
            },
            /**
             * 打开外部应用-微信
             */
            launchApp(e) {
                // 判断平台
                if (plus.os.name == 'Android') {
                    plus.runtime.launchApplication({ pname: e.pname }, function(e) {
                        console.log('Open system default browser failed: ' + e.name)
                    })
                } else if (plus.os.name == 'iOS') {
                    plus.runtime.launchApplication({ action: e.scheme }, function(e) {
                        console.log('Open system default browser failed: ' + e.name)
                    })
                }		
            }
        }
    }
</script>

<style lang="scss" scoped>
.share-link {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    .share-link-item {
        width: 33%;
        margin-top: 20rpx;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        image {
            width: 100rpx;
            height: 100rpx;
        }
        .share-link-item-title {
            margin-top: 16rpx;
            color: #8E8E8E;
        }
    }
}
.share-link-bottom {
    padding-top: 32rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
    .share-link-cancel {
        flex: 1;
        height: 80rpx;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 32rpx;
        font-weight: 500;
        color: #000000;
    }
}
</style>

2、工具类

export const config = {
    baseUrl: "/api",
    filePath: "http://115.1.2.3:280",
    // #ifdef APP-PLUS
    // 开发环境
    baseUrl: "http://115.1.2.3:280/stage-api",
    filePath: "http://115.1.2.3:280",
    // #endif
}

// 文件图片地址
export function getFullUrl(url) {
    let fullUrl = ''
    if (url) {
        fullUrl = /(http|https|blob:):\/\/([\w.]+\/?)\S*/.test(url)
            ? url
            : config.filePath + url
    }
    return fullUrl
}

export const downLoadImg = (file) => {
    // #ifdef APP-PLUS
    uni.showLoading({
            title: '正在下载'
    })
    uni.downloadFile({
        url: getFullUrl(file.fileUrl),
        success: (res) => {
            if (res.statusCode === 200) {
                // console.log(res.tempFilePath)
                uni.saveImageToPhotosAlbum({
                    filePath: res.tempFilePath,
                    success: () => {
                            uni.$u.toast('已保存到系统相册')
                    },
                    fail: () => {
                            uni.$u.toast('图片保存失败')
                    },
                    complete: () => {}
                })
            }
        },
        complete: () => {
            uni.hideLoading()
        }
    })
    // #endif
    // #ifdef H5
    window.open(getFullUrl(file.fileUrl))
    // #endif
    // #ifdef MP
    uni.setClipboardData({
        data: getFullUrl(file.fileUrl),
        success: () => {
            uni.$u.toast('链接已复制,请在浏览器打开')
        }
    })
    // #endif
}

3、弹框组件

my-popup.vue

<template>
    <uni-popup
        ref="popup"
        :safe-area="false"
        :type="type"
        :is-mask-click="isMaskClick"
        @change="change"
        @maskClick="maskClick">
        <view class="popup-content" :style="{ 'height': height }">
            <view v-if="topBtn" class="popup-top">
                <view class="popup-top-cancel" @click="cancel">{{ topCancelText }}</view>
                <view class="popup-title">
                    <slot name="title" v-if="$slots.title"></slot>
                    <view v-else>
                        {{ title }}
                    </view>
                </view>
                <view class="popup-top-confirm" @click="confirm">
                    {{ topConfirmText }}
                </view>
            </view>
            <view v-else class="popup-title">
                <slot name="title" v-if="$slots.title"></slot>
                <view v-else>
                    {{ title }}
                </view>
                <image
                    v-if="topCancel"
                    src="../../static/common/close-outlined.png"
                    mode=""
                    class="icon-close w-40 h-40"
                    @click="closed"
                ></image>
            </view>
            <view
                class="popup-middle"
                :class="[isShowFooter ? 'popup-middle-bottom-160' : 'popup-middle-bottom-32']"
            >
                <slot></slot>
            </view>
            <view class="popup-bottom" v-if="isShowFooter">
                <view
                    v-if="isShowCancelBtn"
                    class="popup-bottom-cancel mr-20"
                    @click="cancel"
                >{{ cancelText }}</view>
                <view class="popup-bottom-confirm" @click="confirm">{{ confirmText }}</view>
            </view>
        </view>
    </uni-popup>
</template>

<script>
export default {
    name: "my-popup",
    props: {
        // 弹出方式
        type: {
            type: String,
            default: 'bottom'
        },
        // 内容区高度
        height: {
            type: String,
            default: ''
        },
        // 表头
        title: {
            type: String,
            default: '筛选'
        },
        // 取消按钮text
        cancelText: {
            type: String,
            default: '重置'
        },
        // 确定按钮text
        confirmText: {
            type: String,
            default: '确定'
        },
        // 顶部,取消按钮text
        topCancelText: {
            type: String,
            default: '取消'
        },
        // 顶部,确定按钮text
        topConfirmText: {
            type: String,
            default: '确定'
        },
        // 蒙版点击是否关闭弹窗
        isMaskClick: {
            type: Boolean,
            default: true
        },
        // 点击确定是否校验内容区域
        confirmIsCheck: {
            type: Boolean,
            default: false
        },
        // 点击取消是否校验内容区域
        cancelIsCheck: {
            type: Boolean,
            default: false
        },
        // 是否显示footer
        isShowFooter: {
            type: Boolean,
            default: true
        },
        // 顶部显示按钮
        topBtn: {
            type: Boolean,
            default: false
        },
        // 顶部不显示按钮时,是否展示取消图标
        topCancel: {
            type: Boolean,
            default: true
        },
        // 是否显示取消按钮
        isShowCancelBtn: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {}
    },
    methods: {
        /**
         * 打开弹框
         */
        popupOpen() {
            this.$refs.popup.open()
        },
        /**
         * 关闭弹框
         */
        popupClose() {
            this.$refs.popup.close()
        },
        /**
         * 右上角按钮关闭
         */
        closed() {
            this.popupClose()
            this.$emit('closed')
        },
        /**
         * 取消按钮点击
         */
        cancel() {
            if (!this.cancelIsCheck) {
                this.popupClose()
            }
            this.$emit('cancel')
        },
        /**
         * 确定按钮点击
         */
        confirm() {
            if (!this.confirmIsCheck) {
                this.popupClose()
            }
            this.$emit('confirm')
        },
        /**
         * 组件状态发生变化触发
         * @param {Object} e
         */
        change(e) {
            this.$emit('change', e)
        },
        /**
         * 点击遮罩层触发
         */
        maskClick() {
            this.$emit('maskClick')
        }
    }
}
</script>

<style lang="scss" scoped>
.popup-content {
    height: 70vh;
    border-radius: 40rpx 40rpx 0 0;
    background: #fff;
}

.popup-title {
    height: 90rpx;
    line-height: 90rpx;
    display: flex;
    justify-content: center;
    box-sizing: border-box;
    padding: 0 32rpx;
    position: relative;
    font-size: 32rpx;
    font-weight: bold;
    overflow: hidden;
    color: #000000;

    .icon-close {
        position: absolute;
        right: 32rpx;
        top: 24rpx;
    }
}

.popup-top {
    display: flex;
    align-items: center;
    font-weight: bold;
    padding: 0 32rpx;
    box-sizing: border-box;

    .popup-title {
        flex: 1;
        padding: 0 32rpx;
    }

    .popup-top-cancel {
        font-size: 32rpx;
        color: #000000;
    }

    .popup-top-confirm {
        font-size: 32rpx;
        color: #005AFF;
    }
}

.popup-middle {
    overflow-y: auto;
    padding: 0 32rpx;
    box-sizing: border-box;
    position: absolute;
    right: 0;
    left: 0;
    top: 90rpx;
    background-color: #fff;
}

.popup-middle-bottom-160 {
    bottom: 160rpx;
}

.popup-middle-bottom-32 {
    bottom: 32rpx;
}

.popup-bottom {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 160rpx;
    padding: 32rpx 32rpx 48rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;

    .popup-bottom-cancel,
    .popup-bottom-confirm {
        flex: 1;
        height: 80rpx;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 32rpx;
        color: #FFFFFF;
        font-weight: 500;
        border-radius: 58rpx;
    }

    .popup-bottom-cancel {
        border: 2rpx solid #005AFF;
        color: #005AFF;
    }

    .popup-bottom-confirm {
        background: linear-gradient(180deg, #4D8CFF 0%, #005AFF 100%);
    }
}
</style>