// 2 роки тому
батько
коміт
03cfe20716

+ 2 - 7
component/activityPop/index.less

@@ -13,8 +13,8 @@
     .closeImg {
         width: 50rpx;
         height: 62rpx;
-        margin-top: 250rpx;
-        margin-left: 80%;
+        margin-top: 260rpx;
+        margin-left: 75%;
     }
 
     .activityImg {
@@ -24,9 +24,4 @@
         overflow: hidden;
     }
 
-    .btnImg {
-        width: 350rpx;
-        height: 82rpx;
-        margin-top: 60rpx;
-    }
 }

+ 1 - 3
component/activityPop/index.wxml

@@ -1,6 +1,4 @@
 <view class="popBox" wx:if="{{state}}">
     <image src="/static/image/lollipop.png" class="closeImg" catchtap="close" />
-    <image src="https://yfklxt-image.ai160.com/reader/20210630/1625021926320684.jpg" class="activityImg"
-        catchtap="jumpDet" />
-    <image src="/static/groupImg/tuanzhangIcon.png" class="btnImg" catchtap="jumpDet" />
+    <image src="http://reader-wx.ai160.com/images/reader/card/dialog.png" class="activityImg" catchtap="jumpDet" />
 </view>

+ 2 - 7
component/activityPop/index.wxss

@@ -13,8 +13,8 @@
 .popBox .closeImg {
   width: 50rpx;
   height: 62rpx;
-  margin-top: 250rpx;
-  margin-left: 80%;
+  margin-top: 260rpx;
+  margin-left: 75%;
 }
 .popBox .activityImg {
   width: 680rpx;
@@ -22,8 +22,3 @@
   border-radius: 20rpx;
   overflow: hidden;
 }
-.popBox .btnImg {
-  width: 350rpx;
-  height: 82rpx;
-  margin-top: 60rpx;
-}

+ 674 - 0
component/yeyouzi-cropper/yeyouzi-cropper.js

