Files

442 lines
13 KiB
Vue
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="sharesheet" :class="{ show: value }">
<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>
<!-- 海报图弹层 -->
<GoodsPosterPopup 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 SettingModel from '@/common/model/Setting'
export default {
name: 'ShareSheet',
components: {
GoodsPosterPopup
},
props: {
// true 组件显示 false 组件隐藏
value: {
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站点地址
SettingModel.h5Url(true)
.then(baseUrl => {
// 检查baseUrl是否有效
if (baseUrl && typeof baseUrl === 'string' && baseUrl.trim() !== '') {
// 生成完整的分享链接
const shareUrl = buildUrL(baseUrl, path, query)
resolve(shareUrl)
} else {
// 如果H5地址无效抛出错误进入catch处理
throw new Error('H5地址无效')
}
})
.catch(err => {
// 如果获取H5地址失败使用默认域名或当前页面路径
console.log('获取H5地址失败:', err)
reject(err)
})
})
},
// 复制商品链接
handleCopyLink() {
const app = this
app.getShareUrl().then(shareUrl => {
console.log('获取到分享链接:', shareUrl)
// 复制到剪贴板
uni.setClipboardData({
data: shareUrl,
success: () => app.$toast('链接复制成功,快去发送给朋友吧~'),
fail: (error) => {
console.error('复制失败:', error)
app.$toast('很遗憾,复制失败')
},
complete: () => app.handleCancel()
})
}).catch(err => {
// 如果获取分享链接失败,使用当前页面路径
const { path, query } = getCurrentPage()
console.log('当前页面信息:', { path, query })
// 构建查询参数字符串
let queryString = ''
if (query && Object.keys(query).length > 0) {
const queryParts = []
for (const key in query) {
if (query.hasOwnProperty(key)) {
queryParts.push(key + '=' + query[key])
}
}
queryString = queryParts.join('&')
}
// 构建当前页面URL
const currentUrl = path + (queryString ? '?' + queryString : '')
const shareText = app.shareTitle + '\n\n查看详情' + currentUrl
console.log('生成的分享文本:', shareText)
uni.setClipboardData({
data: shareText,
success: () => app.$toast('链接复制成功,快去发送给朋友吧~'),
fail: (error) => {
console.error('复制失败:', error)
app.$toast('很遗憾,复制失败')
},
complete: () => app.handleCancel()
})
})
},
// APP发送给微信好友
// #ifdef APP-PLUS
handleShareWechat() {
const app = this
uni.share({
provider: 'weixin',
scene: 'WXSceneSession',
type: 0,
href: app.getShareUrl(),
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
uni.share({
provider: 'weixin',
scene: 'WXSenceTimeline',
type: 0,
href: app.getShareUrl(),
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('input', false)
},
// 生成二维码海报
async handlePoster() {
console.log('ShareSheet handlePoster 被调用');
console.log('posterApiCall 类型:', typeof this.posterApiCall);
console.log('posterApiCall 函数:', this.posterApiCall);
console.log('posterApiParam:', this.posterApiParam);
// 先关闭分享菜单
this.handleCancel();
// 检查是否有海报生成方法
if (typeof this.posterApiCall !== 'function') {
console.error('posterApiCall 不是一个函数!');
uni.showToast({
title: '海报生成功能异常',
icon: 'none'
});
return;
}
try {
// 直接调用海报生成方法,让父组件处理海报显示
const result = await this.posterApiCall(this.posterApiParam);
console.log('海报生成完成:', result);
} catch (error) {
console.error('海报生成失败:', error);
// 错误处理已经在 posterApiCall 中处理了,这里不需要重复显示
}
}
}
}
</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>