Browse Source

用于边民订单确认和首次使用app的人脸认证

李书文 1 year ago
parent
commit
d46c0d3701
2 changed files with 349 additions and 9 deletions
  1. 318 0
      components/cmd-circle/cmd-circle.vue
  2. 31 9
      pages/authentication/face.vue

+ 318 - 0
components/cmd-circle/cmd-circle.vue

@@ -0,0 +1,318 @@
+<template>
+  <view class="cmd-circle">
+    <canvas :canvas-id="cid" :style="calCircleStyle"></canvas>
+  </view>
+</template>
+
+<script>
+  /**
+   * 进度圈组件  
+   * @description 用圈显示一个操作完成的百分比时,为用户显示该操作的当前进度和状态。  
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=259  
+   * @property {String} cid 画布编号 - 默认defaultCanvas  
+   * @property {String} type 进度圈类型 - 圆圈形:circle、仪表盘:dashboard,默认圆圈形:circle  
+   * @property {Number} percent 进度圈百分比值 - 显示范围0-100 ,可能数比较大就需要自己转成百分比的值  
+   * @property {Boolean} show-info 进度圈进度状态信息 - 显示进度数值或状态图标,默认true  
+   * @property {String} font-color 进度圈文字信息颜色  
+   * @property {String} font-size 进度圈文字信息大小 - 默认:14  
+   * @property {String} status 进度圈状态 - 正常:normal、完成:success、失败:exception,默认正常:normal  
+   * @property {Number} stroke-width 进度圈线条宽度 - 建议在条线的宽度范围:1-50,与进度条显示宽度有关,默认:6  
+   * @property {String} stroke-color 进度圈的颜色 - 设置后status状态无效  
+   * @property {String} stroke-background 进度圈的底圈颜色 - 默认:#eeeeee  
+   * @property {String} stroke-shape 进度圈两端的形状 - 圆:round、方直角:square,默认圆:round  
+   * @property {Number} width 进度圈布宽度 - 默认80  
+   * @property {String} gap-degree 进度圈形缺口角度 - 可取值 0 ~ 360,仅支持类型:circle  
+   * @property {String} gap-position 进度圈形缺口位置 - 可取值'top', 'bottom', 'left', 'right',仅支持类型:circle  
+   * @example <cmd-circle id="circle1" type="circle" :percent="75"></cmd-circle>  
+   */
+  export default {
+    name: "cmd-circle",
+
+    props: {
+      // 画布编号 默认defaultCanvas
+      cid: {
+        type: String,
+        default: "defaultCanvas"
+      },
+      // 圈类型默认:circle,可选 circle dashboard
+      type: {
+        type: String,
+        validator: val => {
+          return ['circle', 'dashboard'].includes(val);
+        },
+        default: 'circle'
+      },
+      // 圈进度百分比值
+      percent: {
+        type: Number,
+        validator: val => {
+          return val >= 0 && val <= 100;
+        },
+        default: 0
+      },
+      // 圈是否显示进度数值或状态图标
+      showInfo: {
+        type: Boolean,
+        default: true
+      },
+      // 圈文字信息颜色
+      fontColor: {
+        type: String,
+        default: "#595959"
+      },
+      // 圈文字信息大小 默认14
+      fontSize: {
+        type: Number,
+        default: 14
+      },
+      // 圈进度状态,可选:normal success exception
+      status: {
+        type: String,
+        validator: val => {
+          return ['normal', 'success', 'exception'].includes(val);
+        },
+        default: 'normal'
+      },
+      // 圈线条宽度1-50,与width有关
+      strokeWidth: {
+        type: Number,
+        default: 6
+      },
+      // 圈的颜色,设置后status状态无效
+      strokeColor: {
+        type: String,
+        default: ''
+      },
+      // 圈的底圈颜色 默认:#eeeeee
+      strokeBackground: {
+        type: String,
+        default: '#eeeeee'
+      },
+      // 圈两端的形状 可选:'round', 'square'
+      strokeShape: {
+        type: String,
+        validator: val => {
+          return ['round', 'square'].includes(val);
+        },
+        default: 'round'
+      },
+      // 圈画布宽度
+      width: {
+        type: Number,
+        default: 80
+      },
+      // 圈缺口角度,可取值 0 ~ 360,仅支持类型:circle  
+      gapDegree: {
+        type: Number,
+        validator: val => {
+          return val >= 0 && val <= 360;
+        },
+        default: 360
+      },
+      // 圈缺口开始位置,可取值'top', 'bottom', 'left', 'right',仅支持类型:circle  
+      gapPosition: {
+        type: String,
+        validator: val => {
+          return ['top', 'bottom', 'left', 'right'].includes(val);
+        },
+        default: 'top'
+      }
+    },
+
+    data() {
+      return {
+        // 画布实例
+        ctx: {},
+        // 圈半径
+        width2px: ""
+      }
+    },
+
+    computed: {
+      // 计算设置圈样式
+      calCircleStyle() {
+        return `width: ${this.width}px;
+				height: ${this.width}px;`
+      },
+      // 计算圈状态
+      calStatus() {
+        let status = {}
+        switch (this.status) {
+          case 'normal':
+            status = {
+              color: "#1890ff",
+              value: 1
+            };
+            break;
+          case 'success':
+            status = {
+              color: "#52c41a",
+              value: 2
+            };
+            break;
+          case 'exception':
+            status = {
+              color: "#f5222d",
+              value: 3
+            };
+            break;
+        }
+        return status
+      },
+      // 计算圈缺口角度
+      calGapDegree() {
+        return this.gapDegree <= 0 ? 360 : this.gapDegree
+      },
+      // 计算圈缺口位置
+      calGapPosition() {
+        let gapPosition = 0
+        switch (this.gapPosition) {
+          case 'bottom':
+            gapPosition = 90;
+            break;
+          case 'left':
+            gapPosition = 180;
+            break;
+          case 'top':
+            gapPosition = 270;
+            break;
+          case 'right':
+            gapPosition = 360;
+            break;
+        }
+        return gapPosition
+      },
+    },
+
+    watch: {
+      // 监听百分比值改变
+      percent(val) {
+        this.drawStroke(val);
+      }
+    },
+
+    mounted() {
+      // 创建画布实例
+      this.ctx = uni.createCanvasContext(this.cid, this)
+      // upx转px 圈半径大小
+      this.width2px = uni.upx2px(this.width)
+      // 绘制初始 
+      this.$nextTick(() => {
+        this.drawStroke(this.percent)
+      })
+    },
+
+    methods: {
+      // 绘制圈
+      drawStroke(percent) {
+        percent = percent >= 100 ? 100 : percent < 0 ? 0 : percent
+        // 圈条进度色
+        let color = this.strokeColor || this.calStatus.color
+        // 是否圈中心显示信息
+        if (this.showInfo) {
+          switch (this.calStatus.value) {
+            case 1:
+              if (percent >= 100) {
+                // 设置打勾
+                this.drawSuccess()
+                percent = 100
+                color = "#52c41a"
+              } else {
+                // 设置字体
+                this.drawText(percent)
+              }
+              break;
+            case 2:
+              // 设置打勾
+              this.drawSuccess()
+              percent = 100
+              color = "#52c41a"
+              break;
+            case 3:
+              // 设置打叉
+              this.drawException()
+              percent = 0
+              color = "#f5222d"
+              break;
+            default:
+              break;
+          }
+        }
+        // 缺口
+        let gapPosition = this.calGapPosition
+        let gapDegree = this.calGapDegree
+        // 仪表固定
+        if (this.type === "dashboard") {
+          gapPosition = 135
+          gapDegree = 270
+        }
+        // 圈型条宽
+        this.ctx.setLineCap(this.strokeShape)
+        this.ctx.setLineWidth(this.strokeWidth)
+        // 位置原点
+        this.ctx.translate(this.width2px, this.width2px)
+        // 缺口方向 
+        this.ctx.rotate(gapPosition * Math.PI / 180)
+        // 圈底 
+        this.ctx.beginPath()
+        this.ctx.arc(0, 0, this.width2px - this.strokeWidth, 0, gapDegree * Math.PI / 180)
+        this.ctx.setStrokeStyle(this.strokeBackground)
+        this.ctx.stroke()
+        // 圈进度 
+        this.ctx.beginPath()
+        this.ctx.arc(0, 0, this.width2px - this.strokeWidth, 0, percent * gapDegree * Math.PI / 18000)
+        this.ctx.setStrokeStyle(color)
+        this.ctx.stroke()
+        // 绘制
+        this.ctx.draw()
+      },
+      // 绘制文字格式
+      drawText(percent) {
+        this.ctx.beginPath()
+        this.ctx.setFontSize(this.fontSize)
+        this.ctx.setFillStyle(this.fontColor)
+        this.ctx.setTextAlign('center')
+        this.ctx.fillText(`${percent}%`, this.width2px, this.width2px + this.fontSize / 2)
+        this.ctx.stroke()
+      },
+      // 绘制成功打勾
+      drawSuccess() {
+        let x = this.width2px - this.fontSize / 2
+        let y = this.width2px + this.fontSize / 2
+        this.ctx.beginPath()
+        this.ctx.setLineCap('round')
+        this.ctx.setLineWidth(this.fontSize / 4)
+        this.ctx.moveTo(this.width2px, y)
+        this.ctx.lineTo(y, x)
+        this.ctx.moveTo(this.width2px, y)
+        this.ctx.lineTo(x, this.width2px)
+        this.ctx.setStrokeStyle("#52c41a")
+        this.ctx.stroke()
+      },
+      // 绘制异常打叉
+      drawException() {
+        let x = this.width2px - this.fontSize / 2
+        let y = this.width2px + this.fontSize / 2
+        this.ctx.beginPath()
+        this.ctx.setLineCap('round')
+        this.ctx.setLineWidth(this.fontSize / 4)
+        this.ctx.moveTo(x, x)
+        this.ctx.lineTo(y, y)
+        this.ctx.moveTo(y, x)
+        this.ctx.lineTo(x, y)
+        this.ctx.setStrokeStyle("#f5222d")
+        this.ctx.stroke()
+      }
+    }
+  };
+</script>
+
+<style>
+  .cmd-circle {
+    display: inline-block;
+    box-sizing: border-box;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+  }
+</style>

+ 31 - 9
pages/authentication/face.vue

@@ -1,19 +1,41 @@
 <template>
-	<view>
-		
+	<view class="cmain">
+		<view class="face">
+			<cmd-circle stroke-color="#4581fb" :strokeWidth="13" type="circle" :percent="parseInt(progress.toFixed(0))" :width="200"></cmd-circle>
+			<view class="desc">请误遮挡眼睛</view>
+		</view>
 	</view>
 </template>
 
 <script>
-	export default {
-		data() {
-			return {
-				
-			};
-		}
+export default {
+	data() {
+		return {
+			progress: 0
+		};
+	},
+	onLoad() {
+		let increment = 100 / 3; // 每秒递增的进度值
+		let countdown = setInterval(() => {
+			this.progress += increment;
+			if (this.progress >= 100) {
+				this.progress = 100;
+				clearInterval(countdown); // 达到100后清除定时器
+				uni.$emit('face');
+				uni.navigateBack();
+			}
+		}, 1000);
 	}
+};
 </script>
 
 <style lang="scss">
-
+.face {
+	text-align: center;
+	padding-top: 30px;
+	.desc {
+		margin-top: 15px;
+		color: #969696;
+	}
+}
 </style>