@@ -0,0 +1,674 @@
+// components/yeyouzi-cropper/yeyouzi-cropper.js
+let success;
+let fail;
+Component({
+  /**
+   * 组件的属性列表
+   */
+  properties: {
+
+  },
+
+  /**
+   * 组件的初始数据
+   */
+  data: {
+    canvas: '',
+    ctx: '',
+    dpr: '',
+    x1: 0,
+    y1: 0,
+    x2: 0,
+    y2: 0,
+    k1: 0,
+    m1: 0,
+    k2: 0,
+    m2: 0,
+    cutMove: false,
+    endCut: {
+      x: 0,
+      y: 0
+    },
+    movePoint: '0',
+    img: {
+      path: '',
+      width: 0,
+      height: 0,
+      type: 1    // 1:横向 2:纵向
+    },
+    imageWidth: 0,
+    imageHeight: 0,
+    imageLeft: 0,
+    imageTop: 0,
+    imgRotate: 0,
+    imgMirror: 0,
+    originWidthShow: 0.5,
+    originHeightShow: 0.5,
+    imgMove: false,
+    imgStart: {
+      x: 0,
+      y: 0,
+      left: 0,
+      top: 0,
+      distance: 0,
+      width: 0,
+      height: 0,
+      cutImg: ''
+    },
+    imgScale: false,
+
+    cutImg: {
+      path: '',
+      x: 0,
+      y: 0,
+      width: 0,
+      height: 0
+    }
+
+
+  },
+
+  /**
+   * 组件的方法列表
+   */
+  methods: {
+    /**
+     * 公有方法
+     */
+
+    //初始化
+    init(param){
+      success = param.success
+      fail = param.fail
+      var that = this;
+      this.setData({
+        img: {
+          path: param.imgPath
+        }
+      })
+      const query = wx.createSelectorQuery().in(this)
+      query.select('#cutCanvas')
+          .fields({node: true, size: true})
+          .exec((res) => {
+            const canvas = res[0].node
+            const ctx = canvas.getContext('2d')
+            const dpr = wx.getSystemInfoSync().pixelRatio
+            canvas.width = res[0].width * dpr
+            canvas.height = res[0].height * dpr
+            ctx.scale(dpr,dpr)
+
+            var x1 = canvas.width * 0.15 / dpr;
+            var y1 = (canvas.height - canvas.width * 0.7) / 2 / dpr;
+            var x2 = x1 + canvas.width * 0.7 / dpr;
+            var y2 = y1 + canvas.width * 0.7 / dpr;
+            var k1 = (y2 -y1) / (x2 - x1);
+            var m1 = (x2 * y1 - x1 * y2) / (x2 - x1)
+            var k2 = (y1 - y2) / (x2 -x1);
+            var m2 = (x2 * y2 - x1 * y1) / (x2 - x1);
+            that.setData({
+              canvas: canvas,
+              ctx: ctx,
+              dpr: dpr,
+              x1: x1,
+              y1: y1,
+              x2: x2,
+              y2: y2,
+              k1: k1,
+              m1: m1,
+              k2: k2,
+              m2: m2
+            })
+            this._drawCut(x1, y1, x2, y2)
+            wx.getImageInfo({
+              src: param.imgPath,
+              success(img){
+                var width = '';
+                var height = '';
+                var type = 0;
+                var x = '';var y = '';var d = '';
+                if(img.width > img.height){
+                  height = that.data.y2 - that.data.y1;
+                  width = (img.width * height) / img.height
+                  type = 1
+                  d = img.height
+                  x = (img.width - d) / 2
+                  y = 0
+                }else{
+                  width = that.data.x2 - that.data.x1;
+                  height = (img.height * width) / img.width
+                  type = 2
+                  d = img.width
+                  x = 0
+                  y = (img.height - d) / 2
+                }
+                that.setData({
+                  img: {
+                    path: param.imgPath,
+                    width: img.width,
+                    height: img.height,
+                    type: type
+                  },
+                  cutImg: {
+                    x: x,
+                    y: y,
+                    width: d,
+                    height: d
+                  },
+                  imageWidth: ((x2 - x1) / d) * img.width,
+                  imageHeight: ((y2 - y1) / d) * img.height,
+                  imageLeft: x1 - ((x2 - x1) / d) * x,
+                  imageTop: y1 - ((y2 - y1) / d) * y,
+                  imgRotate: 0
+                })
+              }
+            })
+          })
+          
+    },
+
+    /**
+     * 私有方法
+     */
+    _drawCut(x1, y1, x2, y2){
+      var ctx = this.data.ctx;
+      var canvas = this.data.canvas;
+      ctx.clearRect(0, 0, canvas.width, canvas.height)
+      ctx.globalAlpha = '0.5'
+      ctx.fillStyle = '#000000'
+      ctx.fillRect(0, 0, canvas.width, canvas.height)
+
+      ctx.strokeStyle = '#ffffff'
+      ctx.lineWidth = '3'
+      ctx.lineCap = 'square'
+      ctx.globalAlpha = '1'
+      ctx.strokeRect(x1, y1, x2 - x1, y2 - y1)
+      ctx.fillStyle = '#ffffff'
+      ctx.fillRect(x1 - 5, y1 - 5, 20, 20)//左上角 1
+      ctx.fillRect(x2 - 15, y1 - 5, 20, 20)//右上角 2
+      ctx.fillRect(x1 - 5, y2 - 15, 20, 20)//左下角 3
+      ctx.fillRect(x2 - 15, y2 - 15, 20 , 20)//右下角 4
+      ctx.clearRect(x1, y1, x2 - x1, y2 -y1)
+    },
+
+    _touchStart(e){
+      //裁剪框是否移动
+      var flag = false;
+      var point = '0'
+      if(e.touches[0].x >= this.data.x1 - 10 && this.data.x1 + 10 >= e.touches[0].x){
+        if(e.touches[0].y >= this.data.y1 - 10 && this.data.y1 + 10 >= e.touches[0].y){
+          flag = true; point = '1';
+          this.setData({
+            endCut:{
+              x: this.data.x1,
+              y: this.data.y1
+            }
+          })
+        }else if(e.touches[0].y >= this.data.y2 - 10 && this.data.y2 + 10 >= e.touches[0].y){
+          flag = true; point = '3';
+          this.setData({
+            endCut:{
+              x: this.data.x1,
+              y: this.data.y2
+            }
+          })
+        }
+      }else if(e.touches[0].x >= this.data.x2 - 10 && this.data.x2 + 10 >= e.touches[0].x){
+        if(e.touches[0].y >= this.data.y1 - 10 && this.data.y1 + 10 >= e.touches[0].y){
+          flag = true; point = '2'
+          this.setData({
+            endCut:{
+              x: this.data.x2,
+              y: this.data.y1
+            }
+          })
+        }else if(e.touches[0].y >= this.data.y2 - 10 && this.data.y2 + 10 >= e.touches[0].y){
+          flag = true; point = '4'
+          this.setData({
+            endCut:{
+              x: this.data.x2,
+              y: this.data.y2
+            }
+          })
+        }
+      }
+      this.setData({
+        cutMove: flag,
+        movePoint: point
+      })
+
+      //图片是否移动
+      if(e.touches[0].x >= this.data.x1 + 10 && this.data.x2 - 10 >= e.touches[0].x){
+        if(e.touches[0].y >= this.data.y1 + 10 && this.data.y2 - 10 >= e.touches[0].y){
+          if(e.touches.length == 1){
+            this.setData({
+              imgMove: true,
+              imgStart: {
+                x: e.touches[0].x,
+                y: e.touches[0].y,
+                left: this.data.imageLeft,
+                top: this.data.imageTop
+              },
+              imgScale: false
+            })
+          }else if(e.touches.length == 2){
+            this.setData({
+              imgMove: false,
+              imgStart: {
+                distance: Math.sqrt(Math.pow(e.touches[1].x - e.touches[0].x, 2) + Math.pow(e.touches[1].y - e.touches[0].y, 2)),
+                width: this.data.imageWidth,
+                height: this.data.imageHeight,
+                cutImg: this.data.cutImg
+              },
+              imgScale: true
+            })
+          }
+        }
+      }
+    },
+
+    _touchMove(e){
+      if(this.data.cutMove){
+        var x1;var y1;var x2;var y2;
+        if(this.data.movePoint == '1'){
+          x1 = e.touches[0].x
+          y1 = this.data.k1 * x1 + this.data.m1
+          x2 = this.data.x2
+          y2 = this.data.y2
+          if(x1 > x2 -100){
+            x1 = x2 - 100
+            y1 = this.data.k1 * x1 + this.data.m1
+          }else if(x1 < this.data.x1){
+            x1 = this.data.x1
+            y1 = this.data.k1 * x1 + this.data.m1
+          }
+          this.setData({
+            endCut:{
+              x: x1,
+              y: y1
+            }
+          })
+        }else if(this.data.movePoint == '2'){
+          x2 = e.touches[0].x
+          y1 = this.data.k2 * x2 + this.data.m2
+          x1 = this.data.x1
+          y2 = this.data.y2
+          if(x2 > this.data.x2){
+            x2 = this.data.x2
+            y1 = this.data.y1
+          }else if(x2 < this.data.x1 + 100){
+            x2 = this.data.x1 + 100
+            y1 = this.data.k2 * x2 + this.data.m2
+          }
+          this.setData({
+            endCut:{
+              x: x2,
+              y: y1
+            }
+          })
+        }else if(this.data.movePoint == '3'){
+          x1 = e.touches[0].x
+          y2 = this.data.k2 * x1 + this.data.m2
+          x2 = this.data.x2
+          y1 = this.data.y1
+          if(x1 > x2 - 100){
+            x1 = x2 - 100
+            y2 = this.data.k2 * x1 + this.data.m2
+          }else if(x1 < this.data.x1){
+            x1 = this.data.x1
+            y2 = this.data.y2
+          }
+          this.setData({
+            endCut:{
+              x: x1,
+              y: y2
+            }
+          })
+        }else if(this.data.movePoint == '4'){
+          x2 = e.touches[0].x
+          y2 = this.data.k1 * x2 + this.data.m1
+          x1 = this.data.x1
+          y1 = this.data.y1
+          if(x2 > this.data.x2){
+            x2 = this.data.x2
+            y2 = this.data.k1 * x2 + this.data.m1
+          }else if(x2 < x1 + 100){
+            x2 = x1 + 100
+            y2 = this.data.k1 * x2 + this.data.m1
+          }
+          this.setData({
+            endCut:{
+              x: x2,
+              y: y2
+            }
+          })
+        }
+        this._drawCut(x1, y1, x2, y2)
+      }else if(this.data.imgMove){
+        var dx = this.data.imgStart.x - e.touches[0].x
+        var dy = this.data.imgStart.y - e.touches[0].y
+        var rotate = this.data.imgRotate
+        var left = this.data.imgStart.left - dx
+        var top = this.data.imgStart.top - dy
+        if(this.data.imgMirror == 180){
+          dx = -dx
+          rotate = -rotate
+        }
+        var tx = dx * Math.cos(rotate * Math.PI / 180) + dy * Math.sin(rotate * Math.PI / 180)
+        var ty = dy * Math.cos(rotate * Math.PI / 180) - dx * Math.sin(rotate * Math.PI / 180)
+        var x = (tx + this.data.originWidthShow * this.data.imageWidth) / this.data.imageWidth * this.data.img.width - this.data.cutImg.width / 2
+        var y = (ty + this.data.originHeightShow * this.data.imageHeight) / this.data.imageHeight * this.data.img.height - this.data.cutImg.height / 2
+        this.setData({
+          cutImg: {
+            width: this.data.cutImg.width,
+            height: this.data.cutImg.height,
+            x: x,
+            y: y
+          },
+          imageLeft: left,
+          imageTop: top,
+        })
+      }else if(this.data.imgScale){
+        var nowDistance = Math.sqrt(Math.pow(e.touches[1].x - e.touches[0].x, 2) + Math.pow(e.touches[1].y - e.touches[0].y, 2))
+        var m = nowDistance / this.data.imgStart.distance
+        var width = this.data.imgStart.width * m
+        var height = this.data.imgStart.height * m
+        if(this.data.img.type == 1){
+          height = height < this.data.y2 - this.data.y1 ? this.data.y2 - this.data.y1 : height
+          height = height > (this.data.y2 - this.data.y1)*10 ? (this.data.y2 - this.data.y1)*10 : height
+          width = (height * this.data.img.width) / this.data.img.height
+        }else{
+          width = width < this.data.x2 - this.data.x1 ? this.data.x2 - this.data.x1 : width
+          width = width > (this.data.x2 - this.data.x1)*10 ? (this.data.x2 - this.data.x1)*10 : width
+          height = (width * this.data.img.height) / this.data.img.width
+        }
+        var n = width / this.data.imgStart.width
+        var cut = {
+          x: this.data.imgStart.cutImg.x + ((n - 1) / (2 * n)) * this.data.imgStart.cutImg.width,
+          y: this.data.imgStart.cutImg.y + ((n - 1) / (2 * n)) * this.data.imgStart.cutImg.height,
+          width: this.data.imgStart.cutImg.width / n,
+          height: this.data.imgStart.cutImg.height / n
+        }
+        var left = this.data.x1 - ((this.data.x2 - this.data.x1) / cut.width) * cut.x
+        left = left > this.data.x1 ? this.data.x1 : left
+        left = left < this.data.x2 - this.data.imageWidth ? this.data.x2 - this.data.imageWidth :left
+        var top = this.data.y1 - ((this.data.y2 - this.data.y1) / cut.height) * cut.y
+        top = top > this.data.y1 ? this.data.y1 : top
+        top = top < this.data.y2 - this.data.imageHeight ? this.data.y2 - this.data.imageHeight : top
+        this.setData({
+          imageLeft: left,
+          imageTop: top,
+          imageWidth: width,
+          imageHeight: height,
+          cutImg: {
+            x: cut.x,
+            y: cut.y,
+            width: cut.width,
+            height: cut.height
+          },
+        })
+      }
+    },
+
+    _touchEnd(e){
+      if(this.data.cutMove){
+        var dx;var dy;var d;
+        var movePoint = this.data.movePoint
+        if(movePoint % 2 == 0){
+          d = ((this.data.endCut.x - this.data.x1) * this.data.cutImg.width) / (this.data.x2 - this.data.x1)
+          if(this.data.imgMirror == 180){
+            dx = -(this.data.endCut.x - this.data.x2) / this.data.imageWidth * this.data.img.width /2
+            if(movePoint == '2'){
+              dy = (this.data.endCut.y - this.data.y1) / this.data.imageHeight * this.data.img.height /2
+            }else{
+              dy = (this.data.endCut.y - this.data.y2) / this.data.imageHeight * this.data.img.height /2
+            }
+          }else{
+            dx = (this.data.endCut.x - this.data.x2) / this.data.imageWidth * this.data.img.width /2
+            if(movePoint == '2'){
+              dy = (this.data.endCut.y - this.data.y1) / this.data.imageHeight * this.data.img.height /2
+            }else{
+              dy = (this.data.endCut.y - this.data.y2) / this.data.imageHeight * this.data.img.height /2
+            }
+          }
+        }else{
+          d = ((this.data.x2 - this.data.endCut.x) * this.data.cutImg.width) / (this.data.x2 - this.data.x1)
+          if(this.data.imgMirror == 180){
+            dx = -(this.data.endCut.x - this.data.x1) / this.data.imageWidth * this.data.img.width /2
+            if(movePoint == '1'){
+              dy = (this.data.endCut.y - this.data.y1) / this.data.imageHeight * this.data.img.height /2
+            }else{
+              dy = (this.data.endCut.y - this.data.y2) / this.data.imageHeight * this.data.img.height /2
+            }
+          }else{
+            dx = (this.data.endCut.x - this.data.x1) / this.data.imageWidth * this.data.img.width /2
+            if(movePoint == '1'){
+              dy = (this.data.endCut.y - this.data.y1) / this.data.imageHeight * this.data.img.height /2
+            }else{
+              dy = (this.data.endCut.y - this.data.y2) / this.data.imageHeight * this.data.img.height /2
+            }
+          }
+        }
+        var rotate = this.data.imgMirror == 180 ? -this.data.imgRotate : this.data.imgRotate
+        var x = ((dx * Math.cos(rotate * Math.PI / 180) + dy * Math.sin(rotate * Math.PI / 180)) + this.data.originWidthShow * this.data.img.width) - d / 2
+        var y = ((dy * Math.cos(rotate * Math.PI / 180) - dx * Math.sin(rotate * Math.PI / 180)) + this.data.originHeightShow * this.data.img.height) - d / 2
+        this.setData({
+          cutImg:{
+            x: x,
+            y: y,
+            width: d,
+            height: d
+          },
+          imageWidth: ((this.data.x2 - this.data.x1) / d) * this.data.img.width,
+          imageHeight: ((this.data.y2 - this.data.y1) / d) * this.data.img.height,
+          imageLeft: this.data.x1 - ((this.data.x2 - this.data.x1) / d) * x,
+          imageTop: this.data.y1 - ((this.data.y2 - this.data.y1) / d) * y,
+          
+        })
+        this._drawCut(this.data.x1,this.data.y1,this.data.x2,this.data.y2)
+      }
+      if(this.data.imgMove){
+        var left = this.data.x1 - ((this.data.x2 - this.data.x1) / this.data.cutImg.width) * this.data.cutImg.x
+        var top = this.data.y1 - ((this.data.y2 - this.data.y1) / this.data.cutImg.height) * this.data.cutImg.y
+        this.setData({
+          imageLeft: left,
+          imageTop: top,
+        })
+      }
+      this.setData({
+        originWidthShow: (this.data.cutImg.x + this.data.cutImg.width / 2) / this.data.img.width,
+        originHeightShow: (this.data.cutImg.y + this.data.cutImg.height / 2) / this.data.img.height,
+        cutMove: false,
+        movePoint: '0',
+        imgMove: false,
+        imgScale: false
+      })
+    },
+
+    _rotateChange(e){
+      this.setData({
+        imgRotate: e.detail.value
+      })
+    },
+
+    _rotateNinety(){
+      var r = this.data.imgRotate + 90 > 180 ? this.data.imgRotate - 270 : this.data.imgRotate + 90
+      this.setData({
+        imgRotate: r
+      })
+    },
+
+    _imageMirror(){
+      var m = this.data.imgMirror == 180 ? 0 : 180
+      this.setData({
+        imgMirror: m,
+      })
+    },
+
+    _imgRestore(){
+      this.setData({
+        canvas: '',
+        ctx: '',
+        x1: 0,
+        y1: 0,
+        x2: 0,
+        y2: 0,
+        k1: 0,
+        m1: 0,
+        k2: 0,
+        m2: 0,
+        cutMove: false,
+        endCut: {
+          x: 0,
+          y: 0
+        },
+        movePoint: '0',
+        imageWidth: 0,
+        imageHeight: 0,
+        imageLeft: 0,
+        imageTop: 0,
+        imgRotate: 0,
+        imgMirror: 0,
+        originWidthShow: 0.5,
+        originHeightShow: 0.5,
+        imgMove: false,
+        imgStart: {
+          x: 0,
+          y: 0,
+          left: 0,
+          top: 0,
+          distance: 0,
+          width: 0,
+          height: 0,
+          cutx: 0,
+          cuty: 0
+        },
+        imgScale: false,
+
+        cutImg: {
+          path: '',
+          x: 0,
+          y: 0,
+          width: 0,
+          height: 0
+        }
+      })
+      this.init(this.data.img.path)
+    },
+
+    _cancelCut(){
+      this._restoreData()
+      if(fail){
+        fail('cancel')
+      }
+    },
+
+    _confirmCut(){
+      wx.showLoading({
+        title: '裁剪中...',
+        mask: true
+      })
+      var that = this
+      const query = wx.createSelectorQuery().in(this)
+      query.select('#imgCanvas')
+          .fields({node: true, size: true})
+          .exec((res) => {
+            const canvas = res[0].node
+            const ctx = canvas.getContext('2d')
+            canvas.width = that.data.cutImg.width
+            canvas.height = that.data.cutImg.height
+            ctx.translate(canvas.width / 2, canvas.height / 2)
+            ctx.rotate((that.data.imgRotate >= 0 ? that.data.imgRotate : that.data.imgRotate + 360) * Math.PI / 180)
+            if(that.data.imgMirror == 180){
+              ctx.scale(-1, 1); //左右镜像翻转
+            }
+            const img = canvas.createImage()
+            img.src = that.data.img.path
+            img.onload = () => {
+              ctx.drawImage(img, 0, 0, that.data.img.width, that.data.img.height, -(that.data.cutImg.x+canvas.width/2), -(that.data.cutImg.y+canvas.height/2), that.data.img.width, that.data.img.height)
+
+              wx.canvasToTempFilePath({
+                canvas: canvas,
+                success(img){
+                  success(img.tempFilePath)
+                  that._restoreData()
+                  wx.hideLoading({
+                    success: (res) => {},
+                  })
+                },
+                fail(){
+                  wx.hideLoading({
+                    success: (res) => {
+                      wx.showToast({
+                        title: '裁剪失败',
+                        icon: 'error'
+                      })
+                      if(fail){
+                        fail('fail')
+                      }
+                    },
+                  })
+                }
+              })
+              
+            }
+          })
+      
+    },
+    
+    _restoreData(){
+      this.setData({
+        canvas: '',
+        ctx: '',
+        x1: 0,
+        y1: 0,
+        x2: 0,
+        y2: 0,
+        k1: 0,
+        m1: 0,
+        k2: 0,
+        m2: 0,
+        cutMove: false,
+        endCut: {
+          x: 0,
+          y: 0
+        },
+        movePoint: '0',
+        img: {
+          path: '',
+          width: 0,
+          height: 0,
+          type: 1    // 1:横向 2:纵向
+        },
+        imageWidth: 0,
+        imageHeight: 0,
+        imageLeft: 0,
+        imageTop: 0,
+        imgRotate: 0,
+        imgMirror: 0,
+        originWidthShow: 0.5,
+        originHeightShow: 0.5,
+        imgMove: false,
+        imgStart: {
+          x: 0,
+          y: 0,
+          left: 0,
+          top: 0,
+          distance: 0,
+          width: 0,
+          height: 0,
+          cutx: 0,
+          cuty: 0
+        },
+        imgScale: false,
+
+        cutImg: {
+          path: '',
+          x: 0,
+          y: 0,
+          width: 0,
+          height: 0
+        }
+      })
+    },
+  }
+})

