如图微信小程序生成海报自定义调整位置
//微信小程序组件 poster.wxml<view style='position: relative;{{customStyle}};{{painterStyle}}'><block wx:if="{{!use2D}}"><canvas canvas-id="photo" style="{{photoStyle}};position: absolute; left: -9999px; top: -9999rpx;" /><block wx:if="{{dancePalette}}"><canvas canvas-id="bottom" style="{{painterStyle}};position: absolute;" /><canvas canvas-id="k-canvas" style="{{painterStyle}};position: absolute;" /><canvas canvas-id="top" style="{{painterStyle}};position: absolute;" /><canvas canvas-id="front" style="{{painterStyle}};position: absolute;"bindtouchstart="onTouchStart"bindtouchmove="onTouchMove"bindtouchend="onTouchEnd"bindtouchcancel="onTouchCancel"disable-scroll="{{true}}" /></block></block><block wx:if="{{use2D}}"><canvas type="2d" id="photo" style="{{photoStyle}};" /></block>
</view>
//组件poster.jsimport Pen, { penCache, clearPenCache } from './lib/pen';
import Downloader from './lib/downloader';
import WxCanvas from './lib/wx-canvas';const util = require('./lib/util');
const calc = require('./lib/calc');const downloader = new Downloader();// 最大尝试的绘制次数
const MAX_PAINT_COUNT = 5;
const ACTION_DEFAULT_SIZE = 24;
const ACTION_OFFSET = '2rpx';
Component({canvasWidthInPx: 0,canvasHeightInPx: 0,canvasNode: null,paintCount: 0,currentPalette: {},outterDisabled: false,isDisabled: false,needClear: false,/*** 组件的属性列表*/properties: {use2D: {type: Boolean,},customStyle: {type: String,},// 运行自定义选择框和删除缩放按钮customActionStyle: {type: Object,},palette: {type: Object,observer: function (newVal, oldVal) {if (this.isNeedRefresh(newVal, oldVal)) {this.paintCount = 0;clearPenCache();this.startPaint();}},},dancePalette: {type: Object,observer: function (newVal, oldVal) {if (!this.isEmpty(newVal) && !this.properties.use2D) {clearPenCache();this.initDancePalette(newVal);}},},// 缩放比,会在传入的 palette 中统一乘以该缩放比scaleRatio: {type: Number,value: 1,},widthPixels: {type: Number,value: 0,},// 启用脏检查,默认 falsedirty: {type: Boolean,value: false,},LRU: {type: Boolean,value: false,},action: {type: Object,observer: function (newVal, oldVal) {if (newVal && !this.isEmpty(newVal) && !this.properties.use2D) {this.doAction(newVal, null, false, true);}},},disableAction: {type: Boolean,observer: function (isDisabled) {this.outterDisabled = isDisabled;this.isDisabled = isDisabled;},},clearActionBox: {type: Boolean,observer: function (needClear) {if (needClear && !this.needClear) {if (this.frontContext) {setTimeout(() => {this.frontContext.draw();}, 100);this.touchedView = {};this.prevFindedIndex = this.findedIndex;this.findedIndex = -1;}}this.needClear = needClear;},},},data: {picURL: '',showCanvas: true,painterStyle: '',},methods: {/*** 判断一个 object 是否为 空* @param {object} object*/isEmpty(object) {for (const i in object) {return false;}return true;},isNeedRefresh(newVal, oldVal) {if (!newVal || this.isEmpty(newVal) || (this.data.dirty && util.equal(newVal, oldVal))) {return false;}return true;},getBox(rect, type) {const boxArea = {type: 'rect',css: {height: `${rect.bottom - rect.top}px`,width: `${rect.right - rect.left}px`,left: `${rect.left}px`,top: `${rect.top}px`,borderWidth: '4rpx',borderColor: '#1A7AF8',color: 'transparent',},};if (type === 'text') {boxArea.css = Object.assign({}, boxArea.css, {borderStyle: 'dashed',});}if (this.properties.customActionStyle && this.properties.customActionStyle.border) {boxArea.css = Object.assign({}, boxArea.css, this.properties.customActionStyle.border);}Object.assign(boxArea, {id: 'box',});return boxArea;},getScaleIcon(rect, type) {let scaleArea = {};const { customActionStyle } = this.properties;if (customActionStyle && customActionStyle.scale) {scaleArea = {type: 'image',url: type === 'text' ? customActionStyle.scale.textIcon : customActionStyle.scale.imageIcon,css: {height: `${2 * ACTION_DEFAULT_SIZE}rpx`,width: `${2 * ACTION_DEFAULT_SIZE}rpx`,borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,},};} else {scaleArea = {type: 'rect',css: {height: `${2 * ACTION_DEFAULT_SIZE}rpx`,width: `${2 * ACTION_DEFAULT_SIZE}rpx`,borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,color: '#0000ff',},};}scaleArea.css = Object.assign({}, scaleArea.css, {align: 'center',left: `${rect.right + ACTION_OFFSET.toPx()}px`,top:type === 'text'? `${rect.top - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px`: `${rect.bottom - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px`,});Object.assign(scaleArea, {id: 'scale',});return scaleArea;},getDeleteIcon(rect) {let deleteArea = {};const { customActionStyle } = this.properties;if (customActionStyle && customActionStyle.scale) {deleteArea = {type: 'image',url: customActionStyle.delete.icon,css: {height: `${2 * ACTION_DEFAULT_SIZE}rpx`,width: `${2 * ACTION_DEFAULT_SIZE}rpx`,borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,},};} else {deleteArea = {type: 'rect',css: {height: `${2 * ACTION_DEFAULT_SIZE}rpx`,width: `${2 * ACTION_DEFAULT_SIZE}rpx`,borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,color: '#0000ff',},};}deleteArea.css = Object.assign({}, deleteArea.css, {align: 'center',left: `${rect.left - ACTION_OFFSET.toPx()}px`,top: `${rect.top - ACTION_OFFSET.toPx() - deleteArea.css.height.toPx() / 2}px`,});Object.assign(deleteArea, {id: 'delete',});return deleteArea;},doAction(action, callback, isMoving, overwrite) {if (this.properties.use2D) {return;}let newVal = null;if (action) {newVal = action.view;}if (newVal && newVal.id && this.touchedView.id !== newVal.id) {// 带 id 的动作给撤回时使用,不带 id,表示对当前选中对象进行操作const { views } = this.currentPalette;for (let i = 0; i < views.length; i++) {if (views[i].id === newVal.id) {// 跨层回撤,需要重新构建三层关系this.touchedView = views[i];this.findedIndex = i;this.sliceLayers();break;}}}const doView = this.touchedView;if (!doView || this.isEmpty(doView)) {return;}if (newVal && newVal.css) {if (overwrite) {doView.css = newVal.css;} else if (Array.isArray(doView.css) && Array.isArray(newVal.css)) {doView.css = Object.assign({}, ...doView.css, ...newVal.css);} else if (Array.isArray(doView.css)) {doView.css = Object.assign({}, ...doView.css, newVal.css);} else if (Array.isArray(newVal.css)) {doView.css = Object.assign({}, doView.css, ...newVal.css);} else {doView.css = Object.assign({}, doView.css, newVal.css);}}if (newVal && newVal.rect) {doView.rect = newVal.rect;}if (newVal && newVal.url && doView.url && newVal.url !== doView.url) {downloader.download(newVal.url, this.properties.LRU).then(path => {if (newVal.url.startsWith('https')) {doView.originUrl = newVal.url;}doView.url = path;wx.getImageInfo({src: path,success: res => {doView.sHeight = res.height;doView.sWidth = res.width;this.reDraw(doView, callback, isMoving);},fail: () => {this.reDraw(doView, callback, isMoving);},});}).catch(error => {// 未下载成功,直接绘制console.error(error);this.reDraw(doView, callback, isMoving);});} else {newVal && newVal.text && doView.text && newVal.text !== doView.text && (doView.text = newVal.text);newVal &&newVal.content &&doView.content &&newVal.content !== doView.content &&(doView.content = newVal.content);this.reDraw(doView, callback, isMoving);}},reDraw(doView, callback, isMoving) {const draw = {width: this.currentPalette.width,height: this.currentPalette.height,views: this.isEmpty(doView) ? [] : [doView],};const pen = new Pen(this.globalContext, draw);pen.paint(callbackInfo => {callback && callback(callbackInfo);this.triggerEvent('viewUpdate', {view: this.touchedView,});});const { rect, css, type } = doView;this.block = {width: this.currentPalette.width,height: this.currentPalette.height,views: this.isEmpty(doView) ? [] : [this.getBox(rect, doView.type)],};if (css && css.scalable) {this.block.views.push(this.getScaleIcon(rect, type));}if (css && css.deletable) {this.block.views.push(this.getDeleteIcon(rect));}const topBlock = new Pen(this.frontContext, this.block);topBlock.paint();},isInView(x, y, rect) {return x > rect.left && y > rect.top && x < rect.right && y < rect.bottom;},isInDelete(x, y) {for (const view of this.block.views) {if (view.id === 'delete') {return x > view.rect.left && y > view.rect.top && x < view.rect.right && y < view.rect.bottom;}}return false;},isInScale(x, y) {for (const view of this.block.views) {if (view.id === 'scale') {return x > view.rect.left && y > view.rect.top && x < view.rect.right && y < view.rect.bottom;}}return false;},touchedView: {},findedIndex: -1,onClick() {const x = this.startX;const y = this.startY;const totalLayerCount = this.currentPalette.views.length;let canBeTouched = [];let isDelete = false;let deleteIndex = -1;for (let i = totalLayerCount - 1; i >= 0; i--) {const view = this.currentPalette.views[i];const { rect } = view;if (this.touchedView && this.touchedView.id && this.touchedView.id === view.id && this.isInDelete(x, y, rect)) {canBeTouched.length = 0;deleteIndex = i;isDelete = true;break;}if (this.isInView(x, y, rect)) {canBeTouched.push({view,index: i,});}}this.touchedView = {};if (canBeTouched.length === 0) {this.findedIndex = -1;} else {let i = 0;const touchAble = canBeTouched.filter(item => Boolean(item.view.id));if (touchAble.length === 0) {this.findedIndex = canBeTouched[0].index;} else {for (i = 0; i < touchAble.length; i++) {if (this.findedIndex === touchAble[i].index) {i++;break;}}if (i === touchAble.length) {i = 0;}this.touchedView = touchAble[i].view;this.findedIndex = touchAble[i].index;this.triggerEvent('viewClicked', {view: this.touchedView,});}}if (this.findedIndex < 0 || (this.touchedView && !this.touchedView.id)) {// 证明点击了背景 或无法移动的viewthis.frontContext.draw();if (isDelete) {this.triggerEvent('touchEnd', {view: this.currentPalette.views[deleteIndex],index: deleteIndex,type: 'delete',});this.doAction();} else if (this.findedIndex < 0) {this.triggerEvent('viewClicked', {});}this.findedIndex = -1;this.prevFindedIndex = -1;} else if (this.touchedView && this.touchedView.id) {this.sliceLayers();}},sliceLayers() {const bottomLayers = this.currentPalette.views.slice(0, this.findedIndex);const topLayers = this.currentPalette.views.slice(this.findedIndex + 1);const bottomDraw = {width: this.currentPalette.width,height: this.currentPalette.height,background: this.currentPalette.background,views: bottomLayers,};const topDraw = {width: this.currentPalette.width,height: this.currentPalette.height,views: topLayers,};if (this.prevFindedIndex < this.findedIndex) {new Pen(this.bottomContext, bottomDraw).paint();this.doAction();new Pen(this.topContext, topDraw).paint();} else {new Pen(this.topContext, topDraw).paint();this.doAction();new Pen(this.bottomContext, bottomDraw).paint();}this.prevFindedIndex = this.findedIndex;},startX: 0,startY: 0,startH: 0,startW: 0,isScale: false,startTimeStamp: 0,onTouchStart(event) {if (this.isDisabled) {return;}const { x, y } = event.touches[0];this.startX = x;this.startY = y;this.startTimeStamp = new Date().getTime();if (this.touchedView && !this.isEmpty(this.touchedView)) {const { rect } = this.touchedView;if (this.isInScale(x, y, rect)) {this.isScale = true;this.startH = rect.bottom - rect.top;this.startW = rect.right - rect.left;} else {this.isScale = false;}} else {this.isScale = false;}},onTouchEnd(e) {if (this.isDisabled) {return;}const current = new Date().getTime();if (current - this.startTimeStamp <= 500 && !this.hasMove) {!this.isScale && this.onClick(e);} else if (this.touchedView && !this.isEmpty(this.touchedView)) {this.triggerEvent('touchEnd', {view: this.touchedView,});}this.hasMove = false;},onTouchCancel(e) {if (this.isDisabled) {return;}this.onTouchEnd(e);},hasMove: false,onTouchMove(event) {if (this.isDisabled) {return;}this.hasMove = true;if (!this.touchedView || (this.touchedView && !this.touchedView.id)) {return;}const { x, y } = event.touches[0];const offsetX = x - this.startX;const offsetY = y - this.startY;const { rect, type } = this.touchedView;let css = {};if (this.isScale) {clearPenCache(this.touchedView.id);const newW = this.startW + offsetX > 1 ? this.startW + offsetX : 1;if (this.touchedView.css && this.touchedView.css.minWidth) {if (newW < this.touchedView.css.minWidth.toPx()) {return;}}if (this.touchedView.rect && this.touchedView.rect.minWidth) {if (newW < this.touchedView.rect.minWidth) {return;}}const newH = this.startH + offsetY > 1 ? this.startH + offsetY : 1;css = {width: `${newW}px`,};if (type !== 'text') {if (type === 'image') {css.height = `${(newW * this.startH) / this.startW}px`;} else {css.height = `${newH}px`;}}} else {this.startX = x;this.startY = y;css = {left: `${rect.x + offsetX}px`,top: `${rect.y + offsetY}px`,right: undefined,bottom: undefined,};}this.doAction({view: {css,},},null,!this.isScale,);},initScreenK() {if (!(getApp() && getApp().systemInfo && getApp().systemInfo.screenWidth)) {try {getApp().systemInfo = wx.getSystemInfoSync();} catch (e) {console.error(`Painter get system info failed, ${JSON.stringify(e)}`);return;}}this.screenK = 0.5;if (getApp() && getApp().systemInfo && getApp().systemInfo.screenWidth) {this.screenK = getApp().systemInfo.screenWidth / 750;}setStringPrototype(this.screenK, this.properties.scaleRatio);},initDancePalette() {if (this.properties.use2D) {return;}this.isDisabled = true;this.initScreenK();this.downloadImages(this.properties.dancePalette).then(async palette => {this.currentPalette = palette;const { width, height } = palette;if (!width || !height) {console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`);return;}this.setData({painterStyle: `width:${width.toPx()}px;height:${height.toPx()}px;`,});this.frontContext || (this.frontContext = await this.getCanvasContext(this.properties.use2D, 'front'));this.bottomContext || (this.bottomContext = await this.getCanvasContext(this.properties.use2D, 'bottom'));this.topContext || (this.topContext = await this.getCanvasContext(this.properties.use2D, 'top'));this.globalContext || (this.globalContext = await this.getCanvasContext(this.properties.use2D, 'k-canvas'));new Pen(this.bottomContext, palette, this.properties.use2D).paint(() => {this.isDisabled = false;this.isDisabled = this.outterDisabled;this.triggerEvent('didShow');});this.globalContext.draw();this.frontContext.draw();this.topContext.draw();});this.touchedView = {};},startPaint() {this.initScreenK();const { width, height } = this.properties.palette;if (!width || !height) {console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`);return;}let needScale = false;// 生成图片时,根据设置的像素值重新绘制if (width.toPx() !== this.canvasWidthInPx) {this.canvasWidthInPx = width.toPx();needScale = this.properties.use2D;}if (this.properties.widthPixels) {setStringPrototype(this.screenK, this.properties.widthPixels / this.canvasWidthInPx);this.canvasWidthInPx = this.properties.widthPixels;}if (this.canvasHeightInPx !== height.toPx()) {this.canvasHeightInPx = height.toPx();needScale = needScale || this.properties.use2D;}this.setData({photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`,},function () {this.downloadImages(this.properties.palette).then(async palette => {if (!this.photoContext) {this.photoContext = await this.getCanvasContext(this.properties.use2D, 'photo');}if (needScale) {const scale = getApp().systemInfo.pixelRatio;this.photoContext.width = this.canvasWidthInPx * scale;this.photoContext.height = this.canvasHeightInPx * scale;this.photoContext.scale(scale, scale);}new Pen(this.photoContext, palette).paint(() => {this.saveImgToLocal();});setStringPrototype(this.screenK, this.properties.scaleRatio);});},);},downloadImages(palette) {return new Promise((resolve, reject) => {let preCount = 0;let completeCount = 0;const paletteCopy = JSON.parse(JSON.stringify(palette));if (paletteCopy.background) {preCount++;downloader.download(paletteCopy.background, this.properties.LRU).then(path => {paletteCopy.background = path;completeCount++;if (preCount === completeCount) {resolve(paletteCopy);}},() => {completeCount++;if (preCount === completeCount) {resolve(paletteCopy);}},);}if (paletteCopy.views) {for (const view of paletteCopy.views) {if (view && view.type === 'image' && view.url) {preCount++;/* eslint-disable no-loop-func */downloader.download(view.url, this.properties.LRU).then(path => {view.originUrl = view.url;view.url = path;wx.getImageInfo({src: path,success: res => {// 获得一下图片信息,供后续裁减使用view.sWidth = res.width;view.sHeight = res.height;},fail: error => {// 如果图片坏了,则直接置空,防止坑爹的 canvas 画崩溃了console.warn(`getImageInfo ${view.originUrl} failed, ${JSON.stringify(error)}`);view.url = '';},complete: () => {completeCount++;if (preCount === completeCount) {resolve(paletteCopy);}},});},() => {completeCount++;if (preCount === completeCount) {resolve(paletteCopy);}},);}}}if (preCount === 0) {resolve(paletteCopy);}});},saveImgToLocal() {const that = this;const optionsOf2d = {canvas: that.canvasNode,}const optionsOfOld = {canvasId: 'photo',destWidth: that.canvasWidthInPx,destHeight: that.canvasHeightInPx,}setTimeout(() => {wx.canvasToTempFilePath({...(that.properties.use2D ? optionsOf2d : optionsOfOld),success: function (res) {that.getImageInfo(res.tempFilePath);},fail: function (error) {console.error(`canvasToTempFilePath failed, ${JSON.stringify(error)}`);that.triggerEvent('imgErr', {error: error,});},},this,);}, 300);},getCanvasContext(use2D, id) {const that = this;return new Promise(resolve => {if (use2D) {const query = wx.createSelectorQuery().in(that);const selectId = `#${id}`;query.select(selectId).fields({ node: true, size: true }).exec(res => {that.canvasNode = res[0].node;const ctx = that.canvasNode.getContext('2d');const wxCanvas = new WxCanvas('2d', ctx, id, true, that.canvasNode);resolve(wxCanvas);});} else {const temp = wx.createCanvasContext(id, that);resolve(new WxCanvas('mina', temp, id, true));}});},getImageInfo(filePath) {const that = this;wx.getImageInfo({src: filePath,success: infoRes => {if (that.paintCount > MAX_PAINT_COUNT) {const error = `The result is always fault, even we tried ${MAX_PAINT_COUNT} times`;console.error(error);that.triggerEvent('imgErr', {error: error,});return;}// 比例相符时才证明绘制成功,否则进行强制重绘制if (Math.abs((infoRes.width * that.canvasHeightInPx - that.canvasWidthInPx * infoRes.height) /(infoRes.height * that.canvasHeightInPx),) < 0.01) {that.triggerEvent('imgOK', {path: filePath,});} else {that.startPaint();}that.paintCount++;},fail: error => {console.error(`getImageInfo failed, ${JSON.stringify(error)}`);that.triggerEvent('imgErr', {error: error,});},});},},
});function setStringPrototype(screenK, scale) {/* eslint-disable no-extend-native *//*** string 到对应的 px* @param {Number} baseSize 当设置了 % 号时,设置的基准值*/String.prototype.toPx = function toPx(_, baseSize) {if (this === '0') {return 0;}const REG = /-?[0-9]+(\.[0-9]+)?(rpx|px|%)/;const parsePx = origin => {const results = new RegExp(REG).exec(origin);if (!origin || !results) {console.error(`The size: ${origin} is illegal`);return 0;}const unit = results[2];const value = parseFloat(origin);let res = 0;if (unit === 'rpx') {res = Math.round(value * (screenK || 0.5) * (scale || 1));} else if (unit === 'px') {res = Math.round(value * (scale || 1));} else if (unit === '%') {res = Math.round((value * baseSize) / 100);}return res;};const formula = /^calc\((.+)\)$/.exec(this);if (formula && formula[1]) {// 进行 calc 计算const afterOne = formula[1].replace(/([^\s\(\+\-\*\/]+)\.(left|right|bottom|top|width|height)/g, word => {const [id, attr] = word.split('.');return penCache.viewRect[id][attr];});const afterTwo = afterOne.replace(new RegExp(REG, 'g'), parsePx);return calc(afterTwo);} else {return parsePx(this);}};
}
项目中引用:
<view class="shopView"><!-- 轮播 --><view class="swp"><zswiper style="position: relative;" SwiperList="{{shopBase.slider_image_arr}}" current="{{current}}" bind:monitorCurrent="monitorCurrent"></zswiper><view class="shopHead"><view><text>让利价:</text>¥{{shopBase.price}}</view><view>市场价: ¥{{shopBase.ot_price}}</view></view></view><!-- 介绍 --><view class="shopRemark"><view class="shopTitle hiddenD">{{shopBase.title}}</view><view class="shopbag">{{shopBase.keyword}}</view><view class="shopyy"><view class="shopRadioView">剩余{{shopBase.stock}}{{shopBase.unit_name}} | 月销量{{shopBase.ficti }}{{shopBase.unit_name}}</view></view><view class="shopyys"><view class="colView"><image src="../../images/all/hd.png" mode="" /> <text>品质保障</text></view><view class="colView"><image src="../../images/all/twy.png" mode="" /> <text>退换无忧</text></view><view class="colView"><image src="../../images/all/che.png" mode="" /> <text>直采直销</text></view></view></view><!-- 优惠券 -->
<!-- 优惠券-->
<view wx:if="{{couponList.money}}">
<view class="yhq animated heartBeats delay-5s" bindtap="getSelected" data-id="{{couponList.id}}"><image src="../../images/all/yhq.png" wx:if="{{couponList.status==0}}" mode=""/><image src="../../images/all/yyq.png" wx:else mode=""/><view class="copunBox"><view>{{couponList.money}}元{{couponList.name}}</view><view>部分商品通用</view></view>
</view></view><!-- end --><!-- <view class="chListBox" wx:if="{{couponList.length>0}}" style="margin-bottom: 20rpx;" bindtap="onClose"><view class="cliflex"><label>优惠</label><view class="cpubox"><view>满100减10</view><view class="bgap"></view><view>领券</view></view></view><view class="flexicon">去使用<image src="../../images/all/right.png" mode=""/></view></view> --><!-- 尺寸 --><!-- <view class="chList" style="margin-bottom: 20rpx;"><label>包装尺寸</label><text>100cm × 120cm × 60cm</text></view> --><view class="chList" style=" border-bottom-left-radius: 0;border-bottom-right-radius: 0;"><label>规格</label><text>默认规格</text></view><view class="border"></view><view class="chLists"><label>数量</label><text>(当前剩余{{shopBase.stock }}件)</text><view class="stepper"><van-stepper value="{{shopNum}}" bind:change="getShopNum" disable-input integer /></view></view><view class="chList" style="border-bottom-left-radius: 0;border-bottom-right-radius: 0;"><label>配送</label><text>商家配送</text></view><view class="border"></view><view class="chList" style="margin-bottom: 20rpx;"><label>服务</label><text> 支持7天无理由退货</text></view><!-- 详情 --><view class="shopBaseView"><view class="headT"><view class="text" style="font-weight: 600;">商品详情</view><view class="druk"></view></view><richtext rich_content="{{shopBase.newHtml}}" /></view><!-- 评价 --><!-- <view class="shopBaseView"><view class="headT"><view class="text" style="font-weight: 600;">商品</view><view class="druk"></view></view></view> --><!-- 操作 --><view class="submitView"><view class="iconviewtexts" bindtap="goHome"><button plain="true" class="iconviewtexts"><image src="../../images/all/sy.png" class="icons"></image><text lines="1" class="texty">首页</text></button></view><view><view class="iconviewtexts" bindtap="initCollect" style="margin-left: 0rpx;" data-item="{{shopBase}}" wx:if="{{collectStatus==0}}" data-type="{{1}}"><image src="../../images/all/ai.png" class="icons"></image><text lines="1" class="texty">收藏</text></view><view class="iconviewtexts" bindtap="initCollect" style="margin-left: 0rpx;" data-type="{{0}}" data-item="{{shopBase}}" wx:else><image src="../../images/all/xss.png" class="icons animated rubberBand"></image><text lines="1" class="texty">已收藏</text></view></view><view><view class="iconviewtexts" style="margin-left: 0;"><button plain="true" open-type="contact" class="iconviewtexts"><image src="../../images/all/tes.png" class="icons"></image><text lines="1" class="texty">客服</text></button></view></view><view class="aleview"><view bindtap="getshare" class="rViewBtn">分享得{{shopBase.rebate_money}}元<view class="bubble animated animate__rubberBand">本商品每分享成功一次可得{{shopBase.rebate_money}}元</view></view><!-- <button plain="true" class="rViewBtn" open-type="share">分享得9元</button> --><view class="rSelBtn" bindtap="getPayOrder" data-shopBase="{{shopBase}}">立即购买</view></view></view><!-- end -->
</view><!-- 海报 -->
<van-overlay show="{{ show }}" z-index="999" bind:click="onClickHide"><view class="wrapper"><view style="height: 72rpx;"></view><!-- poster --><view class="block" catch:tap="noop"><view class="closeView" bindtap="getClose"><image src="../../images/all/cha.png" mode="" /></view><view style="height: 30rpx;"></view><view style='position: relative;'><view class="top"><!-- <button bind:tap='onRevert'>撤销</button><button bind:tap='onRecover'>恢复</button> --><!-- <button bind:tap='saveImage'>保存</button> --></view><painter customActionStyle="{{customActionStyle}}" palette="{{paintPallette}}" bind:imgOK="onImgOK" wx:if="{{show}}" action="{{action}}" widthPixels="580" /><image wx:if="{{show}}" src="{{image}}" style="width: 640rpx; height:928rpx;" /></view><image class="logo" src="../../images/all/logo.png" mode="" /></view><!-- end --><!-- 底部弹窗 --><view class="bottomView"><view class="headBoxs"><text>分享给好友,好友注册并下单后您可得{{shopBase.rebate_money}}元</text></view><view class="fwidth"><van-row gutter="20"><van-col class="colConter iconshars" span="12"><button open-type='share' plain="true"><image class="shareicons" src="../../images/all/s1.png" mode="" /></button></van-col><!-- <van-col class="colConter iconshars" span="8"><button open-type='share' plain="true"><image class="shareicons" src="../../images/all/s2.png" mode="" /></button></van-col> --><van-col class="colConter" span="12" bind:tap='saveImage'><image class="shareicons" src="../../images/all/s3.png" mode="" /></van-col></van-row></view><view class="fwidth"><van-row gutter="20"><van-col class="colConter" span="12"><button open-type='share' plain="true">微信好友</button></van-col><!-- <van-col class="colConter" span="8" bindtap="shopShare"> <button open-type='share' plain="true">朋友圈</button></van-col> --><van-col class="colConter" span="12" bind:tap='saveImage'>保存图片</van-col></van-row></view></view><!-- end --></view></van-overlay><!-- 优惠券 -->
<!-- 自定义图标 -->
<van-popup show="{{ modelSHow }}" closeable round z-index="999" position="bottom" custom-style="height: 50%; background-color:#f5f5f5 ;" bind:close="onClose"><view class="headBox" bindtap="onClose">选择优惠券</view><scroll-view class="couBox" scroll-y="true" bindscrolltoupper="upper" bindscrolltolower="lower" bindscroll="scroll" scroll-into-view="{{toView}}" scroll-top="{{scrollTop}}"><sCouList List="{{couponList}}" bind:getSelected="getSelected"></sCouList></scroll-view><view class="btnBox"><view class="btnview" bindtap="onClose">确定</view></view>
</van-popup>
import {request
} from '../../utils/request'
Page({imagePath: '',history: [],future: [],isSave: false,/*** 页面的初始数据*/data: {drawing: [],show: false,modelSHow: false,savebtnText: '点击按钮,保存图片',//轮播图的数组shopBase: {},shopNum: 1,shopid: 0,coupon_id:0,couponList: {},collectStatus: 0,// 海报生成paintPallette: {width: '640rpx',height: '928rpx',background: '#f5f5f5',left: 0,views: [{type: 'rect',css: {width: '580rpx',left: '30rpx',top: '30rpx',height: '766rpx',color: "#fff",},},{type: 'image',url: 'https://shop.rlmeijia.com/statics/uploads/recommendimg/recommendimg20221111141855.jpg',css: {top: '30rpx',left: '30rpx',width: '580rpx',height: '580rpx',},},{type: 'text',text: '【现货】民福康 天然维生素E软胶囊 100粒装',css: {top: '638rpx',left: '58rpx',width: "376rpx",lineHeight: "44rpx",color: '#333333',fontSize: "28rpx",},},{type: 'text',text: '¥194.00',css: {top: '730rpx',left: '58rpx',color: '#E1A765',fontSize: "32rpx",},},{type: 'qrcode',content: 'https://github.com/Kujiale-Mobile/Painter',css: {top: '638rpx',right: '62rpx',width: '96rpx',height: '96rpx',},},{type: 'text',text: '扫码购买',css: {top: '750rpx',right: '66rpx',color: '#333',fontSize: "22rpx",},},{type: 'image',url: '../../images/all/logo.png',css: {top: '818rpx',left: '212rpx',width: '222rpx',height: '72rpx',},},],},customActionStyle: {border: {borderColor: '#1A7AF8',},scale: {textIcon: '/palette/switch.png',imageIcon: '/palette/scale.png',},delete: {icon: '/palette/close.png',},},
},
goHome() {wx.redirectTo({url: '/pages/index/index',})
},
getShopNum(e){console.error(e);this.setData({shopNum:e.detail})
},
/*** 生命周期函数--监听页面加载*/
onLoad(options) {wx.showShareMenu({withShareTicket: true,menus: ['shareAppMessage', 'shareTimeline'],success(res){},fail(error){}})if (options) {this.initData(options.id)this.setData({shopid: options.id})this.initCouponList(options.id)this.getcollect(options.id)if (options.chnnel) {console.error("分享进入==>", options);wx.login({success: res => {// 发送 res.code 到后台换取 openId, sessionKey, unionIdrequest("/login/getoauthtoken", 'post', {"authcode": res.code}).then(res => {if (res.code == 200) {console.error("粉丝添加获取传参==>", "商品id" + options.id, "老用户" + options.openid, "新用户" + res.openid);request("/login/addfriend", 'post', {pid: options.id,openid: options.openid,form_openid: res.openid,sitepage: 2}).then(res => {if (res.code == 0) {} else {}}).catch(err => {console.log(err);})} else {// wx.setStorageSync('openid', 1352168512)}}).catch(err => {console.log(err);})}})}}
},
/*** 获取优惠券列表* @param {*} options */
initCouponList(id) {var openid = wx.getStorageSync('openid')request("/coupon/proccoupon", 'post', {openid: openid,pid: id}).then(res => {if (res.code == 0) {this.setData({couponList: res.data})} else {}}).catch(err => {console.log(err);})
},
/*** 初始化数据*/
initData(id) {var that = this;request("/product/details/", 'post', {pid: id,}).then(res => {if (res.code == 0) {res.detailsRow.newHtml = res.detailsRow.detailed.replace(/(<img\s+.*?style=")(.*?)(".*?>)/g, function (match, p1, p2, p3) {var newStyle = 'width:100%;height:100%;';return p1 + newStyle + p3;});if (res.detailsRow.recommend_image != '') {console.error("判断是否有商品图片生成==>",res.detailsRow);var openid=wx.getStorageSync('openid')request("/login/createwxaqrcode", 'post', {path: "pages/shopBase/index?chnnel=1&id=" + this.data.shopid + "&openid=" + openid,}).then(data => {console.error("生成二维码==>",data);if (data.code == 0) {console.error("成功生成==>",data);that.setData({shopBase: res.detailsRow,paintPallette: {width: '640rpx',height: '928rpx',background: '#f5f5f5',left: 0,views: [{type: 'rect',css: {width: '580rpx',left: '30rpx',top: '30rpx',height: '766rpx',color: "#fff",},},{type: 'image',url: res.detailsRow.recommend_image,css: {top: '30rpx',left: '30rpx',width: '580rpx',height: '580rpx',},},{type: 'text',text: res.detailsRow.title,css: {top: '648rpx',left: '58rpx',width: "376rpx",maxLines: 2,lineHeight: "40rpx",color: '#333333',fontSize: "27rpx",},},{type: 'text',text: '¥' + res.detailsRow.price,css: {top: '730rpx',left: '58rpx',color: '#E1A765',fontSize: "32rpx",},},{type: 'image',url: data.wxaqrcodepath,css: {top: '638rpx',right: '62rpx',width: '100rpx',height: '100rpx',},},// {// type: 'qrcode',// content: data.wxaqrcodepath,// css: {// top: '638rpx',// right: '62rpx',// width: '96rpx',// height: '96rpx',// },// },{type: 'text',text: '扫码购买',css: {top: '750rpx',right: '66rpx',color: '#333',fontSize: "22rpx",},},{type: 'image',url: '../../images/all/logo.png',css: {top: '818rpx',left: '212rpx',width: '222rpx',height: '72rpx',},},],}})} else {}}).catch(err => {console.log(err);})}} else {}}).catch(err => {console.log(err);})
},
/*** 生命周期函数--监听页面初次渲染完成*/
onReady() {},
/*** 商品是否收藏*/
getcollect(id) {var openid = wx.getStorageSync('openid')request("/collect/getcollect", 'post', {openid: openid,cid: id}).then(res => {this.setData({collectStatus: res.code})}).catch(err => {console.log(err);})
},
getSelected(e) {var openid=wx.getStorageSync('openid')
request("/coupon/receivecoupon", 'post', {openid:openid,coupon_id:parseInt(e.currentTarget.dataset.id),
}).then(res => {if (res.code == 0) {
wx.showToast({title: '领取成功',icon:"none"
})} else {wx.showToast({title:res.msg,icon:"none"})}
}).catch(err => {console.log(err);
})
// for (var i in this.data.couponList) {
// if (e.detail.item.coupon_id == this.data.couponList[i].coupon_id) {
// this.data.couponList[i].stats = 1;
// var openid=wx.getStorageSync('openid')
// request("/coupon/receivecoupon", 'post', {
// openid:openid,
// coupon_id:this.data.couponList[i].coupon_id,
// }).then(res => {
// if (res.code == 0) {
// wx.showToast({
// title: '领取成功',
// icon:"none"
// })
// } else {// }
// }).catch(err => {
// console.log(err);
// })
// this.setData({
// coupon_id: this.data.couponList[i].coupon_id
// })
// } else {
// this.data.couponList[i].stats = 0;
// }
// }
// this.setData({
// couponList: this.data.couponList
// })
},
/*** 收藏*/
initCollect(data, type) {var type = data.currentTarget.dataset.type;var item = data.currentTarget.dataset.item;var openid = wx.getStorageSync('openid')console.error("type", type);if (type == 1) {request("/collect/collect", 'post', {openid: openid,cid: item.id,type: 2,stats: type,}).then(res => {if (res.code == 0) {wx.showToast({title: '收藏成功',icon: "none",})this.setData({collectStatus: 1})}}).catch(err => {console.log(err);})} else {request("/collect/getcollect", 'post', {openid: openid,cid: item.id}).then(res => {console.error("“删除", res);if (res.code == 1) {wx.showToast({title: '取消收藏',icon: "none",})this.setData({collectStatus: 0})}}).catch(err => {console.log(err);})}return;},
getClose() {this.setData({show: false})
},
onClose() {this.data.modelSHow = !this.data.modelSHowthis.setData({modelSHow: this.data.modelSHow})
},
shopShare() {wx.shopShareMenu()
},
getshare() {var that = this;setTimeout(() => {if (this.data.shopBase.recommend_image != '') {that.setData({show: true,})} else {wx.showToast({title: '生成失败,请重新尝试',})}}, 800);},
/*** 生命周期函数--监听页面显示*/
onShow() {},
getPayOrder(data) {var item = data.currentTarget.dataset.shopbase;var shopNum = this.data.shopNum;var arrbase = {};arrbase.id = item.id;arrbase.coupon_id=this.data.coupon_id;arrbase.shopNum = shopNum;arrbase.recommend_image = item.recommend_image;arrbase.title = item.title;arrbase.price = item.price;wx.setStorageSync('shopBase', arrbase)console.error(arrbase);wx.navigateTo({url: '/pages/nextOrder/index',})},
/*** 生命周期函数--监听页面隐藏*/
onHide() {},/*** 生命周期函数--监听页面卸载*/
onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/
onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/
onReachBottom() {},/*** 用户点击右上角分享*/
onShareAppMessage() {this.setData({show: false})var openid = wx.getStorageSync('openid')return {title: this.data.shopBase.title,path: '/pages/shopBase/index?chnnel=1&id=' + this.data.shopid + "&openid=" + openid,}},
onShareTimeline(){this.setData({show:false})var openid = wx.getStorageSync('openid')return {title: this.data.shopBase.title,path: '/pages/shopBase/index?chnnel=1&id=' + this.data.shopid + "&openid=" + openid,imageUrl: "/images/share_3.png"}
},
// 海报生成
onImgOK(e) {this.imagePath = e.detail.path;this.setData({image: this.imagePath,});if (this.isSave) {this.saveImage(this.imagePath);}
},
saveImage() {var that=this;wx.showToast({title: '正在生成中,请稍后',icon:"none",duration:1500})var openid=wx.getStorageSync('openid')if (this.imagePath && typeof this.imagePath === 'string') {this.isSave = false;wx.getFileSystemManager().readFile({ // 读取本地文件内容filePath:this.imagePath,encoding: 'base64', //编码格式success(res) {request("/login/dowfile", 'post', {"fileUrl": res.data,openid:openid}, 3).then(gbase => {
console.error("https",gbase);var timestamp = Date.parse(new Date()); timestamp = timestamp / 1000; console.error("传参",gbase.picUrl+"?timestamp="+timestamp);wx.downloadFile({url:gbase.picUrl+"?timestamp="+timestamp,success: res => {console.error("down-success保存到相册权限", res);//保存到相册wx.saveImageToPhotosAlbum({filePath: res.tempFilePath,success: res => {console.info("saveImageToPhotosAlbum-success===>", res);that.setData({show: false,// successShow: true})wx.showToast({title: '已保存到系统相册',icon:'none'})},fail: function (err) {console.info("saveImageToPhotosAlbum-fail===>", err);wx.showModal({title: '提示',content: '需要您授权保存相册',modalType: false,success: modalSuccess => {wx.openSetting({success(settingdata) {console.log("settingdata", settingdata)if (settingdata.authSetting['scope.writePhotosAlbum']) {wx.showModal({title: '提示',content: '获取权限成功,再次点击图片即可保存',modalType: false,})} else {wx.showModal({title: '提示',content: '获取权限失败,将无法保存到相册哦~',modalType: false,})}},fail(failData) {console.log("failData", failData)},complete(finishData) {console.log("finishData", finishData)}})}})},complete(res) {that.setData({show:false})}})},fail: error => {console.error("downloadFile-fail失败2", error);wx.showToast({title: '保存失败,请稍后再试~',icon:'none'})that.setData({show: false,})},});}).catch(err => {console.log(err);})}})return;this.isSave = false;wx.saveImageToPhotosAlbum({filePath: this.imagePath,});console.error("保存",this.imagePath);this.setData({show: false})}
},})
page {background: #F5F5F5;padding-bottom: 150rpx;
}.shopRemark {width: 100%;margin: 0 auto;padding-bottom: 35rpx;background: #fff;border-bottom-left-radius: 20rpx;border-bottom-right-radius: 20rpx;/* margin-bottom: 20rpx; */
}
.abs{position: relative;left: 30rpx;
}
richtext img{width: 100!important;
}
.iconviewtexts button[plain]{border: 0;border-radius: 0;position: relative;right: 15rpx;
}
.aleview button[plain]{border: 0;border-radius: 0;width: 208rpx;height: 98rpx;text-align: center;line-height: 98rpx;font-size: 28rpx;font-family: PingFangSC-Semibold, PingFang SC;font-weight: 600;color: #FFDB9E;background: linear-gradient(90deg, #505050 0%, #515151 100%);
}
.border {width: 666rpx;border-bottom: 1rpx solid #E4E4E4;margin: 0 auto;
}.shopTitle {width: 686rpx;margin: 0 auto;font-size: 32rpx;padding-top: 20rpx;font-family: PingFangSC-Semibold, PingFang SC;font-weight: 600;color: #333333;
}.shopbag {width: 686rpx;margin: 0 auto;font-size: 28rpx;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;color: #999999;
}.shopyy {width: 686rpx;margin: 0 auto;margin-top: 16rpx;
}.shopRadioView {width: 344rpx;display: flex;align-items: center;justify-content: center;height: 52rpx;padding: 0rpx 20rpx;background: #FFF3F3;font-size: 26rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: #E1A765;border-radius: 28rpx;
}.colView image {width: 24rpx;height: 24rpx;margin-right: 10rpx;
}.shopyys {width: 686rpx;margin: 0 auto;margin-top: 16rpx;display: flex;align-items: center;
}.colView {font-size: 24rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;display: flex;align-items: center;color: #B38953;
}.colView:nth-child(2) {margin-left: 80rpx;
}.colView:nth-child(3) {margin-left: 80rpx;
}.chList {width: 100%;height: 108rpx;margin: 0 auto;line-height: 108rpx;background: #FFFFFF;border-radius: 20rpx;
}
.chListBox{width: 100%;height: 108rpx;margin: 0 auto;display: flex;align-items: center;justify-content: space-between;line-height: 108rpx;background: #FFFFFF;border-radius: 20rpx;
}
.chListBox image{width: 16rpx;height: 32rpx;margin-right: 32rpx;
}
.chListBox label {margin-left: 20rpx;font-size: 28rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 600;color: #333333;
}
.flexicon{display: flex;align-items: center;font-size: 26rpx;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;color: #666666;
}
.cpubox view:nth-child(1){margin-left: 12rpx;}
.cpubox view:nth-child(2){width: 2rpx;height: 34rpx;border-right: 1rpx dotted #E1A765;}
.cpubox view:nth-child(3){margin-right: 12rpx;}
.cpubox{width: 228rpx;
height: 52rpx;
line-height: 52rpx;
position: relative;
margin-left: 86rpx;
text-align: center;
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 10rpx;
font-size: 26rpx;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #E1A765;
background: #FFF3F3;
}
.cliflex{display: flex;align-items: center;
}
.flexicon image{
margin-left: 12rpx;
}
.chList label {margin-left: 32rpx;font-size: 28rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 600;color: #333333;
}
.bu{width: 31rpx;
height: 30rpx;
background: #E1A765;
}
.chList text {font-size: 28rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: #999999;margin-left: 30rpx;
}.chListBox text {font-size: 28rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: #999999;margin-left: 30rpx;
}.chLists {width: 100%;margin: 0 auto;height: 136rpx;border-bottom-right-radius: 20rpx;display: flex;border-bottom-left-radius: 20rpx;background-color: #fff;align-items: center;line-height: 136rpx;position: relative;margin-bottom: 20rpx;
}.chLists label {font-size: 30rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 600;color: #333333;margin-left: 32rpx;margin-right: 4rpx;
}.chLists text {font-size: 26rpx;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;color: #666666;
}.stepper {position: absolute;right: 38rpx;
}.shopBaseView {width: 100%;margin: 0 auto;background-color: #fff;border-radius: 20rpx;padding-bottom: 30rpx;
}.headT .text {padding-top: 30rpx;margin-left: 32rpx;font-size: 32rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;height: 44rpx;color: #333333;
}.druk {width: 32rpx;height: 8rpx;position: relative;top: 5rpx;left: 65rpx;border: 5rpx solid #E1A765;border-radius: 0 0 50% 50%/0 0 100% 100%;border-top: none;margin-bottom: 36rpx;
}.shopBaseView image {margin: 0 auto;display: flex;justify-content: center;
}.submitView {width: 100%;height: 98rpx;display: flex;align-items: center;background: #FFFFFF;position: fixed;justify-content: space-between;bottom: 0;z-index: 999;
}.iconviewtexts {display: flex;width: 80rpx;text-align: center;align-items: center;/* background-color: red; */flex-direction: column;align-items: center;margin-left: 10rpx;
}.shopHead view:nth-child(1){font-size: 48rpx;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #E1A765;
display: flex;
align-items: center;margin-left: 32rpx;
margin-bottom: 10rpx;
}
.shopHead view:nth-child(1) text{font-size: 30rpx;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #E1A765;
}
.shopHead view:nth-child(2){font-size: 28rpx;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;margin-left: 32rpx;color: #999999;text-decoration: line-through;
}
.swp{position: relative;
}
.shopHead{padding-top: 20rpx; width: 100%;margin: 0 auto;background: #fff;border-top-left-radius: 20rpx;border-top-right-radius: 20rpx;position: absolute;z-index: 8;bottom: 0rpx;text-align: left;
transform: translate(-50%);
left: 50%;
}
.texty {overflow-wrap: break-word;color: rgba(51,51,51,1);font-size: 22rpx;font-family: PingFangSC-Regular;font-weight: normal;text-align: right;white-space: nowrap;line-height: 20rpx;margin-top: 16rpx;
}.icons {width: 36rpx;height: 32rpx;align-self: center;
}.aleview {display: flex;
}.rViewBtn {width: 208rpx;height: 98rpx;position: relative;text-align: center;line-height: 98rpx;font-size: 28rpx;font-family: PingFangSC-Semibold, PingFang SC;font-weight: 600;color: #FFDB9E;background: linear-gradient(90deg, #505050 0%, #515151 100%);
}.rSelBtn {width: 250rpx;font-size: 28rpx;text-align: center;line-height: 98rpx;font-family: PingFangSC-Semibold, PingFang SC;font-weight: 600;color: #8A511A;height: 98rpx;background: linear-gradient(90deg, #E6C58E 0%, #E1A664 100%);
}/* 海报 */
/* 点击分享弹窗 */
.wrapper {width: 100%;height: 2024rpx!important;overflow: auto;
}
.closeView{width: 48rpx;position: absolute;
height: 48rpx;
top: -25rpx;
right: -25rpx;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
z-index: 9;
background: rgba(0,0,0,0.5);
}
.overlays{width: 750rpx;
height: 1624rpx!important;
background: rgba(0,0,0,0.6);
overflow: auto!important;
}
.closeView image{width: 30rpx;height: 30rpx;
}
.block {width: 640rpx;position: relative;height: 928rpx;display: flex;justify-content: center;align-items: center;margin: 0 auto;background: #EEEEEE;
}.canvas-style{width: 580rpx !important;height: 766rpx !important;margin: 0 auto;
}
.savebtn-style{position: relative;top:220rpx!important;width: 130rpx!important;height: 162rpx!important;right: -265rpx!important;z-index: 999;/* opacity: 0; *//* display: none; */
}
.logo{display: flex;align-items: center;margin: 0 auto;width: 222rpx;
height: 72rpx;
margin-top: 22rpx;
}.bottomView{width: 100%;
/* height: 376rpx; */
background: #FFFFFF;
position: fixed;
bottom: 0;margin-top: 30rpx;
padding-bottom: 50rpx;
border: 2rpx solid #FFFFFF;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
}
.headBoxs{width: 100%;border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;height: 110rpx;/* position: fixed;top: 0;z-index: 2; */text-align: center;
background: linear-gradient(180deg, rgba(230,142,142,0.83) 0%, rgba(225,166,100,0) 100%);
}
.headBoxs text{font-size: 30rpx;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;color: #8A511A;
}
.colConter{text-align: center;font-size: 28rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: #333333;margin-top: 14rpx;
}
.shareicons{width: 100rpx;
height: 100rpx;
}
.colConter button[plain]{font-size: 28rpx;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
height: 40rpx;
line-height: 40rpx;
}
.iconshars button[plain]{
width: 100rpx;
height: 100rpx;
padding: 0;
margin: 0 auto;
}/* 气泡 */
.bubble:before{position: absolute;top: 73rpx;left: 35%;content: '';border: 15rpx solid transparent;border-top-color: #302417;opacity: 0.9;
}
.bubble{
position: absolute;
width: 392rpx;
height: 73rpx;
top: -95rpx;
left: -50rpx;
text-align: center;
line-height: 73rpx;
font-size: 24rpx;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #FFDB9E;
background: rgba(0,0,0,0.72);
border-radius: 30rpx;
box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(0,0,0,0.9);
/* background-color: rgba(#302417,#302417,#302417, 0.8); */
/* background-color: rgb(#302417, #302417, #302417,0.5); */
/* border: 2rpx solid #302417; */
}/* 优惠券 */
.headBox{width: 100%;text-align: center;display: flex;font-size: 36rpx;font-family: PingFang-SC-Bold, PingFang-SC;font-weight: bold;color: #333333;position: relative;align-items: center;height: 110rpx;justify-content: center;line-height: 110rpx;background: linear-gradient(180deg, rgba(230,142,142,0.83) 0%, rgba(225,166,100,0) 100%);}.headBox image{width: 40rpx;height: 40rpx;}.couBox{width: 100%;height: 320rpx;overflow: hidden;}.btnBox{width: 100%;position: fixed;bottom: 0;
height: 148rpx;
justify-content: center;
display: flex;
align-items: center;
background: #FFFFFF;}
.btnview{width: 686rpx;height: 84rpx;font-size: 32rpx;font-family: PingFangSC-Semibold, PingFang SC;font-weight: 600;color: #8A511A;line-height: 84rpx;text-align: center;background: linear-gradient(90deg, #E6C58E 0%, #E1A664 100%);box-shadow: 0rpx 4rpx 8rpx 0rpx rgba(255,59,60,0.25);border-radius: 42rpx;}/* */.yhq{width: 702rpx;height: 218rpx;display: flex;align-items: center;margin: 0 auto; position: relative;
}
.yhq image{position: relative;width: 702rpx;height: 218rpx;display: flex;align-items: center;margin: 0 auto;
}.copunBox{position: absolute;z-index: 2;top: 60rpx;margin-left: 58rpx;
}
.copunBox view:nth-child(1){font-size: 40rpx;
font-family: PingFang-SC-Heavy, PingFang-SC;
font-weight: 800;
color: #EE5514;
}
.copunBox view:nth-child(2){font-size: 22rpx;font-family: PingFangSC-Medium, PingFang SC;font-weight: 500;color: #EE5514;
}.fwidth{width: 80%;margin: 0 auto;
}