Quellcode durchsuchen

修复部分bug

hwb0 vor 3 Jahren
Ursprung
Commit
17aadfb106

+ 5 - 5
components/custom-tab-bar/custom-tab-bar.vue

@@ -1,6 +1,6 @@
 <template>
 	<view>
-		<u-tabbar :value="activeValue" @change="changeTabbar" :fixed="true" :placeholder="true"
+		<u-tabbar :value="activeValue" @change="changeTabbar" :fixed="true" activeColor="#E96737" :placeholder="true"
 			:safeAreaInsetBottom="true">
 			<u-tabbar-item :text="item.text" :name="item.name" v-for="(item, index) in list" :key="index">
 				<image class="icon" slot="active-icon" :src="item.selectedIconPath"></image>
@@ -53,8 +53,8 @@
 					},
 					{
 						name: "core",
-						iconPath: "../../static/tabbar/law.png",
-						selectedIconPath: "../../static/tabbar/law_select.png",
+						iconPath: "../../static/tabbar/core.png",
+						selectedIconPath: "../../static/tabbar/core_select.png",
 						text: "兑换大厅"
 					},
 					{
@@ -71,7 +71,7 @@
 
 <style lang="scss" scoped>
 	.icon {
-		width: 54rpx;
-		height: 54rpx;
+		width: 45rpx;
+		height: 45rpx;
 	}
 </style>

+ 273 - 0
components/hch-poster/draw-demo.vue

@@ -0,0 +1,273 @@
+<!--
+ * @Description: 生成海报组件
+ * @Version: 1.0.0
+ * @Autor: hch
+ * @Date: 2020-08-07 14:48:41
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2021-07-30 09:25:07
+ * 保存海报按钮和关闭按钮 在html代码中写出来 绑定点击方法然后透明 再用canvas 覆盖
+-->
+
+<template>
+  <view class="content">
+    <view class="btn" @tap="handleDraw('square1')">正方形</view>
+    <view class="btn" @tap="handleDraw('square2')">圆角方形</view>
+    <view class="btn" @tap="handleDraw('square3')">圆形</view>
+    <view class="btn" @tap="handleDraw('pic1')">图片</view>
+    <view class="btn" @tap="handleDraw('text1')">左对齐文本</view>
+    <view class="btn" @tap="handleDraw('text2')">居中对齐文本</view>
+    <view class="btn" @tap="handleDraw('text3')">右对齐文本</view>
+
+    <view
+      class="canvas-content"
+      v-show="canvasShow"
+      :style="'width:' + system.w + 'px; height:' + system.h + 'px;'"
+    >
+      <!-- 遮罩层 -->
+      <view class="canvas-mask"></view>
+      <!-- :width="system.w" :height="system.h" 支付宝必须要这样设置宽高才有效果 -->
+      <canvas
+        class="canvas"
+        :canvas-id="canvasId"
+        :id="canvasId"
+        :style="'width:' + system.w + 'px; height:' + system.h + 'px;'"
+        :width="system.w"
+        :height="system.h"
+      ></canvas>
+      <view class="button-wrapper">
+        <!-- 保存海报按钮 -->
+        <!-- #ifndef MP-QQ -->
+        <!-- cover-view 标签qq小程序有问题 -->
+        <cover-view class="save-btn cancel-btn" @tap="handleCancel">取消</cover-view>
+        <!-- #endif -->
+        <!-- #ifdef MP-QQ -->
+        <view class="save-btn cancel-btn" @tap="handleCancel">取消</view>
+        <!-- #endif -->
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  import { drawSquarePic, drawTextReturnH, getSystem } from './utils'
+  export default {
+    data() {
+      return {
+        canvasId: 'canvas',
+        system: {},
+        canvasShow: false,
+        square1: {
+          //正方形
+          x: 40,
+          y: 40,
+          r: 0, //圆角半径
+          w: 80, //宽度
+          h: 80 //高度
+        },
+        square2: {
+          //圆角方形
+          x: 40,
+          y: 40,
+          r: 10, //圆角半径
+          w: 80, //宽度
+          h: 80 //高度
+        },
+        square3: {
+          //圆形
+          x: 40,
+          y: 40,
+          r: 40, //圆角半径
+          w: 80, //宽度
+          h: 80 //高度
+        },
+        pic1: {
+          x: 40,
+          y: 40,
+          url: 'https://huangchunhongzz.gitee.io/imgs/poster/product.png',
+          r: 0, //圆角半径
+          w: 250, //宽度
+          h: 200 //高度
+        },
+        text1: {
+          x: 0,
+          y: 40,
+          text: '今日上新水果,牛奶草莓',
+          fontSize: 16, //字体大小
+          color: '#000', //颜色
+          lineHeight: 25, //行高
+          mt: 0 //margin-top
+        },
+        text2: {
+          x: 0,
+          y: 40,
+          text: '今日上新水果,牛奶草莓',
+          fontSize: 16, //字体大小
+          color: 'blue', //颜色
+          lineHeight: 25, //行高
+          mt: 0, //margin-top
+          align: 'center' //对齐方式
+        },
+        text3: {
+          x: 0,
+          y: 40,
+          text: '今日上新水果,牛奶草莓',
+          fontSize: 16, //字体大小
+          color: 'red', //颜色
+          lineHeight: 25, //行高
+          mt: 0, //margin-top
+          align: 'right' //对齐方式
+        }
+      }
+    },
+    created() {
+      // 获取设备信息
+      this.system = getSystem()
+    },
+    methods: {
+      /**
+       * @description: 展示海报
+       * @param {type}
+       * @return {type}
+       * @author: hch
+       */
+      handleDraw(type) {
+        console.log('handleDraw -> type', type)
+        this.canvasShow = true
+        this.draw(type)
+      },
+      /**
+       * @description: 绘制
+       * @author: hch
+       */
+      draw(type) {
+        uni.showLoading({
+          title: '绘制中...'
+        })
+        if (this.ctx) {
+          this.ctx.clearRect(0, 0, this.system.w, this.system.h) //清空之前的海报
+          this.ctx.restore() //恢复之前被切割的canvas,否则切割之外的就没办法用
+        } else {
+          this.ctx = uni.createCanvasContext(this.canvasId, this)
+        }
+        let drawData = this[type]
+        if (type === 'square1' || type === 'square2' || type === 'square3' || type === 'pic1') {
+          // 绘制图像/图片
+          drawSquarePic(
+            this.ctx,
+            drawData.x,
+            drawData.y,
+            drawData.w,
+            drawData.h,
+            drawData.r,
+            drawData.url
+          )
+        } else {
+          // 绘制文本
+          let textY = drawTextReturnH(
+            this.ctx,
+            drawData.text,
+            drawData.x,
+            drawData.y,
+            this.system.w,
+            drawData.fontSize,
+            drawData.color,
+            drawData.lineHeight,
+            drawData.align
+          )
+        }
+
+        uni.hideLoading()
+      },
+      /**
+       * @description: 取消海报
+       * @param {type}
+       * @return {type}
+       * @author: hch
+       */
+      handleCancel() {
+        this.canvasShow = false
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  .content {
+    margin-bottom: 80rpx;
+    overflow: hidden;
+    border-bottom: 1rpx solid $uni-border-color;
+
+    .btn {
+      float: left;
+      width: 30%;
+      margin: 10rpx;
+      font-size: 30rpx;
+      line-height: 72rpx;
+      color: #fff;
+      text-align: center;
+      background: $uni-btn-color;
+      border-radius: 45rpx;
+      border-radius: 36rpx;
+    }
+  }
+
+  .canvas-content {
+    position: absolute;
+    top: 0;
+    z-index: 9;
+
+    .canvas-mask {
+      position: fixed;
+      top: 0;
+      right: 0;
+      bottom: 0;
+      left: 0;
+      z-index: 9;
+      width: 100%;
+      height: 100%;
+      background: $uni-btn-color;
+    }
+
+    .canvas {
+      z-index: 10;
+    }
+
+    .button-wrapper {
+      position: fixed;
+      bottom: 20rpx;
+      z-index: 16;
+      display: flex;
+      width: 100%;
+      height: 72rpx;
+      justify-content: space-around;
+    }
+
+    .save-btn {
+      z-index: 16;
+      width: 40%;
+      height: 100%;
+      font-size: 30rpx;
+      line-height: 72rpx;
+      color: #fff;
+      text-align: center;
+      background: $uni-btn-color;
+      border-radius: 45rpx;
+      border-radius: 36rpx;
+    }
+
+    .cancel-btn {
+      color: $uni-btn-color;
+      background: #fff;
+    }
+
+    .canvas-close-btn {
+      position: fixed;
+      top: 30rpx;
+      right: 0;
+      z-index: 12;
+      width: 60rpx;
+      height: 60rpx;
+      padding: 20rpx;
+    }
+  }
+</style>

+ 402 - 0
components/hch-poster/hch-poster.vue

@@ -0,0 +1,402 @@
+<!--
+ * @Description: 生成图片组件
+ * @Version: 1.0.0
+ * @Autor: hch
+ * @Date: 2020-08-07 14:48:41
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2021-07-31 18:11:35
+ * 保存图片按钮和关闭按钮 在html代码中写出来 绑定点击方法然后透明 再用canvas 覆盖
+-->
+
+<template>
+	<view class="canvas-content" v-show="canvasShow" :style="'width:' + system.w + 'px; height:' + system.h + 'px;'">
+		<!-- 遮罩层 -->
+		<view class="canvas-mask"></view>
+		<!-- 图片 -->
+		<!-- :width="system.w" :height="system.h" 支付宝必须要这样设置宽高才有效果 -->
+		<canvas class="canvas" canvas-id="myCanvas" id="myCanvas"
+			:style="'width:' + system.w + 'px; height:' + system.h + 'px;'" :width="system.w"
+			:height="system.h"></canvas>
+		<view class="button-wrapper">
+			<!-- 保存图片按钮 -->
+			<!-- #ifndef MP-QQ -->
+			<!-- cover-view 标签qq小程序有问题 -->
+			<cover-view class="save-btn" @tap="handleSaveCanvasImage">保存</cover-view>
+			<cover-view class="save-btn cancel-btn" @tap="handleCanvasCancel">取消</cover-view>
+			<!-- #endif -->
+			<!-- #ifdef MP-QQ -->
+			<view class="save-btn" @tap="handleSaveCanvasImage">保存</view>
+			<view class="save-btn cancel-btn" @tap="handleCanvasCancel">取消</view>
+			<!-- #endif -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		drawSquarePic,
+		drawTextReturnH,
+		getSystem
+	} from './utils'
+	export default {
+		data() {
+			return {
+				system: {},
+				canvasShow: false
+			}
+		},
+		props: {
+			posterData: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			}
+		},
+		computed: {
+			/**
+			 * @description: 计算图片背景数据
+			 * @param {*}
+			 * @return {*}
+			 * @author: hch
+			 */
+			poster() {
+				let data = this.posterData
+				let system = this.system
+				let posterBg = {
+					url: data.poster.url,
+					r: data.poster.r * system.scale,
+					w: data.poster.w * system.scale,
+					h: data.poster.h * system.scale,
+					x: (system.w - data.poster.w * system.scale) / 2,
+					y: (system.h - data.poster.h * system.scale) / 2,
+					p: data.poster.p * system.scale
+				}
+				return posterBg
+			},
+			/**
+			 * @description: 计算图片头部主图
+			 * @param {*}
+			 * @return {*}
+			 * @author: hch
+			 */
+			square3() {
+				let data = this.posterData
+				let system = this.system
+				let posterMain = {
+					r: data.square3.r * system.scale,
+					w: data.square3.w * system.scale,
+					h: data.square3.h * system.scale,
+					x: (system.w - data.square3.w * system.scale) / 2,
+					y: this.poster.y + data.poster.p + data.square3.mt * system.scale,
+					color: '#E96737'
+				}
+				return posterMain
+			},
+
+			title() {
+				let data = this.posterData
+				let system = this.system
+				let posterTitle = data.title
+				posterTitle.x = this.square3.x
+				posterTitle.y = this.square3.y + 30 * system.scale
+				return posterTitle
+			},
+
+			num() {
+				let data = this.posterData
+				let system = this.system
+				let posterTitle = data.num
+				posterTitle.x = this.square3.x
+				posterTitle.y = this.square3.y + 100 * system.scale
+				return posterTitle
+			},
+
+			txt() {
+				let data = this.posterData
+				let system = this.system
+				let posterTitle = data.txt
+				posterTitle.x = this.square3.x
+				posterTitle.y = this.square3.y + 150 * system.scale
+				return posterTitle
+			},
+		},
+		created() {
+			// 获取设备信息
+			this.system = getSystem()
+		},
+		methods: {
+			/**
+			 * @description: 展示图片
+			 * @param {type}
+			 * @return {type}
+			 * @author: hch
+			 */
+			posterShow() {
+				this.canvasShow = true
+				this.creatPoster()
+			},
+			/**
+			 * @description: 生成图片
+			 * @author: hch
+			 */
+			async creatPoster() {
+				uni.showLoading({
+					title: '生成图片中...'
+				})
+				const ctx = uni.createCanvasContext('myCanvas', this)
+				this.ctx = ctx
+				ctx.clearRect(0, 0, this.system.w, this.system.h) //清空之前的图片
+				ctx.draw() //清空之前的图片
+				// 根据设备屏幕大小和距离屏幕上下左右距离,及圆角绘制背景
+				let poster = this.poster
+				let square3 = this.square3
+				let title = this.title
+				let num = this.num
+				let txt = this.txt
+				await drawSquarePic(ctx, poster.x, poster.y, poster.w, poster.h, poster.r, poster.url)
+				await drawSquarePic(ctx, square3.x, square3.y, square3.w, square3.h, square3.r, square3.url, square3
+					.color)
+				// 绘制标题 textY 绘制文本的y位置
+				// console.log('creatPoster -> title.x', title.x)
+				let textY = drawTextReturnH(
+					this.ctx,
+					title.text,
+					title.x,
+					title.y,
+					this.system.w,
+					title.fontSize,
+					title.color,
+					title.lineHeight,
+					title.align
+				)
+
+				let numY = drawTextReturnH(
+					this.ctx,
+					num.text,
+					num.x,
+					num.y,
+					this.system.w,
+					num.fontSize,
+					num.color,
+					num.lineHeight,
+					num.align
+				)
+
+				let txtY = drawTextReturnH(
+					this.ctx,
+					txt.text,
+					txt.x,
+					txt.y,
+					this.system.w,
+					txt.fontSize,
+					txt.color,
+					txt.lineHeight,
+					txt.align
+				)
+
+				uni.hideLoading()
+			},
+			/**
+			 * @description: 保存到系统相册
+			 * @param {type}
+			 * @return {type}
+			 * @author: hch
+			 */
+			handleSaveCanvasImage() {
+				uni.showLoading({
+					title: '保存中...'
+				})
+				let _this = this
+				// 把画布转化成临时文件
+				// #ifndef MP-ALIPAY
+				// 支付宝小程序外,其他都是用这个方法 canvasToTempFilePath
+				uni.canvasToTempFilePath({
+						x: this.poster.x,
+						y: this.poster.y,
+						width: this.poster.w, // 画布的宽
+						height: this.poster.h, // 画布的高
+						destWidth: this.poster.w * 5,
+						destHeight: this.poster.h * 5,
+						canvasId: 'myCanvas',
+						success(res) {
+							//保存图片至相册
+							// #ifndef H5
+							// 除了h5以外的其他端
+							uni.saveImageToPhotosAlbum({
+								filePath: res.tempFilePath,
+								success(res) {
+									uni.hideLoading()
+									uni.showToast({
+										title: '图片保存成功',
+										duration: 2000,
+										icon: 'none'
+									})
+									_this.handleCanvasCancel()
+									_this.handleCanvasConfirm()
+								},
+								fail() {
+									uni.showToast({
+										title: '保存失败,稍后再试',
+										duration: 2000,
+										icon: 'none'
+									})
+									uni.hideLoading()
+								}
+							})
+							// #endif
+
+							// #ifdef H5
+							// h5的时候
+							uni.showToast({
+								title: '请长按保存',
+								duration: 3000,
+								icon: 'none'
+							})
+							_this.handleCanvasCancel()
+							_this.$emit('previewImage', res.tempFilePath)
+							// #endif
+						},
+						fail(res) {
+							// console.log('fail -> res', res)
+							uni.showToast({
+								title: '保存失败,稍后再试',
+								duration: 2000,
+								icon: 'none'
+							})
+							uni.hideLoading()
+						}
+					},
+					this
+				)
+				// #endif
+				// #ifdef MP-ALIPAY
+				// 支付宝小程序条件下 toTempFilePath
+				this.ctx.toTempFilePath({
+						x: this.poster.x,
+						y: this.poster.y,
+						width: this.poster.w, // 画布的宽
+						height: this.poster.h, // 画布的高
+						destWidth: this.poster.w * 5,
+						destHeight: this.poster.h * 5,
+						success(res) {
+							//保存图片至相册
+							my.saveImage({
+								url: res.apFilePath,
+								showActionSheet: true,
+								success(res) {
+									uni.hideLoading()
+									uni.showToast({
+										title: '图片保存成功',
+										duration: 2000,
+										icon: 'none'
+									})
+									_this.handleCanvasCancel()
+								},
+								fail() {
+									uni.showToast({
+										title: '保存失败,稍后再试',
+										duration: 2000,
+										icon: 'none'
+									})
+									uni.hideLoading()
+								}
+							})
+						},
+						fail(res) {
+							// console.log('fail -> res', res)
+							uni.showToast({
+								title: '保存失败,稍后再试',
+								duration: 2000,
+								icon: 'none'
+							})
+							uni.hideLoading()
+						}
+					},
+					this
+				)
+				// #endif
+			},
+			/**
+			 * @description: 取消图片
+			 * @param {type}
+			 * @return {type}
+			 * @author: hch
+			 */
+			handleCanvasCancel() {
+				this.canvasShow = false
+				this.$emit('cancel', true)
+			},
+
+			handleCanvasConfirm() {
+				this.$emit('canvasConfirm')
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.content {
+		height: 100%;
+		text-align: center;
+	}
+
+	.canvas-content {
+		position: absolute;
+		top: 0;
+
+		.canvas-mask {
+			position: fixed;
+			top: 0;
+			right: 0;
+			bottom: 0;
+			left: 0;
+			z-index: 9;
+			width: 100%;
+			height: 100%;
+			background: rgba(0, 0, 0, 0.5);
+		}
+
+		.canvas {
+			z-index: 10;
+		}
+
+		.button-wrapper {
+			position: fixed;
+			bottom: 80rpx;
+			z-index: 16;
+			display: flex;
+			width: 100%;
+			height: 72rpx;
+			justify-content: space-around;
+		}
+
+		.save-btn {
+			z-index: 16;
+			width: 40%;
+			height: 100%;
+			font-size: 30rpx;
+			line-height: 72rpx;
+			color: #fff;
+			text-align: center;
+			background: $uni-btn-color;
+			border-radius: 45rpx;
+			border-radius: 36rpx;
+		}
+
+		.cancel-btn {
+			color: $uni-btn-color;
+			background: #fff;
+		}
+
+		.canvas-close-btn {
+			position: fixed;
+			top: 30rpx;
+			right: 0;
+			z-index: 12;
+			width: 60rpx;
+			height: 60rpx;
+			padding: 20rpx;
+		}
+	}
+</style>

+ 139 - 0
components/hch-poster/utils/index.js

@@ -0,0 +1,139 @@
+/*
+ * @Description: 公共方法
+ * @Version: 1.0.0
+ * @Autor: hch
+ * @Date: 2021-07-22 00:01:09
+ */
+/**
+ * @description: 绘制正方形(可以定义圆角),并且有图片地址的话填充图片
+ * @param {CanvasContext} ctx canvas上下文
+ * @param {number} x 圆角矩形选区的左上角 x坐标
+ * @param {number} y 圆角矩形选区的左上角 y坐标
+ * @param {number} w 圆角矩形选区的宽度
+ * @param {number} h 圆角矩形选区的高度
+ * @param {number} r 圆角的半径
+ * @param {String} url 图片的url地址
+ */
+export function drawSquarePic(ctx, x, y, w, h, r, url, color) {
+  ctx.save()
+  ctx.beginPath()
+  // 绘制左上角圆弧
+  ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
+  // 绘制border-top
+  // 画一条线 x终点、y终点
+  ctx.lineTo(x + w - r, y)
+  // 绘制右上角圆弧
+  ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
+  // 绘制border-right
+  ctx.lineTo(x + w, y + h - r)
+  // 绘制右下角圆弧
+  ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
+  // 绘制左下角圆弧
+  ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
+  // 绘制border-left
+  ctx.lineTo(x, y + r)
+  // 填充颜色(需要可以自行修改)
+  ctx.setFillStyle(color || '#ffffff')
+  ctx.fill()
+  // 剪切,剪切之后的绘画绘制剪切区域内进行,需要save与restore 这个很重要 不然没办法保存
+  ctx.clip()
+
+  // 绘制图片
+  return new Promise((resolve, reject) => {
+    if (url) {
+      uni.getImageInfo({
+        src: url,
+        success(res) {
+          ctx.drawImage(res.path, x, y, w, h)
+          ctx.restore() //恢复之前被切割的canvas,否则切割之外的就没办法用
+          ctx.draw(true)
+          resolve()
+        },
+        fail(res) {
+          console.log('fail -> res', res)
+          uni.showToast({
+            title: '图片下载异常',
+            duration: 2000,
+            icon: 'none'
+          })
+        }
+      })
+    } else {
+      ctx.draw(true)
+      resolve()
+    }
+  })
+}
+
+/**
+ * @description: 获取设备信息
+ * @param {type}
+ * @return {type}
+ * @author: hch
+ */
+export function getSystem() {
+  let system = wx.getSystemInfoSync()
+  let scale = system.windowWidth / 375 //按照苹果留 375*667比例 其他型号手机等比例缩放 显示
+  return { w: system.windowWidth, h: system.windowHeight, scale: scale }
+}
+
+/**
+ * @description: 绘制文本时文本的总体高度
+ * @param {Object} ctx canvas上下文
+ * @param {String} text 需要输入的文本
+ * @param {Number} x X轴起始位置
+ * @param {Number} y Y轴起始位置
+ * @param {Number} maxWidth 单行最大宽度
+ * @param {Number} fontSize 字体大小
+ * @param {String} color 字体颜色
+ * @param {Number} lineHeight 行高
+ * @param {String} textAlign 字体对齐方式
+ */
+export function drawTextReturnH(
+  ctx,
+  text,
+  x,
+  y,
+  maxWidth = 375,
+  fontSize = 14,
+  color = '#000',
+  lineHeight = 30,
+  textAlign = 'left'
+) {
+  if (textAlign) {
+    ctx.setTextAlign(textAlign) //设置文本的水平对齐方式  ctx.setTextAlign这个可以兼容百度小程序 ,注意:ctx.textAlign百度小程序有问题
+    switch (textAlign) {
+      case 'center':
+        x = getSystem().w / 2
+        break
+
+      case 'right':
+        x = (getSystem().w - maxWidth) / 2 + maxWidth
+        break
+
+      default:
+        // 左对齐
+        x = (getSystem().w - maxWidth) / 2
+        break
+    }
+  }
+  let arrText = text.split('')
+  let line = ''
+  for (let n = 0; n < arrText.length; n++) {
+    let testLine = line + arrText[n]
+    ctx.font = fontSize + 'px sans-serif' //设置字体大小,注意:百度小程序 用ctx.setFontSize设置字体大小后,计算字体宽度会无效
+    ctx.setFillStyle(color) //设置字体颜色
+    let metrics = ctx.measureText(testLine) //measureText() 方法返回包含一个对象,该对象包含以像素计的指定字体宽度。
+    let testWidth = metrics.width
+    if (testWidth > maxWidth && n > 0) {
+      ctx.fillText(line, x, y)
+      line = arrText[n]
+      y += lineHeight
+    } else {
+      line = testLine
+    }
+  }
+  ctx.fillText(line, x, y)
+  ctx.draw(true) //本次绘制是否接着上一次绘制。即 reserve 参数为 false,则在本次调用绘制之前 native 层会先清空画布再继续绘制;若 reserve 参数为 true,则保留当前画布上的内容,本次调用 drawCanvas 绘制的内容覆盖在上面,默认 false。
+  return y
+}

+ 181 - 51
pages/choice/index.vue

@@ -8,11 +8,16 @@
 				<view class="choice-list-item" v-for="(item, index) in prizeList" :key="index"
 					@click="selectPrize(item, index)">
 					<view
-						:class="{'flex action': actionIndex == index, 'flex confirm': actionIndex != index, 'flex null': item.remainQty == 0}">
-						<view class="info">
+						:class="{'item-info action': actionIndex == index && total > 1, 'item-info confirm': actionIndex != index, 'item-info null': item.remainQty == 0}">
+						<view class="flex info">
 							<image :src="item.picUrl" mode="aspectFill"></image>
-							<view class="title">{{ item.title }}</view>
-							<view class="tip" v-if="item.remainQty == 0">已兑完</view>
+						</view>
+						<view class="title" v-if="item.prizeType && item.prizeType.value != 'coin'">{{ item.title }}
+						</view>
+						<view class="title" v-else>盲豆x {{ item.value }}</view>
+						<view class="tip" v-if="item.remainQty == 0">已兑完</view>
+						<view class="flex action-icon" v-if="actionIndex == index && total > 1">
+							<u-icon name="checkmark" color="#fff" size="24"></u-icon>
 						</view>
 					</view>
 				</view>
@@ -28,6 +33,25 @@
 				<view class="btn" @click="toIndex">确认</view>
 			</view>
 		</u-popup>
+
+		<u-popup :show="comfirmShow" :round="10" mode="center">
+			<view class="confirm-prize">
+				<view class="flex confirm-prize-info">
+					<image :src="actionInfo.picUrl" mode="aspectFill"></image>
+					<view class="title" v-if="actionInfo.prizeType && actionInfo.prizeType.value != 'coin'">
+						{{ actionInfo.title }}
+					</view>
+					<view class="title" v-else>盲豆x {{ actionInfo.value }}</view>
+				</view>
+				<view class="confirm-prize-tip" v-if="actionInfo.prizeType && actionInfo.prizeType.value != 'coin'">
+					已放入我的奖品库</view>
+				<view class="confirm-prize-tip" v-else>已放入“我的盲豆”</view>
+				<view class="flex confirm-prize-btn">
+					<view class="back" @click="back">返回</view>
+					<view class="confirm" @click="toPrize">前往查看</view>
+				</view>
+			</view>
+		</u-popup>
 	</view>
 </template>
 
@@ -41,7 +65,9 @@
 				prizeList: [],
 				total: 0,
 				actionIndex: 0,
-				tipShow: false
+				tipShow: false,
+				comfirmShow: false,
+				actionInfo: {}
 			};
 		},
 		onLoad(options) {
@@ -67,13 +93,14 @@
 						res.data.prizeList.forEach(item => {
 							let picUrlArr = item.picUrl.split(',')
 							item.picUrl = env.filePublic + picUrlArr[0]
+							item.prizeType = JSON.parse(item.prizeType)
 						})
 						this.prizeList = res.data.prizeList
 						this.ticketId = res.data.ticketId
-						this.total = res.data.length
+						this.total = this.prizeList.length
 					} else if (res.code == 1018) {
 						this.tipShow = true
-					}else{
+					} else {
 						this.tipShow = true
 					}
 				}).catch(() => {
@@ -92,29 +119,38 @@
 			confirmPrize() {
 				let _this = this
 				let item = _this.prizeList[_this.actionIndex]
-				uni.showModal({
-					title: '提示',
-					content: '确定选择该奖品吗?',
-					success(res) {
-						if (res.confirm) {
-							$http.post('/api/v1/mp/user/ticket/cashPrize', {
-								ticketId: _this.ticketId,
-								awardsId: item.awardsId,
-								prizeId: item.prizeId
-							}).then(res => {
-								if (res.code == 0) {
-									uni.$u.toast('兑换成功');
-									setTimeout(() => {
-										uni.switchTab({
-											url: '/pages/index/index'
-										})
-									}, 500)
-								}
-							})
+				_this.actionInfo = item
+				if (_this.prizeList.length > 1) {
+					uni.showModal({
+						title: '提示',
+						content: '确定选择该奖品吗?',
+						success(res) {
+							if (res.confirm) {
+								$http.post('/api/v1/mp/user/ticket/cashPrize', {
+									ticketId: _this.ticketId,
+									awardsId: item.awardsId,
+									prizeId: item.prizeId
+								}).then(res => {
+									if (res.code == 0) {
+										uni.$u.toast('兑换成功');
+										_this.comfirmShow = true
+									}
+								})
+							}
 						}
-					}
-				})
-
+					})
+				} else {
+					$http.post('/api/v1/mp/user/ticket/cashPrize', {
+						ticketId: _this.ticketId,
+						awardsId: item.awardsId,
+						prizeId: item.prizeId
+					}).then(res => {
+						if (res.code == 0) {
+							uni.$u.toast('兑换成功');
+							_this.comfirmShow = true
+						}
+					})
+				}
 			},
 
 			toIndex() {
@@ -122,6 +158,25 @@
 					url: '/pages/index/index'
 				})
 			},
+
+			back() {
+				let pages = getCurrentPages();
+				if (pages.length > 1) {
+					uni.navigateBack({
+						delta: 1
+					})
+				} else {
+					uni.switchTab({
+						url: '/pages/core/index'
+					})
+				}
+			},
+
+			toPrize() {
+				uni.switchTab({
+					url: '/pages/user/index'
+				})
+			}
 		}
 	}
 </script>