+ 4 - 0
component/yeyouzi-cropper/yeyouzi-cropper.json

@@ -0,0 +1,4 @@
+{
+  "component": true,
+  "usingComponents": {}
+}

+ 30 - 0
component/yeyouzi-cropper/yeyouzi-cropper.wxml

@@ -0,0 +1,30 @@
+<!--components/yeyouzi-cropper/yeyouzi-cropper.wxml-->
+<!-- <view class="Container{{img.path != '' ? '-show' : ''}}"> -->
+<view class="Container-show" wx:if="{{img.path != ''}}">
+  <view class="imgContainer">
+    <canvas type="2d" id="cutCanvas" style="width: 100%;height: 100%;z-index:9999;" bindtouchstart="_touchStart" bindtouchend="_touchEnd" bindtouchmove="_touchMove" ></canvas>
+
+    <view style="position: absolute;top:{{imageTop}}px;left: {{imageLeft}}px;transform: rotateY({{imgMirror}}deg);transform-origin:{{originWidthShow * 100}}% {{originHeightShow * 100}}%;">
+      <image src="{{img.path}}" style="width:{{imageWidth}}px;height:{{imageHeight}}px;transform: rotateZ({{imgMirror == 180 ? -imgRotate : imgRotate}}deg);transform-origin:{{originWidthShow * 100}}% {{originHeightShow * 100}}%;"></image>
+    </view>
+
+  </view>
+  <view class="settingContainer">
+    <view class="rotate" style="color: #fff;width: 100%;text-align: center;">{{imgRotate}}°</view>
+    <view class="rotateContainer">
+      <text style="color: #fff;font-size: 20px;" bindtap="_imageMirror">⇌</text>
+      <slider style="width: 100%;" min="-180" max="180" value="{{imgRotate}}" block-size="18px" selected-color="#fff" bindchanging="_rotateChange"></slider>
+      <text style="color: #fff;font-size: 22px;" bindtap="_rotateNinety">⊙</text>
+    </view>
+
+    <view class="btnContainer">
+      <text style="color: #fff;font-size: 24px;" bindtap="_cancelCut">×</text>
+      <text style="color: #fff;font-size: 16px;text-align:center;align-self: center;" bindtap="_imgRestore">还原</text>
+      <text style="color: #fff;font-size: 24px;" bindtap="_confirmCut">✓</text>
+    </view>
+    
+  </view>
+
+  <canvas type="2d" id="imgCanvas" style="width: 0;height: 0;"></canvas>
+  
+</view>

