You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

373 lines
10 KiB

5 months ago
<template>
<view class="sharesheet" :class="{ show: modelValue }">
<view class="mask-class sharesheet__mask" @click="onMaskClick"></view>
<view class="sharesheet__container">
<!-- 分享选项列表 -->
<view class="sharesheet__list">
<!-- 选项按钮: 发送给朋友(仅支持小程序) -->
<!-- #ifdef MP -->
<button class="share-item btn-normal" open-type="share" @click="handleCancel()">
<view class="item-image" :style="{ backgroundColor: '#44DB74' }">
<text class="iconfont icon-weixin"></text>
</view>
<view class="item-name">
<text>发送给朋友</text>
</view>
</button>
<!-- #endif -->
<!-- 选项按钮: APP端分享给微信好友 -->
<!-- #ifdef APP-PLUS -->
<view v-if="enabledAppShareWeixin" class="share-item" @click="handleShareWechat()">
<view class="item-image" :style="{ backgroundColor: '#44DB74' }">
<text class="iconfont icon-weixin"></text>
</view>
<view class="item-name">
<text>微信好友</text>
</view>
</view>
<!-- #endif -->
<!-- 选项按钮: APP端分享到微信朋友圈 -->
<!-- #ifdef APP-PLUS -->
<view v-if="enabledAppShareWeixin" class="share-item" @click="handleShareWechatTimeline()">
<view class="item-image" :style="{ backgroundColor: '#69D416' }">
<text class="iconfont icon-timeline"></text>
</view>
<view class="item-name">
<text>微信朋友圈</text>
</view>
</view>
<!-- #endif -->
<view class="share-item" @click="handlePoster()">
<view class="item-image" :style="{ backgroundColor: '#38beec' }">
<text class="iconfont icon-poster"></text>
</view>
<view class="item-name">
<text>生成海报</text>
</view>
</view>
<view class="share-item" @click="handleCopyLink()">
<view class="item-image" :style="{ backgroundColor: '#38beec' }">
<text class="iconfont icon-link"></text>
</view>
<view class="item-name">
<text>复制链接</text>
</view>
</view>
<!-- <view class="share-item">
<view class="item-image" :style="{ backgroundColor: '#FE8A4F' }">
<text class="iconfont icon-weibo"></text>
</view>
<view class="item-name">
<text>新浪微博</text>
</view>
</view> -->
<!-- <view class="share-item">
<view class="item-image" :style="{ backgroundColor: '#56C0F2' }">
<text class="iconfont icon-qq"></text>
</view>
<view class="item-name">
<text>QQ好友</text>
</view>
</view> -->
<!-- <view class="share-item">
<view class="item-image" :style="{ backgroundColor: '#FFBB0D' }">
<text class="iconfont icon-qzone"></text>
</view>
<view class="item-name">
<text>QQ空间</text>
</view>
</view> -->
</view>
<!-- 取消按钮 -->
<view v-if="cancelText" class="sharesheet__footer" @click="handleCancel()">
<view class="btn-cancel">{{ cancelText }}</view>
</view>
</view>
<!-- 海报图弹层 -->
<goods-poster-popup v-model="showGoodsPosterPopup" :apiCall="posterApiCall" :apiParam="posterApiParam" />
</view>
</template>
<!-- 参考的uniapp文档 -->
<!-- https://uniapp.dcloud.io/component/button?id=button -->
<!-- https://uniapp.dcloud.io/api/plugins/share -->
<script>
import Config from '@/core/config'
import { getCurrentPage, buildUrL } from '@/core/app'
import { inArray } from '@/utils/util'
import GoodsPosterPopup from '@/components/goods-poster-popup'
import StoreModel from '@/common/model/Store'
export default {
name: 'ShareSheet',
components: {
GoodsPosterPopup
},
emits: ['update:modelValue'],
props: {
// 控制组件显示隐藏
modelValue: {
Type: Boolean,
default: false
},
// 点击遮罩层取消
cancelWithMask: {
type: Boolean,
default: true
},
// 分享链接的标题
shareTitle: {
type: String,
default: '商品分享'
},
// 分享链接的封面图
shareImageUrl: {
type: String,
default: ''
},
// 取消按钮文字
cancelText: {
type: String,
default: '关闭'
},
// 获取海报图的api方法
posterApiCall: {
type: Function,
default: () => {}
},
// 获取海报图的api参数
posterApiParam: {
type: Object,
default: () => {}
},
},
data() {
return {
// 是否启用分享到微信聊天 (仅APP端支持)
enabledAppShareWeixin: Config.get('enabledAppShareWeixin'),
// 是否显示商品海报图弹层
showGoodsPosterPopup: false,
}
},
// 初始化方法
created() {
this.initSharesheet()
},
methods: {
// 初始化选择项
initSharesheet() {
const app = this
// 获取支持的服务商 (仅APP端支持)
uni.getProvider({
service: 'share',
success({ provider }) {
if (!inArray('weixin', provider)) {
app.enabledAppShareWeixin = false
}
}
})
},
// 点击遮罩层(关闭菜单)
onMaskClick() {
if (this.cancelWithMask) {
this.handleCancel()
}
},
// 获取分享链接 (H5外链)
getShareUrl() {
const { path, query } = getCurrentPage()
return new Promise((resolve, reject) => {
// 获取h5站点地址
StoreModel.h5Url().then(baseUrl => {
// 生成完整的分享链接
const shareUrl = buildUrL(baseUrl, path, query)
resolve(shareUrl)
})
})
},
// 复制商品链接
handleCopyLink() {
const app = this
app.getShareUrl().then(shareUrl => {
// 复制到剪贴板
uni.setClipboardData({
data: shareUrl,
success: () => app.$toast('链接复制成功,快去发送给朋友吧~'),
fail: ({ errMsg }) => app.$toast('复制失败 ' + errMsg),
complete: () => app.handleCancel()
})
})
},
// APP发送给微信好友
// #ifdef APP-PLUS
handleShareWechat() {
const app = this
app.getShareUrl().then(shareUrl => {
uni.share({
provider: 'weixin',
scene: 'WXSceneSession',
type: 0,
href: shareUrl,
title: app.shareTitle,
summary: '我发现了一个很不错的商品,赶快来看看吧!',
imageUrl: app.shareImageUrl,
success(res) {
console.log("success:" + JSON.stringify(res));
},
fail({ errCode }) {
if (errCode === -8) {
app.$toast('很抱歉,您的手机没有安装微信~')
}
},
complete: () => app.handleCancel()
})
})
},
// #endif
// APP分享到微信朋友圈
// #ifdef APP-PLUS
handleShareWechatTimeline() {
const app = this
app.getShareUrl().then(shareUrl => {
uni.share({
provider: 'weixin',
scene: 'WXSenceTimeline',
type: 0,
href: shareUrl,
title: app.shareTitle,
summary: '我发现了一个很不错的商品,赶快来看看吧!',
imageUrl: app.shareImageUrl,
success(res) {
console.log("success:" + JSON.stringify(res));
},
fail({ errCode }) {
if (errCode === -8) {
app.$toast('很抱歉,您的手机没有安装微信~')
}
},
complete: () => app.handleCancel()
})
})
},
// #endif
// 关闭菜单
handleCancel() {
this.$emit('update:modelValue', false)
},
// 生成二维码海报
handlePoster() {
this.showGoodsPosterPopup = true
this.handleCancel()
}
}
}
</script>
<style lang="scss" scoped>
.sharesheet {
background-color: #f8f8f8;
font-size: 28rpx;
}
.sharesheet__mask {
position: fixed;
top: 0;
left: var(--window-left);
right: var(--window-right);
bottom: var(--window-bottom);
z-index: 12;
background: rgba(0, 0, 0, 0.7);
display: none;
}
.sharesheet__container {
position: fixed;
left: var(--window-left);
right: var(--window-right);
bottom: var(--window-bottom);
background: #ffffff;
transform: translate3d(0, 50%, 0);
transform-origin: center;
transition: all 0.2s ease;
z-index: 13;
opacity: 0;
visibility: hidden;
border-top-left-radius: 26rpx;
border-top-right-radius: 26rpx;
padding: 50rpx 30rpx 0 30rpx;
// 设置ios刘海屏底部横线安全区域
padding-bottom: calc(constant(safe-area-inset-bottom) + 30rpx);
padding-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
}
.sharesheet__list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
margin-bottom: -35rpx;
.share-item {
flex: 0 0 25%;
margin-bottom: 40rpx;
.item-name,
.item-image {
width: 140rpx;
margin: 0 auto;
}
.item-image {
display: flex;
justify-content: center;
align-items: center;
width: 86rpx;
height: 86rpx;
border-radius: 50%;
color: #fff;
font-size: 38rpx;
}
.item-name {
margin-top: 12rpx;
text-align: center;
font-size: 26rpx;
}
}
}
.sharesheet__footer {
background: #fff;
margin-top: 40rpx;
.btn-cancel {
font-size: 28rpx;
text-align: center;
}
}
// 显示状态
.show {
.sharesheet__mask {
display: block;
}
.sharesheet__container {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
visibility: visible;
}
}
</style>