@@ -150,65 +205,87 @@
 		&-list {
 			justify-content: space-around;
 			flex-wrap: wrap;
-			margin-top: 60rpx;
+			padding: 60rpx;
 			margin-bottom: 60rpx;
 
 			&-item {
-				width: 40%;
+				position: relative;
+				width: 43%;
 				height: 440rpx;
 				margin-bottom: 40rpx;
+				background-color: #FFFFFF;
+				border-radius: 10rpx;
+				
+				.item-info {
+					height: 100%;
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					border: 2px solid #FFFFFF;
+					border-radius: 10rpx;
+				}
 
 				.confirm {
-					height: 100%;
 					background: none;
 					box-shadow: none;
-					border: none;
+				}
+				
+				.action-icon{
+					position: absolute;
+					bottom: -15rpx;
+					right: -15rpx;
+					width: 82rpx;
+					height: 82rpx;
+					line-height: 82rpx;
+					background-color: rgba(236, 122, 61, 100);
+					text-align: center;
+					box-shadow: 0px 4rpx 12rpx 0px rgba(0, 0, 0, 0.4);
+					border-radius: 50%;
 				}
 
 				.action {
-					height: 100%;
-					background-color: #4cd964;
 					box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.4);
-					border: 1px solid rgba(187, 187, 187, 54);
+					border: 2px solid rgba(236, 122, 61, 100);
 				}
 
 				.null {
-					height: 100%;
-					background: #918b8d;
 					box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.4);
-					border: 1px solid rgba(187, 187, 187, 54);
+					border: 2px solid rgba(187, 187, 187, 54);
 				}
 
 				.info {
-					width: 80%;
-					height: 80%;
-					background-color: #C0C0C0;
+					width: 100%;
+					height: 75%;
+					background-color: #F8F8F8;
+					border-top-left-radius: 10rpx;
+					border-top-right-radius: 10rpx;
 				}
 
 				image {
 					width: 100%;
-					height: 60%;
+					height: 80%;
 				}
 
 				.title {
-					margin-top: 20rpx;
-					color: #FFFFFF;
-					text-align: center;
+					width: 100%;
+					font-size: 24rpx;
+					margin: 16rpx 0 0 10rpx;
+					color: #333;
 				}
 
 				.tip {
-					margin-top: 20rpx;
+					margin: 16rpx 0 0 10rpx;
+					font-size: 24rpx;
 					color: red;
-					text-align: center;
 				}
 			}
 		}
 
 		.btn {
 			.confirm {
-				width: 320rpx;
-				height: 60rpx;
-				line-height: 60rpx;
+				width: 400rpx;
+				height: 80rpx;
+				line-height: 80rpx;
 				border-radius: 8px;
 				background-color: rgba(235, 112, 9, 100);
 				color: rgba(255, 255, 255, 100);
@@ -240,4 +317,57 @@
 			text-align: center;
 		}
 	}