+ 51 - 0
component/yeyouzi-cropper/yeyouzi-cropper.wxss

@@ -0,0 +1,51 @@
+/* components/yeyouzi-cropper/yeyouzi-cropper.wxss */
+.Container{
+  opacity: 0;
+  z-index: -9999;
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  height: 100%;
+  position: fixed;
+  left: 0;
+  top: 0;
+}
+
+.Container-show{
+  position: fixed;
+  left: 0;
+  top: 0;
+  background:#000;
+  display: flex;
+  width: 100%;
+  height: 100%;
+  flex-direction: column;
+  opacity: 1;
+  z-index: 999;
+}
+
+.imgContainer{
+  height: 100%;
+  width: 100%;
+  position: relative;
+}
+
+.settingContainer{
+  background: #000;
+  padding: 10px 0;
+  z-index: 10000;
+}
+
+.rotateContainer{
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding: 0 20px;
+}
+
+.btnContainer{
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  padding: 20px;
+}

+ 369 - 348
pages/activityDet/index.js

@@ -1,373 +1,394 @@
 import {
-  getActivityInfo,
-  getShareText,
-  saveActivity
+    getActivityInfo,
+    getShareText,
+    saveActivity
 } from '~/api/activity'
 import {
-  actionRecord
+    actionRecord
 } from '~/api/global'
 /*微信录音*/
 let recorderManager = wx.getRecorderManager();
 let dsq
 Page({
-  /**
-   * 页面的初始数据
-   */
-  data: {
-    // 'before录制前, process 录制中,after录制后'
-    state: 'before',
-    tens: 3,
-    bits: 0,
-    fromWidth: 100,
-    toWidth: 100,
-    configure: {},
-    avatar: '',
-    // 本地录音地址
-    tempFilePath: '',
-    // 线上录音地址
-    audioPath: '',
-    uploadState: false,
-    // 此id保存模板使用
-    id: '',
-    greeting: [],
-    // 是否更改过头像
-    changeAvatarFlag: false,
-    greetingCard: {
-      audioPath: "https://reader-wx.ai160.com/reader/resource/20230111/1673407488488535.mp3",
-      cardUrl: "https://reader-wx.ai160.com/reader/resource/20230111/1673407490510737.png",
-      duration: 6,
-      gmtCreated: null,
-      gmtModified: null,
-      id: 1673407492033889,
-      likeAmount: null,
-      playAmount: null,
-      status: null,
-      templateId: 50,
-      templateName: "",
-      uid: "9db2bedb2b9b47c5b0358bb9bec39145"
+    /**
+     * 页面的初始数据
+     */
+    data: {
+        // 'before录制前, process 录制中,after录制后'
+        state: 'before',
+        tens: 3,
+        bits: 0,
+        fromWidth: 100,
+        toWidth: 100,
+        configure: {},
+        avatar: '',
+        // 本地录音地址
+        tempFilePath: '',
+        // 线上录音地址
+        audioPath: '',
+        uploadState: false,
+        // 此id保存模板使用
+        id: '',
+        greeting: [],
+        // 是否更改过头像
+        changeAvatarFlag: false,
+        greetingCard: {
+            audioPath: "https://reader-wx.ai160.com/reader/resource/20230111/1673407488488535.mp3",
+            cardUrl: "https://reader-wx.ai160.com/reader/resource/20230111/1673407490510737.png",
+            duration: 6,
+            gmtCreated: null,
+            gmtModified: null,
+            id: 1673407492033889,
+            likeAmount: null,
+            playAmount: null,
+            status: null,
+            templateId: 50,
+            templateName: "",
+            uid: "9db2bedb2b9b47c5b0358bb9bec39145"
+        },
+        userAudioState: false,
+        // 当前音频播放时长
+        playTime: '00:00',
+        endTime: '00:00',
+        vProgress: 0
     },
-    userAudioState: false,
-    // 当前音频播放时长
-    playTime: '00:00',
-    endTime: '00:00',
-    vProgress: 0
-  },
-  async onLoad(options) {
-    let configure = await getActivityInfo(options.id)
-    wx.setNavigationBarTitle({
-      title: configure.title,
-    })
-    this.setData({
-      configure,
-      avatar: configure.photoText,
-      fromWidth: configure.fromText.length * configure.fromFontSize,
-      toWidth: configure.toText.length * configure.toFontSize,
-      id: options.id,
-      greeting: configure.greeting.split('\r'),
-      tens: configure.bgMusicLength[0],
-      bits: configure.bgMusicLength[1]
-    })
-    this.innerAudioContext = wx.createInnerAudioContext();
-    // 录音授权
-    wx.getSetting({
-      success(res) {
-        console.log(res);
-        if (!res.authSetting['scope.record']) {
-          wx.authorize({
-            scope: 'scope.record',
-            success() {
-              // 用户已经同意小程序使用录音功能,后续调用接口不会弹窗询问
+    async onLoad(options) {
+        let configure = await getActivityInfo(options.id)
+        wx.setNavigationBarTitle({
+            title: configure.title,
+        })
+        this.setData({
+            configure,
+            avatar: configure.photoText,
+            fromWidth: configure.fromText.length * configure.fromFontSize,
+            toWidth: configure.toText.length * configure.toFontSize,
+            id: options.id,
+            greeting: configure.greeting.split('\r'),
+            tens: configure.bgMusicLength[0],
+            bits: configure.bgMusicLength[1]
+        })
+        this.innerAudioContext = wx.createInnerAudioContext();
+        // 录音授权
+        wx.getSetting({
+            success(res) {
+                console.log(res);
+                if (!res.authSetting['scope.record']) {
+                    wx.authorize({
+                        scope: 'scope.record',
+                        success() {
+                            // 用户已经同意小程序使用录音功能,后续调用接口不会弹窗询问
+                        }
+                    })
+                }
             }
-          })
-        }
-      }
-    })
-    await actionRecord({
-      action: 'NEW_YEAR_ACTIVITY_CHOOSE_TEMPLATE',
-      targetContent: options.id
-    })
-  },
-  async changeAvatar(e) {
-    const {
-      avatarUrl
-    } = e.detail
-    let res = await this.uploadFile(avatarUrl)
-    this.setData({
-      changeAvatarFlag: true,
-      avatar: res
-    })
-  },
-  play() {
-    if (this.data.state == 'before') {
-      this.innerAudioContext.src = this.data.configure.bgMusic; // 这里可以是录音的临时路径
-      this.innerAudioContext.play();
-      this.innerAudioContext.onEnded((res) => {
-        console.log('音频播放完毕');
+        })
+        await actionRecord({
+            action: 'NEW_YEAR_ACTIVITY_CHOOSE_TEMPLATE',
+            targetContent: options.id
+        })
+
+    },
+    showActionSheet() {
+        wx.chooseMedia({
+            count: 1,
+            mediaType: ['image'],
+            sourceType: ['album', 'camera'],
+            camera: 'back',
+            success: (res) => {
+                this.cropper = this.selectComponent("#yeyouzi-cropper");
+                this.cropper.init({
+                    imgPath: res.tempFiles[0].tempFilePath, //imgPath是需要裁剪图片的图片路径,只支持本地或临时路径
+                    success: (res) => {
+                        this.changeAvatar(res)
+                    },
+                    fail(error) {
+                        console.log(error) //有两种:cancel代表点击了叉,fail代表wx.canvasToTempFilePath生成图片失败
+                    }
+                });
+            }
+        })
+    },
+    async changeAvatar(e) {
+        /*    const {
+               avatarUrl
+           } = e.detail */
+        let res = await this.uploadFile(e)
         this.setData({
-          userAudioState: false
+            changeAvatarFlag: true,
+            avatar: res
         })
-      });
-      this.setData({
-        state: 'process'
-      })
-      let countDown = Number(this.data.configure.bgMusicLength)
-      // 倒计时
-      this.dsq = setInterval(item => {
-        console.log('仍然倒计时呢');
-        // 倒计时结束
-        if (countDown == 1) {
-          this.stopRecording()
-        }
-        if (countDown % 10 == 0) {
-          this.setData({
-            tens: --this.data.tens,
-            bits: 9
-          })
+    },
+    play() {
+        if (this.data.state == 'before') {
+            this.innerAudioContext.src = this.data.configure.bgMusic; // 这里可以是录音的临时路径
+            this.innerAudioContext.play();
+            this.innerAudioContext.onEnded((res) => {
+                console.log('音频播放完毕');
+                this.setData({
+                    userAudioState: false
+                })
+            });
+            this.setData({
+                state: 'process'
+            })
+            let countDown = Number(this.data.configure.bgMusicLength)
+            // 倒计时
+            this.dsq = setInterval(item => {
+                console.log('仍然倒计时呢');
+                // 倒计时结束
+                if (countDown == 1) {
+                    this.stopRecording()
+                }
+                if (countDown % 10 == 0) {
+                    this.setData({
+                        tens: --this.data.tens,
+                        bits: 9
+                    })
+                } else {
+                    this.setData({
+                        bits: --this.data.bits
+                    })
+                }
+                --countDown
+            }, 1000)
+            const options = {
+                sampleRate: 44100, //采样率
+                numberOfChannels: 1, //录音通道数
+                encodeBitRate: 192000, //编码码率
+                format: 'mp3', //音频格式,有效值aac/mp3
+                frameSize: 50 //指定帧大小,单位 KB
+            };
+            //开始录音,在开始录音回调中feed音频片
+            recorderManager.start(options);
+            //监听录音结束事件
+            recorderManager.onStop((res) => {
+                this.setData({
+                    tempFilePath: res.tempFilePath,
+                });
+                this.uploadAudio(res.tempFilePath)
+            });
         } else {
-          this.setData({
-            bits: --this.data.bits
-          })
+            this.stopRecording()
         }
-        --countDown
-      }, 1000)
-      const options = {
-        sampleRate: 44100, //采样率
-        numberOfChannels: 1, //录音通道数
-        encodeBitRate: 192000, //编码码率
-        format: 'mp3', //音频格式,有效值aac/mp3
-        frameSize: 50 //指定帧大小,单位 KB
-      };
-      //开始录音,在开始录音回调中feed音频片
-      recorderManager.start(options);
-      //监听录音结束事件
-      recorderManager.onStop((res) => {
-        this.setData({
-          tempFilePath: res.tempFilePath,
-        });
-        this.uploadAudio(res.tempFilePath)
-      });
-    } else {
-      this.stopRecording()
-    }
-  },
-  stopRecording() {
-    clearInterval(this.dsq)
-    this.innerAudioContext.stop();
-    recorderManager.stop();
-    this.setData({
-      state: 'after',
-      tens: this.data.configure.bgMusicLength[0],
-      bits: this.data.configure.bgMusicLength[1]
-    })
-  },
-  uploadAudio(recordSource) {
-    this.setData({
-      uploadState: true
-    });
-    const uploadTask = wx.uploadFile({
-      url: 'https://reader-api.ai160.com//file/upload',
-      filePath: recordSource,
-      name: '朗读录音',
-      header: {
-        uid: wx.getStorageSync('uid')
-      },
-      success: (res) => {
-        const formateRes = JSON.parse(res.data);
-        let audioPath = formateRes.data;
+    },
+    stopRecording() {
+        clearInterval(this.dsq)
+        this.innerAudioContext.stop();
+        recorderManager.stop();
         this.setData({
-          audioPath
+            state: 'after',
+            tens: this.data.configure.bgMusicLength[0],
+            bits: this.data.configure.bgMusicLength[1]
         })
-        this.uploadActivity()
-      },
-    })
-  },
-  // 上传贺卡
-  async uploadActivity() {
-    this.createActivityImg('upload').then(async res => {
-      let cardUrl = await this.uploadFile(res)
-      let data = {
-        audioPath: this.data.audioPath,
-        // 生成贺卡图片地址
-        cardUrl,
-        toText: this.data.configure.toText,
-        fromText: this.data.configure.fromText,
-        templateId: this.data.id
-      }
-      console.log(data, 'data');
-      let greetingCard = await saveActivity(data)
-      console.log('贺卡生成', greetingCard);
-      this.setDuration('endTime', greetingCard.duration)
-      this.setData({
-        greetingCard,
-        uploadState: false
-      })
-      await actionRecord({
-        action: 'NEW_YEAR_ACTIVITY_GENERATE_TEMPLATE',
-        targetContent: this.data.id
-      })
-    })
-  },
-  playUserAudio() {
-    if (!this.innerAudioContext) {
-      this.innerAudioContext = wx.createInnerAudioContext();
-    }
-    if (this.data.userAudioState) {
-      this.innerAudioContext.stop();
-      this.setData({
-        userAudioState: false
-      })
-    } else {
-      this.innerAudioContext.src = this.data.greetingCard.audioPath;
-      this.innerAudioContext.onTimeUpdate(() => {
-        this.setDuration('playTime', this.innerAudioContext.currentTime)
+    },
+    uploadAudio(recordSource) {
         this.setData({
-          vProgress: Math.ceil((Math.ceil(this.innerAudioContext.currentTime) / this.innerAudioContext.duration) * 100)
+            uploadState: true
+        });
+        const uploadTask = wx.uploadFile({
+            url: 'https://reader-api.ai160.com//file/upload',
+            filePath: recordSource,
+            name: '朗读录音',
+            header: {
+                uid: wx.getStorageSync('uid')
+            },
+            success: (res) => {
+                const formateRes = JSON.parse(res.data);
+                let audioPath = formateRes.data;
+                this.setData({
+                    audioPath
+                })
+                this.uploadActivity()
+            },
         })
-      })
-      this.innerAudioContext.play();
-      this.setData({
-        userAudioState: true
-      })
-    }
-  },
-  bindKeyInput(e) {
-    if (e.currentTarget.dataset.type == 'from') {
-      this.setData({
-        fromWidth: e.detail.cursor * this.data.configure.fromFontSize,
-        'configure.fromText': e.detail.value
-      })
-    } else if (e.currentTarget.dataset.type == 'to') {
-      this.setData({
-        toWidth: e.detail.cursor * this.data.configure.toFontSize,
-        'configure.toText': e.detail.value
-      })
-    }
-  },
-  // 上传图片
-  uploadFile(filePath) {
-    return new Promise((resolve, reject) => {
-      wx.uploadFile({
-        url: 'https://reader-api.ai160.com/file/upload',
-        filePath,
-        name: '头像',
-        header: {
-          uid: wx.getStorageSync('uid')
-        },
-        success: (res) => {
-          const result = JSON.parse(res.data).data;
-          resolve(result)
-        }
-      })
-    })
-  },
-  // 生成活动图片
-  createActivityImg(createType = 'share') {
-    return new Promise(async (resolve, reject) => {
-      if (createType == 'share') {
-        let title = await getShareText({
-          cardReadId: this.data.greetingCard.id
+    },
+    // 上传贺卡
+    async uploadActivity() {
+        this.createActivityImg('upload').then(async res => {
+            let cardUrl = await this.uploadFile(res)
+            let data = {
+                audioPath: this.data.audioPath,
+                // 生成贺卡图片地址
+                cardUrl,
+                toText: this.data.configure.toText,
+                fromText: this.data.configure.fromText,
+                templateId: this.data.id
+            }
+            console.log(data, 'data');
+            let greetingCard = await saveActivity(data)
+            console.log('贺卡生成', greetingCard);
+            this.setDuration('endTime', greetingCard.duration)
+            this.setData({
+                greetingCard,
+                uploadState: false
+            })
+            await actionRecord({
+                action: 'NEW_YEAR_ACTIVITY_GENERATE_TEMPLATE',
+                targetContent: this.data.id
+            })
         })
-        resolve({
-          title,
-          path: `/pages/greeting/index?uid=${wx.getStorageSync('uid')}&cardId=${this.data.greetingCard.id}`,
-          imageUrl: this.data.greetingCard.cardUrl
+    },
+    playUserAudio() {
+        if (!this.innerAudioContext) {
+            this.innerAudioContext = wx.createInnerAudioContext();
+        }
+        if (this.data.userAudioState) {
+            this.innerAudioContext.stop();
+            this.setData({
+                userAudioState: false
+            })
+        } else {
+            this.innerAudioContext.src = this.data.greetingCard.audioPath;
+            this.innerAudioContext.onTimeUpdate(() => {
+                this.setDuration('playTime', this.innerAudioContext.currentTime)
+                this.setData({
+                    vProgress: Math.ceil((Math.ceil(this.innerAudioContext.currentTime) / this.innerAudioContext.duration) * 100)
+                })
+            })
+            this.innerAudioContext.play();
+            this.setData({
+                userAudioState: true
+            })
+        }
+    },
+    bindKeyInput(e) {
+        if (e.currentTarget.dataset.type == 'from') {
+            this.setData({
+                fromWidth: e.detail.cursor * this.data.configure.fromFontSize,
+                'configure.fromText': e.detail.value
+            })
+        } else if (e.currentTarget.dataset.type == 'to') {
+            this.setData({
+                toWidth: e.detail.cursor * this.data.configure.toFontSize,
+                'configure.toText': e.detail.value
+            })
+        }
+    },
+    // 上传图片
+    uploadFile(filePath) {
+        return new Promise((resolve, reject) => {
+            wx.uploadFile({
+                url: 'https://reader-api.ai160.com/file/upload',
+                filePath,
+                name: '头像',
+                header: {
+                    uid: wx.getStorageSync('uid')
+                },
+                success: (res) => {
+                    const result = JSON.parse(res.data).data;
+                    resolve(result)
+                }
+            })
         })
-      }
-      let context = wx.createSelectorQuery();
-      context
-        .select('#share')
-        .fields({
-          node: true,
-          size: true
-        }).exec((res) => {
-          const canvas = res[0].node;
-          const ctx = canvas.getContext('2d');
-          const dpr = wx.getSystemInfoSync().pixelRatio;
-          canvas.width = res[0].width * dpr;
-          canvas.height = res[0].height * dpr;
-          ctx.scale(dpr, dpr);
-          let avatar = canvas.createImage();
-          avatar.src = this.data.avatar
-          avatar.onload = () => {
-            ctx.drawImage(avatar, this.data.configure.templateBase.photoLeft / 2, this.data.configure.templateBase.photoTop / 2, this.data.configure.templateBase.photoWidth / 2, this.data.configure.templateBase.photoHeight / 2);
-            let bgImg = canvas.createImage();
-            bgImg.src = this.data.configure.bgImg
-            bgImg.onload = () => {
-              ctx.drawImage(bgImg, 0, 0, 375, 300);
-              ctx.font = `${this.data.configure.fromFontSize/2}px PingFang`;
-              ctx.fillText(this.data.configure.toText, this.data.configure.templateBase.toLeft / 2, this.data.configure.templateBase.toTop / 2 + this.data.configure.fromFontSize / 2)
-              ctx.fillText(this.data.configure.fromText, this.data.configure.templateBase.fromLeft / 2, this.data.configure.templateBase.fromTop / 2 + this.data.configure.toFontSize / 2)
-              console.log(this.data.configure.toText, this.data.configure.templateBase.toLeft / 2, this.data.configure.templateBase.toTop / 2);
-              console.log(this.data.configure.fromText, this.data.configure.templateBase.fromLeft / 2, this.data.configure.templateBase.fromTop / 2);
-              setTimeout(() => {
-                wx.canvasToTempFilePath({
-                  canvas: canvas,
-                  success(res) {
-                    resolve(res.tempFilePath)
-                  },
-                  fail(res) {
-                    reject()
-                  }
-                }, this)
-              }, 1000)
+    },
+    // 生成活动图片
+    createActivityImg(createType = 'share') {
+        return new Promise(async (resolve, reject) => {
+            if (createType == 'share') {
+                let title = await getShareText({
+                    cardReadId: this.data.greetingCard.id
+                })
+                resolve({
+                    title,
+                    path: `/pages/greeting/index?uid=${wx.getStorageSync('uid')}&cardId=${this.data.greetingCard.id}`,
+                    imageUrl: this.data.greetingCard.cardUrl
+                })
             }
-          }
+            let context = wx.createSelectorQuery();
+            context
+                .select('#share')
+                .fields({
+                    node: true,
+                    size: true
+                }).exec((res) => {
+                    const canvas = res[0].node;
+                    const ctx = canvas.getContext('2d');
+                    const dpr = wx.getSystemInfoSync().pixelRatio;
+                    canvas.width = res[0].width * dpr;
+                    canvas.height = res[0].height * dpr;
+                    ctx.scale(dpr, dpr);
+                    let avatar = canvas.createImage();
+                    avatar.src = this.data.avatar
+                    avatar.onload = () => {
+                        ctx.drawImage(avatar, this.data.configure.templateBase.photoLeft / 2, this.data.configure.templateBase.photoTop / 2, this.data.configure.templateBase.photoWidth / 2, this.data.configure.templateBase.photoHeight / 2);
+                        let bgImg = canvas.createImage();
+                        bgImg.src = this.data.configure.bgImg
+                        bgImg.onload = () => {
+                            ctx.drawImage(bgImg, 0, 0, 375, 300);
+                            ctx.font = `${this.data.configure.fromFontSize/2}px PingFang`;
+                            ctx.fillText(this.data.configure.toText, this.data.configure.templateBase.toLeft / 2, this.data.configure.templateBase.toTop / 2 + this.data.configure.fromFontSize / 2)
+                            ctx.fillText(this.data.configure.fromText, this.data.configure.templateBase.fromLeft / 2, this.data.configure.templateBase.fromTop / 2 + this.data.configure.toFontSize / 2)
+                            console.log(this.data.configure.toText, this.data.configure.templateBase.toLeft / 2, this.data.configure.templateBase.toTop / 2);
+                            console.log(this.data.configure.fromText, this.data.configure.templateBase.fromLeft / 2, this.data.configure.templateBase.fromTop / 2);
+                            setTimeout(() => {
+                                wx.canvasToTempFilePath({
+                                    canvas: canvas,
+                                    success(res) {
+                                        resolve(res.tempFilePath)
+                                    },
+                                    fail(res) {
+                                        reject()
+                                    }
+                                }, this)
+                            }, 1000)
+                        }
+                    }
+                })
         })
-    })
-  },
-  onShareAppMessage({
-    from,
-  }) {
-    if (from == 'button') {
-      actionRecord({
-        action: 'NEW_YEAR_ACTIVITY_SEND_BLESSING',
-      })
-      const promise = new Promise(resolve => {
-        this.createActivityImg().then(res => {
-          resolve(res)
+    },
+    onShareAppMessage({
+        from,
+    }) {
+        if (from == 'button') {
+            actionRecord({
+                action: 'NEW_YEAR_ACTIVITY_SEND_BLESSING',
+            })
+            const promise = new Promise(resolve => {
+                this.createActivityImg().then(res => {
+                    resolve(res)
+                })
+            })
+            return {
+                title: '请欣赏我的课文朗读作品,点赞+评论。',
+                path: `/pages/index/index?&uid=${wx.getStorageSync('uid')}`,
+                imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png',
+                promise
+            }
+        } else {
+            return {
+                title: '课文朗读,从未如此有趣。',
+                path: `/pages/index/index?&uid=${wx.getStorageSync('uid')}`,
+                imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png'
+            }
+        }
+    },
+    // 设置时间文案
+    setDuration(label, s) {
+        let t = '';
+        s = Math.ceil(s);
+        if (s > -1) {
+            let min = Math.floor(s / 60) % 60;
+            let sec = s % 60;
+            if (min < 10) {
+                t += "0";
+            }
+            t += min + ":";
+            if (sec < 10) {
+                t += "0";
+            }
+            t += sec;
+        }
+
+        this.setData({
+            [label]: t,
         })
-      })
-      return {
-        title: '请欣赏我的课文朗读作品,点赞+评论。',
-        path: `/pages/index/index?&uid=${wx.getStorageSync('uid')}`,
-        imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png',
-        promise
-      }
-    } else {
-      return {
-        title: '课文朗读,从未如此有趣。',
-        path: `/pages/index/index?&uid=${wx.getStorageSync('uid')}`,
-        imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png'
-      }
-    }
-  },
-  // 设置时间文案
-  setDuration(label, s) {
-    let t = '';
-    s = Math.ceil(s);
-    if (s > -1) {
-      let min = Math.floor(s / 60) % 60;
-      let sec = s % 60;
-      if (min < 10) {
-        t += "0";
-      }
-      t += min + ":";
-      if (sec < 10) {
-        t += "0";
-      }
-      t += sec;
+    },
+    onHide() {
+        recorderManager.stop()
+        this.innerAudioContext.stop()
+    },
+    onUnload() {
+        recorderManager.stop()
+        this.innerAudioContext.stop()
     }
-
-    this.setData({
-      [label]: t,
-    })
-  },
-  onHide() {
-    recorderManager.stop()
-    this.innerAudioContext.stop()
-  },
-  onUnload() {
-    recorderManager.stop()
-    this.innerAudioContext.stop()
-  }
 })

+ 3 - 1
pages/activityDet/index.json

@@ -1,4 +1,6 @@
 {
-    "usingComponents": {},
+    "usingComponents": {
+        "yeyouzi-cropper": "/component/yeyouzi-cropper/yeyouzi-cropper"
+    },
     "enablePullDownRefresh": false
 }

+ 61 - 60
pages/activityDet/index.wxml

@@ -1,69 +1,70 @@
 <view class="activityDet">
-  <view class="header" wx:if="{{state!='after'||!greetingCard.cardUrl}}">
-    <image src="{{configure.bgImg}}" class="templateImg" />
-    <view class="toBox" style="top:{{configure.templateBase.fromTop}}rpx;left: {{configure.templateBase.fromLeft}}rpx;">
-      <input value="{{configure.fromText}}" disabled="{{state=='process'}}" class="text" maxlength='8'
-        style="color:{{configure.fromColor}};font-size: {{configure.fromFontSize}}rpx;border-color: {{configure.fromColor}}60;width: {{fromWidth}}rpx;"
-        bindinput="bindKeyInput" data-type='from' />
-      <image src="/static/image/edit_new.png" wx:if="{{state!='process'}}" />
+    <view class="header" wx:if="{{state!='after'||!greetingCard.cardUrl}}">
+        <image src="{{configure.bgImg}}" class="templateImg" />
+        <view class="toBox"
+            style="top:{{configure.templateBase.fromTop}}rpx;left: {{configure.templateBase.fromLeft}}rpx;">
+            <input value="{{configure.fromText}}" disabled="{{state=='process'}}" class="text" maxlength='8'
+                style="color:{{configure.fromColor}};font-size: {{configure.fromFontSize}}rpx;border-color: {{configure.fromColor}}60;width: {{fromWidth}}rpx;"
+                bindinput="bindKeyInput" data-type='from' />
+            <image src="/static/image/edit_new.png" wx:if="{{state!='process'}}" />
+        </view>
+        <view class="toBox" style="top:{{configure.templateBase.toTop}}rpx;left: {{configure.templateBase.toLeft}}rpx;">
+            <input value="{{configure.toText}}" disabled="{{state=='process'}}" class="text" maxlength='8'
+                style="color:{{configure.toColor}};font-size: {{configure.toFontSize}}rpx;border-color: {{configure.toColor}}60;width: {{toWidth}}rpx;"
+                bindinput="bindKeyInput" data-type='to' />
+            <image src="/static/image/edit_new.png" wx:if="{{state!='process'}}" />
+        </view>
+        <view class="avatar" bindtap="showActionSheet" wx:if="{{state!='process'}}"
+            style="top:{{configure.templateBase.photoTop}}rpx;left: {{configure.templateBase.photoLeft}}rpx;width: {{configure.templateBase.photoWidth}}rpx;height:{{configure.templateBase.photoHeight}}rpx">
+            <view class="tips" wx:if="{{!changeAvatarFlag}}">点击更换图片</view>
+        </view>
+        <image class="avatarImg"
+            style="top:{{configure.templateBase.photoTop}}rpx;left: {{configure.templateBase.photoLeft}}rpx;width: {{configure.templateBase.photoWidth}}rpx;height:{{configure.templateBase.photoHeight}}rpx"
+            src="{{avatar}}"></image>
     </view>
-    <view class="toBox" style="top:{{configure.templateBase.toTop}}rpx;left: {{configure.templateBase.toLeft}}rpx;">
-      <input value="{{configure.toText}}" disabled="{{state=='process'}}" class="text" maxlength='8'
-        style="color:{{configure.toColor}};font-size: {{configure.toFontSize}}rpx;border-color: {{configure.toColor}}60;width: {{toWidth}}rpx;"
-        bindinput="bindKeyInput" data-type='to' />
-      <image src="/static/image/edit_new.png" wx:if="{{state!='process'}}" />
+    <view class="header" wx:if="{{state=='after'&&greetingCard.cardUrl}}">
+        <image src="{{greetingCard.cardUrl}}" class="templateImg" />
+        <view class="progressBox">
+            <view class="after">{{playTime}}</view>
+            <progress percent="{{vProgress}}" class="progress" stroke-width="8" activeColor="#9FFB3E"
+                backgroundColor="#3333340" />
+            <view class="before">{{endTime}}</view>
+        </view>
     </view>
-    <button class="avatar resetBtn" open-type="chooseAvatar" bind:chooseavatar="changeAvatar"
-      wx:if="{{state!='process'}}"
-      style="top:{{configure.templateBase.photoTop}}rpx;left: {{configure.templateBase.photoLeft}}rpx;width: {{configure.templateBase.photoWidth}}rpx;height:{{configure.templateBase.photoHeight}}rpx">
-      <view class="tips" wx:if="{{!changeAvatarFlag}}">点击更换图片</view>
-    </button>
-    <image class="avatarImg"
-      style="top:{{configure.templateBase.photoTop}}rpx;left: {{configure.templateBase.photoLeft}}rpx;width: {{configure.templateBase.photoWidth}}rpx;height:{{configure.templateBase.photoHeight}}rpx"
-      src="{{avatar}}"></image>
-  </view>
-  <view class="header" wx:if="{{state=='after'&&greetingCard.cardUrl}}">
-    <image src="{{greetingCard.cardUrl}}" class="templateImg" />
-    <view class="progressBox">
-      <view class="after">{{playTime}}</view>
-      <progress percent="{{vProgress}}" class="progress" stroke-width="8" activeColor="#9FFB3E"
-        backgroundColor="#3333340" />
-      <view class="before">{{endTime}}</view>
+    <!-- 录制控制区域 -->
+    <view class="btnsBox" wx:if="{{state!='after'}}">
+        <image wx:if="{{state=='before'}}" src="http://reader-wx.ai160.com/images/reader/card/play_1.png" class="send"
+            bindtap="play" />
+        <view class="recordingBox" wx:if="{{state=='process'}}">
+            <image class="readingNow" src="/static/index/readingNow.gif" />
+            <image src="http://reader-wx.ai160.com/images/reader/card/play_3.png" class="send" bindtap="play" />
+        </view>
+        <view class="countDown" wx:if="{{state=='process'}}">
+            倒计时:<view class="countBox">{{tens}}</view>
+            <view class="countBox">{{bits}}</view>秒
+        </view>
     </view>
-  </view>
-  <!-- 录制控制区域 -->
-  <view class="btnsBox" wx:if="{{state!='after'}}">
-    <image wx:if="{{state=='before'}}" src="http://reader-wx.ai160.com/images/reader/card/play_1.png" class="send"
-      bindtap="play" />
-    <view class="recordingBox" wx:if="{{state=='process'}}">
-      <image class="readingNow" src="/static/index/readingNow.gif" />
-      <image src="http://reader-wx.ai160.com/images/reader/card/play_3.png" class="send" bindtap="play" />
+    <!-- 试听与分享控制区域 -->
+    <view class="music" wx:if="{{state=='after'}}">
+        <!-- <view class="music"> -->
+        <image
+            src="{{userAudioState?'http://reader-wx.ai160.com/images/reader/card/audition2.png':'http://reader-wx.ai160.com/images/reader/card/audition.png'}}"
+            class="playAuido" bindtap="playUserAudio" />
+        <button class="resetBtn share textOver" open-type="share">
+            发送给{{configure.toText}}
+        </button>
     </view>
-    <view class="countDown" wx:if="{{state=='process'}}">
-      倒计时:<view class="countBox">{{tens}}</view>
-      <view class="countBox">{{bits}}</view>秒
+    <!-- 祝福语 -->
+    <view class="blessing">
+        <view wx:for="{{greeting}}" wx:key="index" class="content">{{item}}</view>
     </view>
-  </view>
-  <!-- 试听与分享控制区域 -->
-  <view class="music" wx:if="{{state=='after'}}">
-    <!-- <view class="music"> -->
-    <image
-      src="{{userAudioState?'http://reader-wx.ai160.com/images/reader/card/audition2.png':'http://reader-wx.ai160.com/images/reader/card/audition.png'}}"
-      class="playAuido" bindtap="playUserAudio" />
-    <button class="resetBtn share textOver" open-type="share">
-      发送给{{configure.toText}}
-    </button>
-  </view>
-  <!-- 祝福语 -->
-  <view class="blessing">
-    <view wx:for="{{greeting}}" wx:key="index" class="content">{{item}}</view>
-  </view>
-  <!-- 上传进度 -->
-  <view class="mask" wx:if="{{uploadState}}">
-    <view class="maskBox" catchtap="true">
-      <image src="/static/index/zqq.png" class="img" />
-      <view>祝福生成中</view>
+    <!-- 上传进度 -->
+    <view class="mask" wx:if="{{uploadState}}">
+        <view class="maskBox" catchtap="true">
+            <image src="/static/index/zqq.png" class="img" />
+            <view>祝福生成中</view>
+        </view>
     </view>
-  </view>
 </view>
+<yeyouzi-cropper id="yeyouzi-cropper" style="width: 100%;height: 100%;"></yeyouzi-cropper>
 <canvas id='share' type="2d"> </canvas>