442 lines
13 KiB
Vue
Executable File
442 lines
13 KiB
Vue
Executable File
<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>
|