+
+	.confirm-prize {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		width: 80vw;
+		padding: 40rpx 0;
+
+		&-info {
+			width: 80%;
+			margin-bottom: 60rpx;
+			justify-content: space-around;
+
+			image {
+				width: 150rpx;
+				height: 200rpx;
+			}
+		}
+
+		&-tip {
+			text-align: center;
+			margin-bottom: 60rpx;
+		}
+
+		&-btn {
+			width: 80%;
+			justify-content: space-around;
+
+			.back {
+				width: 160rpx;
+				height: 60rpx;
+				line-height: 60rpx;
+				border-radius: 8rpx;
+				color: rgba(235, 112, 9, 100);
+				font-size: 28rpx;
+				text-align: center;
+				font-family: Microsoft Yahei;
+				border: 1px solid rgba(235, 112, 9, 100);
+			}
+
+			.confirm {
+				width: 160rpx;
+				height: 60rpx;
+				line-height: 60rpx;
+				border-radius: 8rpx;
+				background-color: rgba(235, 112, 9, 100);
+				color: rgba(253, 253, 253, 100);
+				font-size: 28rpx;
+				text-align: center;
+			}
+		}
+	}
 </style>

+ 1 - 1
pages/core/index.vue

@@ -44,7 +44,7 @@
 			};
 		},
 		
