初始化商家端
548
components/fu-share/fu-share.vue
Normal file
@ -0,0 +1,548 @@
|
||||
<template>
|
||||
<view>
|
||||
<fu-popup v-model="sharePopup" mode="bottom" :safe-area-inset-bottom="true" :mask-close-able="true" border-radius="24">
|
||||
<view class="wrap">
|
||||
<view class="flex">
|
||||
<view class="flex-sub text-center">{{ $t('分享到') }}</view>
|
||||
<view class="cuIcon-close" @tap.stop="close"></view>
|
||||
</view>
|
||||
<view class="padding-tb">
|
||||
<!-- APP平台 start -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="grid col-4">
|
||||
<block v-for="(item, index) in shareList" :key="index">
|
||||
<view v-if="provider.includes(item.type)" class="height-200 flex flex-direction align-center justify-center" @tap.stop="share(item)">
|
||||
<image class="block-85" :src="item.icon" mode="aspectFit"></image>
|
||||
<text class="margin-top-xs text-sm">{{ item.title }}</text>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- APP平台 end -->
|
||||
|
||||
<!-- 微信小程序平台 start -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="grid col-2">
|
||||
<view>
|
||||
<button class="height-200 flex flex-direction align-center justify-center cu-btn bg-white" open-type="share">
|
||||
<image class="block-85" :src="require('./static/weixin.png')" mode="aspectFit"></image>
|
||||
<text class="margin-top-xs text-sm">{{ $t('微信好友') }}</text>
|
||||
</button>
|
||||
</view>
|
||||
<view>
|
||||
<button class="height-200 flex flex-direction align-center justify-center cu-btn bg-white" @tap.stop="createPoster">
|
||||
<image class="block-85" :src="require('./static/poster.png')" mode="aspectFit"></image>
|
||||
<text class="margin-top-xs text-sm">{{ $t('二维码海报') }}</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- 微信小程序平台 end -->
|
||||
|
||||
<!-- H5平台 staart -->
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="grid col-3">
|
||||
<view>
|
||||
<button class="height-200 flex flex-direction align-center justify-center cu-btn bg-white" @tap.stop="createPoster">
|
||||
<image class="block-85" :src="require('./static/poster.png')" mode="aspectFit"></image>
|
||||
<text class="margin-top-xs text-sm">{{ $t('二维码海报') }}</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- H5平台 end -->
|
||||
</view>
|
||||
</view>
|
||||
</fu-popup>
|
||||
<fu-popup v-model="posterPopup" mode="bottom" :safe-area-inset-bottom="true" :mask-close-able="true" border-radius="24">
|
||||
<view class="wrap">
|
||||
<view class="flex align-center justify-between">
|
||||
<view class="text-df text-333">{{ $t('保存到相册') }}</view>
|
||||
<view class="cuIcon-close text-333" @click.stop="close"></view>
|
||||
</view>
|
||||
<view class="margin-top flex justify-center align-center">
|
||||
<image class="preview-image" :src="previewImageUrl" mode="aspectFill" @click="previewImage(previewImageUrl)"></image>
|
||||
</view>
|
||||
<!-- #ifndef H5 -->
|
||||
<view class="margin-top" @click="saveImage">
|
||||
<button class="action2 cu-btn block round">{{ $t('保存图片') }}</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</fu-popup>
|
||||
<view class="offset-canvas">
|
||||
<canvas canvas-id="poster-canvas" style="width: 375px; height: 550px"></canvas>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* @alias 刘欢
|
||||
* @description 常规分享组件,提供分享到微信,微信朋友圈,QQ,QQ空间,分享海报等功能
|
||||
* @param { Boollean } isShareToMp 是否分享到小程序
|
||||
* */
|
||||
const providers = [
|
||||
{
|
||||
title: global.i18n.t('微信好友'),
|
||||
icon: require('./static/weixin.png'),
|
||||
type: 'weixin',
|
||||
scene: 'WXSceneSession',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('朋友圈'),
|
||||
icon: require('./static/pengyouquan.png'),
|
||||
type: 'weixin',
|
||||
scene: 'WXSenceTimeline',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('QQ好友'),
|
||||
icon: require('./static/qq.png'),
|
||||
type: 'qq',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('QQ空间'),
|
||||
icon: require('./static/kongjian.png'),
|
||||
type: 'qq',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('新浪微博'),
|
||||
icon: require('./static/weibo.png'),
|
||||
type: 'sinaweibo',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('复制链接'),
|
||||
icon: require('./static/copy.png'),
|
||||
type: 'link',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('二维码海报'),
|
||||
icon: require('./static/poster.png'),
|
||||
type: 'image',
|
||||
},
|
||||
]
|
||||
export default {
|
||||
props: {
|
||||
info: Object,
|
||||
isShareToMp: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ctx: null,
|
||||
previewImageUrl: '',
|
||||
shareList: [
|
||||
{
|
||||
title: global.i18n.t('微信好友'),
|
||||
icon: require('./static/weixin.png'),
|
||||
type: 'weixin',
|
||||
scene: 'WXSceneSession',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('朋友圈'),
|
||||
icon: require('./static/pengyouquan.png'),
|
||||
type: 'weixin',
|
||||
scene: 'WXSenceTimeline',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('QQ好友'),
|
||||
icon: require('./static/qq.png'),
|
||||
type: 'qq',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('QQ空间'),
|
||||
icon: require('./static/kongjian.png'),
|
||||
type: 'qq',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('新浪微博'),
|
||||
icon: require('./static/weibo.png'),
|
||||
type: 'sinaweibo',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('复制链接'),
|
||||
icon: require('./static/copy.png'),
|
||||
type: 'link',
|
||||
},
|
||||
{
|
||||
title: global.i18n.t('二维码海报'),
|
||||
icon: require('./static/poster.png'),
|
||||
type: 'image',
|
||||
},
|
||||
],
|
||||
provider: [], // 已配置的服务供应商
|
||||
sharePopup: false,
|
||||
posterPopup: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 图片点击放大
|
||||
previewImage(url) {
|
||||
uni.previewImage({
|
||||
current: url,
|
||||
urls: [url],
|
||||
})
|
||||
},
|
||||
// 打开弹窗
|
||||
open() {
|
||||
console.log(this.info, 888888)
|
||||
this.sharePopup = true
|
||||
},
|
||||
// 关闭弹窗
|
||||
close() {
|
||||
this.sharePopup = false
|
||||
this.posterPopup = false
|
||||
},
|
||||
// 初始化分享数据
|
||||
init() {
|
||||
this.sharePopup = false
|
||||
this.posterPopup = true
|
||||
this.initCanvas()
|
||||
console.log('init????')
|
||||
},
|
||||
// 获取服务商列表
|
||||
getProvider() {
|
||||
uni.getProvider({
|
||||
service: 'share',
|
||||
success: (data) => {
|
||||
console.log('已配置的分享服务', data)
|
||||
this.provider = [...data.provider, 'link', 'image']
|
||||
},
|
||||
})
|
||||
},
|
||||
// 分享
|
||||
share(item) {
|
||||
let _scene = ''
|
||||
let _provider = item.type
|
||||
let _type = 0
|
||||
switch (_provider) {
|
||||
case 'weixin':
|
||||
_scene = item.scene
|
||||
uni.share({
|
||||
provider: _provider,
|
||||
type: _type,
|
||||
title: this.info.goodsName,
|
||||
scene: _scene,
|
||||
summary: this.info.summary,
|
||||
href: this.info.href,
|
||||
imageUrl: this.info.goodsImage,
|
||||
success: (res) => {
|
||||
this.close()
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('分享失败', err)
|
||||
this.$message.info(global.i18n.t('分享失败'))
|
||||
},
|
||||
})
|
||||
break
|
||||
case 'qq':
|
||||
_type = 1
|
||||
uni.share({
|
||||
provider: _provider,
|
||||
type: _type,
|
||||
title: this.info.goodsName,
|
||||
scene: _scene,
|
||||
summary: this.info.summary,
|
||||
href: this.info.href,
|
||||
imageUrl: this.info.goodsImage,
|
||||
success: (res) => {
|
||||
this.close()
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('分享失败', err)
|
||||
this.$message.info(global.i18n.t('分享失败'))
|
||||
},
|
||||
})
|
||||
break
|
||||
case 'sinaweibo':
|
||||
uni.share({
|
||||
provider: _provider,
|
||||
type: _type,
|
||||
title: this.info.goodsName,
|
||||
scene: _scene,
|
||||
summary: this.info.summary,
|
||||
href: this.info.href,
|
||||
imageUrl: this.info.goodsImage,
|
||||
success: (res) => {
|
||||
this.close()
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('分享失败', err)
|
||||
this.$message.info(global.i18n.t('分享失败'))
|
||||
},
|
||||
})
|
||||
break
|
||||
case 'link':
|
||||
uni.setClipboardData({
|
||||
data: this.info.href,
|
||||
success: () => {
|
||||
this.$message.success(global.i18n.t('复制成功'))
|
||||
this.close()
|
||||
},
|
||||
})
|
||||
break
|
||||
case 'image':
|
||||
this.createPoster()
|
||||
break
|
||||
}
|
||||
},
|
||||
// 生成海报
|
||||
createPoster() {
|
||||
console.log('生成海报')
|
||||
this.$util.actionAuth(() => {
|
||||
this.$emit('getPosterInfo')
|
||||
})
|
||||
},
|
||||
// 初始化画布
|
||||
initCanvas() {
|
||||
uni.showLoading({
|
||||
title: global.i18n.t('海报生成中...'),
|
||||
mask: true,
|
||||
})
|
||||
console.log('开始绘图', this.info)
|
||||
this.ctx = uni.createCanvasContext('poster-canvas', this)
|
||||
setTimeout(() => {
|
||||
this.drawBack()
|
||||
}, 200)
|
||||
},
|
||||
// 绘制背景
|
||||
drawBack() {
|
||||
let ctx = this.ctx
|
||||
ctx.setFillStyle('#FFFFFF')
|
||||
ctx.fillRect(0, 0, 375, 550)
|
||||
ctx.draw(false, () => {
|
||||
console.log('背景绘制成功')
|
||||
this.drawUserInfo()
|
||||
})
|
||||
},
|
||||
// 绘制个人信息
|
||||
async drawUserInfo() {
|
||||
let ctx = this.ctx
|
||||
console.log(this.info)
|
||||
await new Promise((resolve) => {
|
||||
uni.getImageInfo({
|
||||
src: this.info.avatar,
|
||||
success: (res) => {
|
||||
console.log('头像图片', res)
|
||||
let { width, height, path } = res
|
||||
if (width > height) {
|
||||
let startX = (width - height) / 2
|
||||
ctx.drawImage(res.path, startX, 0, height, height, 20, 20, 50, 50)
|
||||
} else if (width < height) {
|
||||
let startY = (height - width) / 2
|
||||
ctx.drawImage(res.path, 0, startY, width, width, 20, 20, 50, 50)
|
||||
} else {
|
||||
ctx.drawImage(res.path, 20, 20, 50, 50)
|
||||
}
|
||||
resolve()
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading()
|
||||
this.$message.info(global.i18n.t('获取头像信息失败'))
|
||||
console.log('获取图片信息失败', err)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
ctx.setFillStyle('#333333')
|
||||
ctx.setFontSize(18)
|
||||
ctx.fillText(this.info.name, 90, 40)
|
||||
ctx.setFillStyle('#999999')
|
||||
ctx.setFontSize(16)
|
||||
ctx.fillText(global.i18n.t('推荐一个好物给你,请查收'), 90, 65)
|
||||
ctx.draw(true, () => {
|
||||
console.log('个人信息绘制成功')
|
||||
this.drawGoodsImage()
|
||||
})
|
||||
},
|
||||
// 绘制商品图片
|
||||
async drawGoodsImage() {
|
||||
let ctx = this.ctx
|
||||
await new Promise((resolve) => {
|
||||
uni.getImageInfo({
|
||||
src: this.info.goodsImage,
|
||||
success: (res) => {
|
||||
console.log('商品图片', res)
|
||||
let { width, height, path } = res
|
||||
if (width > height) {
|
||||
let startX = (width - height) / 2
|
||||
ctx.drawImage(res.path, startX, 0, height, height, 20, 90, 335, 335)
|
||||
} else if (width < height) {
|
||||
let startY = (height - width) / 2
|
||||
ctx.drawImage(res.path, 0, startY, width, width, 20, 90, 335, 335)
|
||||
} else {
|
||||
ctx.drawImage(res.path, 20, 90, 335, 335)
|
||||
}
|
||||
resolve()
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading()
|
||||
console.log('商品图片绘制失败', err)
|
||||
this.$message.info(global.i18n.t('获取商品图片信息失败'))
|
||||
},
|
||||
})
|
||||
})
|
||||
ctx.draw(true, () => {
|
||||
console.log('商品图片绘制成功')
|
||||
this.drawGoodsInfo()
|
||||
})
|
||||
},
|
||||
// 绘制商品名称价格
|
||||
drawGoodsInfo() {
|
||||
let ctx = this.ctx
|
||||
this.drawText(ctx, this.info.goodsName, 20, 455, 240, 2, '#333333', 18)
|
||||
ctx.setFontSize(20)
|
||||
ctx.setFillStyle('#d55034')
|
||||
ctx.fillText('¥' + this.info.price, 20, 510)
|
||||
ctx.draw(true, () => {
|
||||
console.log('商品信息绘制成功')
|
||||
this.drawCode()
|
||||
// this.exportImage();
|
||||
})
|
||||
},
|
||||
// 绘制二维码
|
||||
async drawCode() {
|
||||
let ctx = this.ctx
|
||||
await new Promise((resolve) => {
|
||||
uni.getImageInfo({
|
||||
src: this.info.code,
|
||||
success: (res) => {
|
||||
console.log('二维码信息', res)
|
||||
let { width, height, path } = res
|
||||
if (width > height) {
|
||||
let startX = (width - height) / 2
|
||||
ctx.drawImage(res.path, startX, 0, height, height, 275, 445, 80, 80)
|
||||
} else if (width < height) {
|
||||
let startY = (height - width) / 2
|
||||
ctx.drawImage(res.path, 0, startY, width, width, 275, 445, 80, 80)
|
||||
} else {
|
||||
ctx.drawImage(res.path, 275, 445, 80, 80)
|
||||
}
|
||||
resolve()
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('二维码绘制失败', err)
|
||||
uni.hideLoading()
|
||||
this.$message.info(global.i18n.t('获取二维码信息失败'))
|
||||
},
|
||||
})
|
||||
})
|
||||
ctx.draw(true, () => {
|
||||
console.log('二维码绘制成功')
|
||||
this.exportImage()
|
||||
})
|
||||
},
|
||||
// 导出图片
|
||||
exportImage() {
|
||||
uni.canvasToTempFilePath(
|
||||
{
|
||||
canvasId: 'poster-canvas',
|
||||
success: (res) => {
|
||||
uni.hideLoading()
|
||||
console.log('导出图片成功', res)
|
||||
this.previewImageUrl = res.tempFilePath
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading()
|
||||
console.log('导出图片失败', err)
|
||||
},
|
||||
},
|
||||
this
|
||||
)
|
||||
},
|
||||
// 保存图片
|
||||
saveImage() {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: this.previewImageUrl,
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
this.$message.info(global.i18n.t('保存成功'))
|
||||
this.close()
|
||||
},
|
||||
})
|
||||
},
|
||||
/**
|
||||
* @description 绘制图片通用方法
|
||||
* @param {Object} ctx - canvas上下文
|
||||
* @param {String} 图片路径 - canvas上下文
|
||||
* */
|
||||
async drawImage(ctx, path) {},
|
||||
/**
|
||||
* @description 绘制文本通用方法
|
||||
* @param {Object} ctx - canvas上下文
|
||||
* @param {String} text - 文本
|
||||
* @param {Number} startX - X轴开始位置
|
||||
* @param {Number} startY - Y轴开始位置
|
||||
* @param {Number} limitWidth - 文字绘制区限制宽度
|
||||
* @param {Number} limitLine - 文字绘制限制行数
|
||||
* @param {String} color - 文字颜色
|
||||
* @param {Number} size - 字体大小
|
||||
* */
|
||||
drawText(ctx, text, startX, startY, limitWidth, limitLine = 2, color = '#333333', size = 18, isBold = false) {
|
||||
ctx.setFillStyle(color)
|
||||
ctx.setFontSize(size)
|
||||
let arrText = text.split('')
|
||||
let line = ''
|
||||
let column = 0
|
||||
for (let n = 0, len = arrText.length; n < len; n++) {
|
||||
let testline = line + arrText[n]
|
||||
let metrics = ctx.measureText(testline)
|
||||
let testWidth = metrics.width
|
||||
if (testWidth > limitWidth && n > 0 && column < limitLine) {
|
||||
ctx.fillText(line, startX, startY)
|
||||
column += 1
|
||||
line = arrText[n]
|
||||
startY += size * 1.5
|
||||
} else {
|
||||
line = testline
|
||||
}
|
||||
}
|
||||
if (column < limitLine) {
|
||||
ctx.fillText(line, startX, startY)
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
console.log('组件 created')
|
||||
this.getProvider()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrap {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.block-85 {
|
||||
width: 85rpx;
|
||||
height: 85rpx;
|
||||
}
|
||||
|
||||
.height-200 {
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.action2 {
|
||||
height: 80rpx;
|
||||
background-color: #f02523;
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.preview-image {
|
||||
width: 375rpx;
|
||||
height: 550rpx;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.offset-canvas {
|
||||
position: fixed;
|
||||
top: -1000px;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
}
|
||||
</style>
|
||||
26
components/fu-share/lang.js
Normal file
@ -0,0 +1,26 @@
|
||||
export default {
|
||||
"zh": {
|
||||
"分享到": "分享到",
|
||||
"微信好友": "微信好友",
|
||||
"二维码海报": "二维码海报",
|
||||
"保存到相册": "保存到相册",
|
||||
"保存图片": "保存图片",
|
||||
"微信好友": "微信好友",
|
||||
"朋友圈": "朋友圈",
|
||||
"QQ好友": "QQ好友",
|
||||
"QQ空间": "QQ空间",
|
||||
"新浪微博": "新浪微博",
|
||||
"复制链接": "复制链接",
|
||||
"二维码海报": "二维码海报",
|
||||
"分享失败": "分享失败",
|
||||
"复制成功": "复制成功",
|
||||
"海报生成中...": "海报生成中...",
|
||||
"获取头像信息失败": "获取头像信息失败",
|
||||
"推荐一个好物给你,请查收": "推荐一个好物给你,请查收",
|
||||
"获取商品图片信息失败": "获取商品图片信息失败",
|
||||
"获取二维码信息失败": "获取二维码信息失败",
|
||||
"保存成功": "保存成功"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
BIN
components/fu-share/static/copy.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
components/fu-share/static/kongjian.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
components/fu-share/static/pengyouquan.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
components/fu-share/static/poster.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
components/fu-share/static/qq.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
components/fu-share/static/weibo.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
components/fu-share/static/weixin.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |