Authored by 肖亚东

商品快照分享功能 — review by 李其昌

import {
SHOWSIZEBOX,
SHOWSHARESHEET
SHOWSHARESHEET,
SHOWSNAPSHOT
} from '../constants/productDetail'
export const showSizeBox = (isShow) => {
... ... @@ -16,4 +17,11 @@ export const showSharesheet = (isShow) => {
type: SHOWSHARESHEET
}
}
export const showSnapshot = (isShow) => {
return {
isShow,
type: SHOWSNAPSHOT
}
}
 
\ No newline at end of file
... ...
... ... @@ -28,6 +28,8 @@ Component({
methods: {
onShare: function(e) {
event.emit(SHARE_CANCEL);
let type = e.currentTarget.dataset.type;
if (type == 'friends') {//微信好友或群
event.emit(SHARE_FRIENDS);
... ...
import Taro from '@tarojs/taro'
import event from '../../../utils/event.js'
import {getImgUrl} from '../../../utils';
// 获取系统信息
let systemInfo = Taro.getSystemInfoSync();
const windowWidth = systemInfo.windowWidth;
const windowHeight = systemInfo.windowHeight;
const screenHeight = systemInfo.screenHeight;
let scale = windowWidth / 375;
let HScale = scale
const SHARE_CANCEL_MOMENTS = 'user-canel-share-moments';
Component({
/**
* 组件的属性列表
*/
properties: {
isShow: {
type: Boolean,
value: false,
observer: "_creatSnapshoot"
},
sourceType: {
type: String,
value: ""
},
shareData: {
type: Object,
value: null,
}
},
/**
* 组件的初始数据
*/
data: {
screenHeight: systemInfo.screenHeight,
windowWidth: systemInfo.windowWidth,
windowHeight: systemInfo.windowHeight,
scale,
ratio:2
},
/**
* 组件的方法列表
*/
methods: {
hidden() {
// this.triggerEvent("hiddenSnaphotSheet");
event.emit(SHARE_CANCEL_MOMENTS);
},
saveToAlbum() {
var that = this;
if (wx.getSetting) {
wx.getSetting({
success(res) {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success: function (res) {
that.saveSnapShoot();
},
fail: function (error) {
if (res.authSetting['scope.writePhotosAlbum'] == false) {
wx.showModal({
title: '',
content: '需要打开小程序的设置,重新授权访问您的系统相册',
confirmText: "去开启",
confirmColor: "#000000",
success: function (res) {
if (res.confirm) {
wx.openSetting({
success: function (res) {
}
});
}
}
});
}
},
})
} else {
that.saveSnapShoot();
}
}
})
} else {
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
},
saveSnapShoot() {
var that = this;
var canvasWidth = windowWidth * that.data.ratio;
var canvasHeight = screenHeight * that.data.ratio;
var destWidth = windowWidth * 2 * that.data.ratio;
var destHeight = screenHeight * 2 * that.data.ratio;
var canvasId = 'productDetailCanvas';
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
destWidth: destWidth,
destHeight: destHeight,
quality: 1.0,
canvasId: canvasId,
success: function (result) {
wx.saveImageToPhotosAlbum({
filePath: result.tempFilePath,
success(res) {
wx.showToast({
title:
'保存成功',
icon:
'success',
duration:
2000
})
that.hidden();
},
fail: function (err) {
that.hidden();
}
}, );
},
fail: function (error) {
that.hidden();
},
complete: function (res) {
that.hidden();
}
}, this);
},
_creatSnapshoot: function(newValue, oldValue) {
if(newValue) {
this.creatProductDetailSnapShoot();
}
},
creatProductDetailSnapShoot() {
var that = this;
var product = that.properties.shareData;
console.log('====================================');
console.log(product);
console.log('====================================');
if(!product){
return
}
let ratio = this.data.ratio
let snapWidth = this.data.windowWidth * ratio
let snapHeight = this.data.screenHeight * ratio
let middle = snapWidth / 2
scale = snapWidth / 262.5
HScale = scale
// console.log(windowWidth,screenHeight,snapWidth,snapHeight,scale)
let logoHeight = 15.4 * HScale;
let logoWidth = 78.4 * scale;
let logoTop = 25.2 * HScale;
let logoMarginBottom = 21 * HScale;
let logoLeft = (snapWidth - logoWidth) / 2 //logo左边坐标
let imgContainerWidth = 227.5 * scale;
let imgContainerHeight = 303.1 * HScale
let imgContainerLeft = (snapWidth - imgContainerWidth) / 2 //图片容器左边位置
let imgContainerTop = logoHeight + logoTop + logoMarginBottom //图片容器顶部位置
let namePriceBgHeight = 56 * HScale
let namePriceBgTop = imgContainerTop + (imgContainerHeight - namePriceBgHeight)
let x = 10 * scale
let nameTop = imgContainerTop + 255*scale + x
let priceTop = imgContainerTop + 280* scale + x
//以下为小程序码相关
let qrImgMarginTop = 21 * HScale
let qrCodeTop = imgContainerTop + imgContainerHeight + qrImgMarginTop
let qrImgWH = 56 * scale
let tipX = 10 * scale
let tipLeft = imgContainerLeft + qrImgWH + 13.7 * scale
let tip1Top = imgContainerTop + imgContainerHeight + 34.2*scale + tipX
let tip2Top = imgContainerTop + imgContainerHeight + 52.5 * scale + tipX
var pCtx = wx.createCanvasContext("productDetailCanvas", this);
pCtx.setFillStyle('white');
pCtx.fillRect(0, 0, snapWidth, snapHeight);
/*---------开始新的作画-----------*/
pCtx.drawImage('../../../assets/images/share-logo@2x.png',logoLeft , logoTop, logoWidth, logoHeight)//画logo
pCtx.setFillStyle('white');
pCtx.setStrokeStyle('#e0e0e0')
// pCtx.fillRect(imgContainerLeft,imgContainerTop,320*scale,430*scale)//图片容器
pCtx.strokeRect(imgContainerLeft, imgContainerTop, imgContainerWidth , imgContainerHeight)//图片容器
var defaultImage = getImgUrl(product.default_image, imgContainerWidth, imgContainerHeight);
if (defaultImage && defaultImage.indexOf("https://") == -1) {
defaultImage = defaultImage.replace('http://', 'https://');
}
product.default_image = defaultImage;
that.setData({
shareData: product
})
wx.getImageInfo({
src: defaultImage,
success:function(res){
pCtx.drawImage(res.path, imgContainerLeft, imgContainerTop, imgContainerWidth, imgContainerHeight)
pCtx.setFillStyle("rgba(34,34,34,0.8)");//画名称价格背景
pCtx.fillRect(imgContainerLeft, namePriceBgTop, imgContainerWidth, namePriceBgHeight)
pCtx.setFillStyle('white');
that.drawLongText(product.product_name, pCtx, middle, nameTop, 'white', 9.8, 30,1);
pCtx.setTextAlign('center');
pCtx.setFontSize(16.8 * scale);
pCtx.fillText(product.product_price, middle, priceTop);
pCtx.draw(true)
}
})
// wx.getImageInfo({
// src: product.product_qrCode,
// success:function(res){
// pCtx.drawImage(res.path, imgContainerLeft, qrCodeTop, qrImgWH, qrImgWH);//画小程序码
// pCtx.draw(true)
// }
// })
pCtx.setFillStyle('#444444')
pCtx.setFontSize(9.8*scale)
pCtx.fillText('长按扫码查看详情',tipLeft,tip1Top)
pCtx.setFillStyle('#b0b0b0')
pCtx.setFontSize(8.4*scale)
pCtx.fillText('实际价格以页面展示为准', tipLeft, tip2Top)
pCtx.draw()
/*---------结束新的作画-----------*/
},
drawLongText(longtext, cxt, begin_width, begin_height, color, fontSize, numsForLine,numberOfLine,
isCenter = true,lineL = 0) {
let linelenght = lineL;//行间距
if (linelenght == 0){
linelenght = (fontSize + 2) * scale
}
if(!numberOfLine){
numberOfLine = 2;
}
var text = "";
var count = 0;
var lineNumber = 1;
var begin_width = begin_width;
var begin_height = begin_height;
var stringLenght = longtext.length;
var newtext = longtext.split("");
cxt.setFillStyle(color);
cxt.setFontSize(fontSize * scale);
if(isCenter){
cxt.setTextAlign('center');
}
for (var i = 0; i <= stringLenght; i++) {
if (count == numsForLine) {
if (lineNumber === numberOfLine) {
var t = text + '...';
cxt.fillText(t, begin_width, begin_height);
} else {
cxt.fillText(text, begin_width, begin_height);
}
begin_height = begin_height + linelenght;
text = "";
count = 0;
lineNumber ++;
}
if (i == stringLenght) {
cxt.fillText(text, begin_width, begin_height);
}
text = text + newtext[0];
count++;
newtext.shift();
if(lineNumber > numberOfLine){
break;
}
}
}
}
})
... ...
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file
... ...
<view class="snapshoot-container" style="display: {{isShow ? 'block' : 'none'}}" >
<view class="snapshoot-container">
<view class="snapshoot-content">
<!--商品详情开始 -->
<view class="snapshoot">
<image class="yoho-logo" style='margin-top:50.4rpx' src="../../../assets/images/share-logo@2x.png"></image>
<view class="snapshoot-productinfo">
<image class="product-defaultImage" src="{{shareData.default_image}}"> </image>
<view class="product-info-content">
<text class="product-name">{{shareData.product_name}}</text>
<text class="product-price">{{shareData.product_price}}</text>
</view>
</view>
<view class='product-miniqr-new'>
<image class="product-qrcode" src="{{shareData.product_qrCode}}"></image>
<view class='product-tips-new'>
<text class="snapshoot-tips-new">长按扫码查看详情</text>
<text class="product-tips-text-new" style='margin-top:10.4rpx;margin-left:0rpx'>实际价格以页面展示为准</text>
</view>
</view>
</view>
</view>
<!--底部按钮 -->
<view class="snapshoot-bottom">
<view class="snapshoot-save" bindtap="saveToAlbum">
<!-- <image class="img" src="./images/down@2x.png"></image> -->
<text class="text">保存到相册</text>
</view>
<view class="snapshoot-cancel" bindtap="hidden">
<text class="cancel-text">取消</text>
</view>
</view>
</view>
</view>
<block>
<canvas canvas-id="productDetailCanvas" style="width: {{windowWidth*ratio}}px;height:{{screenHeight*ratio}}px;background-color: white;margin-top: 10000px;margin-left:10000px;position:fixed"></canvas>
</block>
... ...
.snapshoot-container {
position: fixed;
left: 0rpx;
top: 0rpx;
width: 750rpx;
height: 1206rpx;
background-color: rgba(0, 0, 0, 0.5);
flex-direction: column;
z-index: 9999;
}
.snapshoot-container .snapshoot-content {
margin-top: 40rpx;
margin-left: 112.5rpx;
width: 525rpx;
height:auto;
background-color: white;
flex-direction: column;
padding-bottom: 36rpx;
/* height:960rpx */
}
.snapshoot-container .snapshoot-content .snapshoot {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.snapshoot-container .snapshoot-content .snapshoot .img-bg {
width: 100%;
height: 142rpx;
}
.snapshoot-container .snapshoot-content .snapshoot .snapshoot-shopinfo {
margin-top: 30rpx;
width: 460rpx;
height: wrap;
background-color: white;
border: 0.5rpx solid #e5e5e5;
display: flex;
flex-direction: column;
align-items: center;
/* box-shadow:5px 5px 3px lightgray; */
}
.snapshoot-container .snapshoot-content .snapshoot .snapshoot-shopinfo .img-logo {
margin-top: 30rpx;
width: 200rpx;
height: 168rpx;
}
.snapshoot-container .snapshoot-content .snapshoot .snapshoot-shopinfo .shop-name {
margin-top: 35.8rpx;
font-size: 25.2rpx;
font-weight: bold;
text-align: center;
font-family: PingFang-SC-Semibold;
color: #444444
}
.snapshoot-container .snapshoot-content .snapshoot .snapshoot-shopinfo .shop-intro {
/* margin-top: 61rpx; */
font-size: 19.6rpx;
/* font-weight: bold; */
text-align: center;
width: 399rpx;
height: wrap;
line-height:33.6rpx;
display: -webkit-box;
overflow: hidden;
text-overflow:ellipsis;
white-space: pre-wrap;
-webkit-box-orient: vertical;
-webkit-line-clamp: 5;
}
.yoho-logo {
width: 156.8rpx;
height: 30rpx;
margin-top: 21rpx;
}
.product-qrcode {
width: 112rpx;
height: 112rpx;
}
.snapshoot-container .snapshoot-save {
width: 250rpx;
height: 88rpx;
background-color: red;
border-radius: 10rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.snapshoot-container .snapshoot-cancel {
margin-left: 25rpx;
width: 250rpx;
height: 88rpx;
background-color: white;
border-radius: 10rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center
}
.img {
width: 41rpx;
height: 38rpx;
}
.text {
font: 28rpx;
color: white;
text-align: center;
}
.cancel-text {
font: 28rpx;
color: black;
text-align: center;
}
.snapshoot-tips {
margin-top: 16rpx;
font-size: 16rpx;
color: #444444;
}
.snapshoot-tips-new{
font-family: PingFang-SC-Regular;
font-size: 20rpx;
color: #444444;
letter-spacing: 0;
text-align: center;
}
.snapshoot-productinfo {
margin-top: 42rpx;
width: 455rpx;
height: 606.2rpx;
background-color: white;
display: flex;
flex-direction: column;
align-items: center;
border: 0rpx solid #e0e0e0;
}
.product-defaultImage {
width: 100%;
height: 100%
}
.product-info-content {
width: 100%;
height: 112rpx;
margin-top: -112rpx;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
align-items: center;
}
.product-name {
width: 90%;
margin-top: 16.8rpx;
color: #FFFFFF;
text-align: center;
font-size: 20rpx;
/* margin-bottom: 20rpx; */
line-height: 32rpx;
display: -webkit-box;
overflow: hidden;
text-overflow:ellipsis;
white-space: pre-wrap;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
.product-price {
color: #FFFFFF;
text-align: center;
font-size: 30rpx;
margin-top: 10rpx;
}
.product-tips {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin-top: 10rpx;
}
.product-tips-img {
width: 18rpx;
height: 18rpx;
}
.product-tips-text {
font-size: 16rpx;
color: #b0b0b0;
margin-left: 10rpx;
}
.product-tips-text-new {
font-family: PingFang-SC-Regular;
font-size: 16rpx;
color: #B0B0B0;
letter-spacing: 0;
}
.snapshoot-bottom {
margin-left: 112.5rpx;
margin-top: 25rpx;
width: 525rpx;
height: 88rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.product-miniqr-new{
height:112rpx;
margin-top:42rpx;
display: flex;
flex-direction: row;
align-items: center;
width:455rpx;
/* margin-left:112.5rpx; */
}
.product-tips-new {
margin-left:27.4rpx;
width:wrap;
display: flex;
flex-direction: column;
align-items: flex-start
}
\ No newline at end of file
... ...
export const SHOWSIZEBOX = 'SHOWSIZEBOX'
export const SHOWSHARESHEET = 'SHOWSHARESHEET'
\ No newline at end of file
export const SHOWSHARESHEET = 'SHOWSHARESHEET'
export const SHOWSNAPSHOT = 'SHOWSNAPSHOT'
... ...
... ... @@ -54,9 +54,6 @@ export default class Search extends Component {
let {setFilter} = this.props;
setFilter(filter);
console.log('====================================');
console.log(filter);
console.log('====================================');
wx.navigateBack({
delta: 1
})
... ...
... ... @@ -4,7 +4,7 @@ import {productDetail as productDetailModel} from '../../models';
import {getImgUrl} from '../../utils';
import {ProductList, SelectSize} from '../../components';
import { connect } from '@tarojs/redux';
import { showSizeBox, showSharesheet } from '../../actions/productDetail'
import { showSizeBox, showSharesheet, showSnapshot } from '../../actions/productDetail'
import share from '../../static/images/share.png';
... ... @@ -16,6 +16,8 @@ import event from '../../utils/event'
const SHARE_FRIENDS = 'user-share-friends';
const SHARE_MOMENTS = 'user-share-moments';
const SHARE_CANCEL = 'user-canel-share';
const SHARE_CANCEL_MOMENTS = 'user-canel-share-moments';
@connect(({ productDetail }) => ({
productDetail
}), (dispatch) => ({
... ... @@ -24,6 +26,9 @@ const SHARE_CANCEL = 'user-canel-share';
},
showSharesheet (isShow) {
dispatch(showSharesheet(isShow))
},
showSnapshot (isShow) {
dispatch(showSnapshot(isShow))
}
}))
... ... @@ -37,7 +42,7 @@ export default class ProductDetail extends Component {
recommendList: [],
collectTitle: '收藏',
isFavorite: false,
isShare: false,
snapshootShareData: {},
productDec: {
color: {
text: '颜色',
... ... @@ -65,7 +70,8 @@ export default class ProductDetail extends Component {
config = {
usingComponents: {
'share-sheet' : '../../components/shareSheet/shareSheet'
'share-sheet' : '../../components/shareSheet/shareSheet',
'snapshoot-share' : '../../components/shareSheet/snapshootShare/snapshootShare'
}
}
componentDidMount() {
... ... @@ -85,6 +91,9 @@ export default class ProductDetail extends Component {
event.on(SHARE_MOMENTS, () => {
this.shareMomentsCallback();
});
event.on(SHARE_CANCEL_MOMENTS, () => {
this.hiddenSnaphotSheet();
});
}
getProductData(id) {
... ... @@ -93,13 +102,35 @@ export default class ProductDetail extends Component {
let data = ret.data || {};
let productInfo = data && data.product_info || {};
let goodsList = productInfo.goods_list && productInfo.goods_list.length > 0 && productInfo.goods_list[0] || {};
let imageSize = goodsList.image_list.length;
let imageSize = goodsList.image_list.length;
let default_image = imageSize > 0 ? goodsList.image_list[0]['image_url'] : '';
var product_qrCode = ''
// if (app.globalData.user_union_type) {
// let page_param = {
// union_type: app.globalData.user_union_type,
// productSkn: data.data.product_id,
// }
// product_qrCode = API_HOST + '/wechat/miniapp/img-check.jpg?param=' + encodeURIComponent(JSON.stringify(page_param)) + '&miniQrType=7';
// } else {
// product_qrCode = API_HOST + '/wechat/miniapp/img-check.jpg?param=' + data.data.product_id;
// }
var shareData = {
product_name : productInfo.product_name,
product_price: '¥'+productInfo.max_price,
product_mprice: (productInfo.min_price === '0' || productInfo.max_price == productInfo.min_price ? '0' : '¥' + productInfo.min_price),
default_image,
product_qrCode,
product_skn: productInfo.product_id
}
this.setState({
productInfo: productInfo,
imageSize: imageSize,
goodsList: goodsList,
swiperNum: `1 | ${imageSize}`,
snapshootShareData: shareData,
productDec: [
{
text: '颜色',
... ... @@ -222,11 +253,16 @@ export default class ProductDetail extends Component {
showSharesheet(false);
}
//点击组件的分享朋友圈回调处理
//点击组件的分享朋友圈回调
shareMomentsCallback() {
console.log('====================================');
console.log('分享到朋友圈');
console.log('====================================');
let {showSnapshot} = this.props;
showSnapshot(true);
}
//取消分享朋友圈回调
hiddenSnaphotSheet() {
let {showSnapshot} = this.props;
showSnapshot(false);
}
onClickBuy() {
... ... @@ -304,6 +340,11 @@ export default class ProductDetail extends Component {
}
{
this.props.productDetail.showSnapshot &&
<snapshoot-share isShow={this.props.productDetail.showSnapshot} shareData={snapshootShareData} bindhiddenSnaphotSheet='hiddenSnaphotSheet'></snapshoot-share>
}
{
this.props.productDetail.showSizeBox &&
<SelectSize sizeList={goodsList.size_list} product_id={id}></SelectSize>
}
... ...
import { SHOWSIZEBOX, SHOWSHARESHEET } from '../constants/productDetail'
import { SHOWSIZEBOX, SHOWSHARESHEET, SHOWSNAPSHOT } from '../constants/productDetail'
const INITIAL_STATE = {
showSizeBox: false,
showSharesheet: false
showSharesheet: false,
showSnapshot: false
}
export default function productDetail (state = INITIAL_STATE, action) {
... ... @@ -13,10 +14,16 @@ export default function productDetail (state = INITIAL_STATE, action) {
showSizeBox: action.isShow
}
case SHOWSHARESHEET:
return {
...state,
showSharesheet: action.isShow
return {
...state,
showSharesheet: action.isShow
}
case SHOWSNAPSHOT:
return {
...state,
showSnapshot: action.isShow
}
default:
return state
}
... ...