-		onShow() {
+		onLoad() {
 			this.pageList()
 		},
 		methods: {

+ 4 - 2
pages/goods/detail.vue

@@ -112,7 +112,6 @@
 		},
 		onShow(){
 			this.getDetail()
-			this.getBean()
 		},
 		methods: {
 			getDetail() {
@@ -179,7 +178,10 @@
 			},
 
 			exChange() {
-				this.choiceShow = true
+				this.getBean()
+				if(uni.getStorageSync('token')){
+					this.choiceShow = true
+				}
 			},
 
 			close() {

+ 91 - 9
pages/lucky/index.vue

@@ -13,12 +13,11 @@
 				<view class="txt">{{ info.title }}</view>
 				<view class="id">盲票序列号:{{ info.serialNo }}</view>
 			</view>
+			<view class="flex lucky-tip"><text>请刮开纸质票面的数字,与此幸运数字相同的就是所中奖项</text></view>
 			<view class="flex lucky-btn">
 				<view class="pay" @click="pay" v-if="info.status == 1">支付{{ info.facePrice / 100 }}元 立即查看</view>
-				<view class="pay" @click="screen" v-else>保存至手机相册</view>
+				<view class="pay" @click="saveImg" v-else>保存至手机相册</view>
 			</view>
-			<view class="index" @click="toIndex">去首页</view>
-
 		</view>
 
 		<pay-popup :pay-show="payShow" :pay-info="payInfo" @close="close" @success="getDetailInfo" />
@@ -29,6 +28,8 @@
 				<view class="btn" @click="toIndex">确认</view>
 			</view>
 		</u-popup>
+
+		<hch-poster ref="hchPoster" @cancel="handleCancel" :posterData.sync="posterData" @previewImage='previewImage' @canvasConfirm="toIndex" />
 	</view>
 </template>
 
@@ -36,9 +37,12 @@
 	import env from '../../config/env.js'
 	import $http from '@/utils/request.js'
 	import PayPopup from '../../components/pay-popup/pay-popup.vue'
+	import HchPoster from "../../components/hch-poster/hch-poster.vue"
+
 	export default {
 		components: {
-			PayPopup
+			PayPopup,
+			HchPoster
 		},
 		data() {
 			return {
@@ -48,6 +52,7 @@
 				payShow: false,
 				payLookFlag: true,
 				showNull: false,
+				posterData: {}
 			};
 		},
 
@@ -128,6 +133,50 @@
 					uni.hideLoading();
 					if (res.code == 0) {
 						this.info = res.data
+						let num = res.data.plainLuckyNum
+						this.posterData.num.text =
+							this.posterData = {
+								poster: {
+									//根据屏幕大小自动生成图片背景大小
+									url: env.filePublic + this.info.picUrl, //图片地址
+									r: 10, //圆角半径
+									w: 300, //图片宽度
+									h: 480, //图片高度
+									p: 20 //图片内边距padding
+								},
+								square3: {
+									x: 100,
+									y: 100,
+									r: 0, //圆角半径
+									w: 240, //宽度
+									h: 180, //高度
+									mt: 65
+								},
+								title: {
+									text: "幸运数字", //文本
+									fontSize: 20, //字体大小
+									color: "#000", //颜色
+									lineHeight: 25, //行高
+									mt: 20, //margin-top
+									align: 'center'
+								},
+								num: {
+									text: num + '', //文本
+									fontSize: 40, //字体大小
+									color: "#fff", //颜色
+									lineHeight: 25, //行高
+									mt: 20, //margin-top
+									align: 'center'
+								},
+								txt: {
+									text: res.data.title, //文本
+									fontSize: 16, //字体大小
+									color: "#000", //颜色
+									lineHeight: 25, //行高
+									mt: 20, //margin-top
+									align: 'center'
+								},
+							}
 					}
 				}).catch(() => {
 					uni.hideLoading();
@@ -172,6 +221,24 @@
 					url: '/pages/index/index'
 				})
 			},
+
+			previewImage() {
+
+			},
+
+			saveImg() {
+				this.$refs.hchPoster.posterShow()
+			},
+
+			handleCancel() {
+
+			},
+			
+			toIndex() {
+				uni.switchTab({
+					url: '/pages/index/index'
+				})
+			},
 		}
 	}
 </script>
@@ -183,14 +250,14 @@
 		background-image: linear-gradient(to right, #ebbba7 0%, #cfc7f8 100%);
 
 		&-number {
-			padding-top: 400rpx;
+			padding-top: 300rpx;
 
 			&-circle {
 				box-sizing: border-box;
 				flex-direction: column;
 				width: 336rpx;
 				height: 336rpx;
-				background-color: $uni-bg-color;
+				background-color: #FFFFFF;
 				border-radius: 50%;
 				margin: auto;
 
@@ -199,18 +266,20 @@
 				}
 
 				.num {
-					font-size: 100rpx;
+					font-size: 120rpx;
+					color: #E86737;
 				}
 
 				.luckyNum {
-					font-size: 36rpx;
+					font-size: 120rpx;
+					color: #E86737;
 				}
 			}
 		}
 
 		&-title {
 			margin-top: 40rpx;
-			margin-bottom: 70rpx;
+			margin-bottom: 10rpx;
 
 			.txt {
 				text-align: center;
@@ -223,8 +292,21 @@
 			.id {
 				line-height: 40rpx;
 				text-align: center;
+				color: #888787;
 			}
 		}
+		
+		&-tip{
+			padding: 0 40rpx;
+			color: #333;
+			width: 80vw;
+			height: 200rpx;;
+			border-radius: 10rpx;
+			background-color: rgba(255, 255, 255, 20);
+			// opacity: .4;
+			text-align: center;
+			margin: 0 auto 20rpx;
+		}
 
 		&-btn {
 			.pay {

+ 2 - 1
pages/prize/coupon.vue

@@ -27,7 +27,8 @@
 						<view class="flex btn">
 							<view class="amt"><text>¥</text>{{ item.discount / 100 }}</view>
 						</view>
-						<view class="state">{{ item.status.desc }}</view>
+						<view class="state" v-if="state == 2">已使用</view>
+						<view class="state" v-else>已过期</view>
 					</view>
 				</view>
 			</view>

BIN
static/tabbar/core.png


BIN
static/tabbar/core_select.png


BIN
static/tabbar/index.png


BIN
static/tabbar/index_select.png


BIN
static/tabbar/law.png


BIN
static/tabbar/law_select.png


BIN
static/tabbar/news.png


BIN
static/tabbar/news_select.png


BIN
static/tabbar/user.png


BIN
static/tabbar/user_select.png


+ 1 - 0
uni.scss

@@ -13,6 +13,7 @@
  */
 
 /* 颜色变量 */
+$uni-btn-color: #E96737;
 
 /* 行为相关颜色 */
 $uni-color-primary: #007aff;