canvas验证码 uni-app/小程序

1 <template>
2 <view class="logo-wrapper">
3 <view class="logo-img">
4 <image src="../../static/images/logo-login.png" mode="widthFix" />
5 </view>
6 <view class="form-box">
7 <view class="form-item">
8 <view class="icon-box">
9 <i class="iconfont icon-yonghu"></i>
10 </view>
11 <input class="ipt" v-model="username" type="text" placeholder="用户名" />
12 </view>
13 <view class="form-item">
14 <view class="icon-box">
15 <i class="iconfont icon-mima"></i>
16 </view>
17 <input class="ipt" v-model="password" type="password" placeholder="密码" />
18 </view>
19 <view class="form-item">
20 <view class="icon-box">
21 <i class="iconfont icon-yanzhengma"></i>
22 </view>
23 <input class="ipt short" v-model="capCode" type="text" placeholder="验证码" />
24 <canvas class="canvas" canvas-id="yzmCanvas" id="yzmCanvas" @tap="tapCaptcha"></canvas>
25 </view>
26 <button class="btn-login" @tap="login">登录</button>
27 </view>
28 <view class="bottom-img">
29 <image src="../../static/images/login-bottom.png" mode="widthFix" />
30 </view>
31 </view>
32 </template>
33
34 <script>
35 export default {
36 data() {
37 return {
38 capShow: true,
39 username: '',
40 password: '',
41 capCode: '',
42 uuid: ''
43 }
44 },
45 methods: {
46 async queryCaptcha() {
47 const { data } = await this.$http({
48 url: '/captchaImage',
49 method: 'GET',
50 });
51 this.uuid = data.data.uuid;
52 this.creatCanvas(data.data.image);
53 },
54 tapCaptcha() {
55 this.capShow = false;
56 this.$nextTick(() => {
57 this.capShow = true;
58 this.queryCaptcha();
59 });
60 },
61 //得到随机的颜色值
62 randomColor() {
63 var r = Math.floor(Math.random() * 256);
64 var g = Math.floor(Math.random() * 256);
65 var b = Math.floor(Math.random() * 256);
66 return 'rgb(' + r + ',' + g + ',' + b + ')';
67 },
68 creatCanvas(str) {
69 const ctx = uni.createCanvasContext('yzmCanvas');
70 ctx.setFontSize(28 + Math.floor(Math.random() * 4 - 2));
71 ctx.setFillStyle(this.randomColor());
72 for (let i = 0; i < 4; i++) {
73 ctx.setFontSize(28 + Math.floor(Math.random() * 4 - 2));
74 ctx.fillText(str[i], 20 * i + 10, 32);
75 ctx.setFillStyle(this.randomColor());
76 // 旋转随机在-3到3之间
77 ctx.rotate((Math.floor(Math.random() * 6 - 3) * Math.PI) / 180);
78 }
79 // 直线 begin path
80 for (let i = 0; i < 4; i++) {
81 ctx.beginPath();
82 ctx.setStrokeStyle(this.randomColor());
83 // x/-10~110 y/-10~50
84 ctx.moveTo(
85 Math.floor(Math.random() * 100) + Math.floor(Math.random() * 20 - 10),
86 Math.floor(Math.random() * 40) + Math.floor(Math.random() * 20 - 10)
87 );
88 ctx.lineTo(
89 Math.floor(Math.random() * 100) + Math.floor(Math.random() * 20 - 10),
90 Math.floor(Math.random() * 40) + Math.floor(Math.random() * 20 - 10)
91 );
92 ctx.stroke();
93 }
94 ctx.draw();
95 },
96 async login() {
97 if(this.username === '') {
98 uni.showToast({
99 icon: 'none',
100 title: '请填写用户名'
101 });
102 return;
103 }
104 if(this.password === '') {
105 uni.showToast({
106 icon: 'none',
107 title: '请填写密码'
108 });
109 return;
110 }
111 if(this.capCode === '') {
112 uni.showToast({
113 icon: 'none',
114 title: '请填写验证码'
115 });
116 return;
117 }
118 const { data } = await this.$http({
119 url: '/login',
120 method: 'POST',
121 data: {
122 username: this.username,
123 password: this.password,
124 code: this.capCode,
125 uuid: this.uuid
126 }
127 });
128 uni.setStorageSync('token', data.data.token);
129
130 const res = await this.$http({
131 url: '/personal/userInfo',
132 method: 'GET',
133 data: {
134 token: data.data.token,
135 }
136 });
137 let userInfo = res.data.data;
138 uni.setStorageSync('userInfo', userInfo);
139
140 uni.switchTab({
141 url: '/pages/index/index'
142 });
143 }
144 },
145 onLoad() {
146 this.queryCaptcha();
147 },
148 }
149 </script>
150
151 <style lang="scss">
152 .logo-wrapper {
153 display: flex;
154 flex-direction: column;
155 align-items: center;
156 justify-content: space-between;
157 }
158 .logo-img {
159 width: 590upx;
160 height: 246upx;
161 margin-top: 60upx;
162 }
163 .form-box {
164 width: 560upx;
165 height: 580upx;
166 margin: 30upx 0 140upx 0;
167 }
168 .form-item {
169 width: 100%;
170 height: 82upx;
171 margin-top: 48upx;
172 border-bottom: 1px solid #c1c1c1;
173 display: flex;
174 align-items: center;
175 }
176 .icon-box {
177 width: 50upx;
178 height: 50upx;
179 border-radius: 50%;
180 margin-right: 40upx;
181 text-align: center;
182 line-height: 42upx;
183 background-color: #f0443c;
184 color: #fff;
185 i {
186 font-size: 24upx;
187 }
188 }
189 .ipt {
190 flex: 1;
191 height: 80upx;
192 }
193 .canvas {
194 width: 190upx;
195 height: 68upx;
196 border: 1px solid #f1f1f1;
197 background: #fdfdfd;
198 }
199 .btn-login {
200 margin-top: 84upx;
201 background-color: #f0443c;
202 color: #fff;
203 }
204 .bottom-img {
205 width: 628upx;
206 height: 124upx;
207 // margin: 50upx auto 0;
208 }
209 </style>
canvas验证码 uni-app/小程序的更多相关文章
- uni与小程序,vue的区别
标签区别 uni使用小程序的标签,vue使用web端的标签 标签名变化的: 标签描述\类别 vue uniapp 文本 span\font text 链接 a navigator/ router-li ...
- Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解
Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解 说明:Java生鲜电商平台-APP/小程序接口传输常见的加密算法及详解,加密算法,是现在每个软件项目里必须用到的内容. 广泛应用在包括 ...
- Java生鲜电商平台-电商中"再来一单"功能架构与详细设计(APP/小程序)
Java生鲜电商平台-电商中"再来一单"功能架构与详细设计(APP/小程序) 说明:在实际的业务场景中(无论是TO B还是TO C)不管是休闲食品.餐饮.水果.日用百货.母婴等高频 ...
- Spring Security 一键接入验证码登录和小程序登录
最近实现了一个多端登录的Spring Security组件,用起来非常丝滑,开箱即用,可插拔,而且灵活性非常强.我觉得能满足大部分场景的需要.目前完成了手机号验证码和微信小程序两种自定义登录,加上默认 ...
- 2018最新版 手机号、验证码正则表达式 jq + 小程序
HTML: <!-- 表单 --> <input class="weui-input" id="tel" type="tel&quo ...
- 小程序学习三 一切的开始app() 小程序的注册
现在打开 app.js //app.js App({ onLaunch(options) { //小程序初始化 // console.log("小程序初始化", options) ...
- 小迪安全 Web安全 基础入门 - 第十天 - 信息打点-APP&小程序篇&抓包封包&XP框架&反编译&资产提取
一.本节知识点思维导图 二.APP-外在资产收集 1.将APP安装在模拟器中,修改模拟器代理设置,使用Fiddler.Burpsuite.Charles等抓包工具抓取APP访问的http协议数据包,抓 ...
- 小迪安全 Web安全 基础入门 - 第三天 - 抓包&封包&协议&APP&小程序&PC应用&WEB应用
一.抓包工具 1.Fiddler.Fiddler是一个用于HTTP调试的代理服务器应用程序,能捕获HTTP和HTTPS流量,并将其记录下来供用户查看.它通过使用自签名证书实现中间人攻击来进行日志记录. ...
- uni微信小程序优化,几行代码就能省100kb的主包空间?
不是标题党,我们公司的项目确确实实是省下了100kb的主包空间,而且还是在没有牺牲任何的性能和业务的前提下实现的. 但是100kb是根据项目大小,所以你用这个插件可能省下超过100kb或者更少. 直接 ...
- uni微信小程序优化,打包后的import vue路径是可删除的
这次的优化我公司项目主包只减小了32kb,但是减小的不仅仅是主包,所有分包均在没有改动任何业务代码的情况下完成了压缩空间的优化. 主包分包压缩空间的优化都要视项目而定,32kb只是我公司的小程序项目. ...
随机推荐
- [ABC317G] Rearranging
Problem Statement There is a grid with $N$ rows and $M$ columns. The square at the $i$-th row from t ...
- [GDOIpj221B] 数列游戏
第二题 数列游戏 提交文件: sequence.cpp 输入文件: sequence.in 输出文件: sequence.out 时间空间限制: 1 秒, 256 MB 有一个长度为 \(n\) 的序 ...
- 文心一言 VS 讯飞星火 VS chatgpt (163)-- 算法导论13.1 3题
三.用go语言,定义一棵松弛红黑树(relaxed red-black tree)为满足红黑性质 1.3.4 和5的二叉搜索树.换句话说,根结点可以是红色或是黑色.考虑一棵根结点为红色的松弛红黑树 T ...
- Javascript Ajax总结——HTTP头部信息
每个HTTP请求和响应都会带有相应的头部信息,其中有的对开发人员有用,有的没用.XHR对象也提供了操作这两种头部(即请求头部和响应头部)信息的方法.默认情况下,在发送XHR请求的同时,还会发送下列头部 ...
- ElasticSearch之Index modules
索引的参数,分为两类: 静态参数,仅支持在创建索引时指定,或者关闭索引后指定. 动态参数,允许在索引工作期间指定或者修改. 静态参数 index.number_of_shards 默认值为1. 本参数 ...
- GO的逃逸分析
逃逸分析 前言 指的就是由编译器决定内存分配的位置,不需要由程序员来指定.函数中申请一个新的对象,其目的是为了提高程序的性能,减少内存分配和垃圾回收的开销. 分配在 栈 中, 则函数执行结束则可自动将 ...
- 云MSP服务案例|互联网商城的上云改造之旅
简介: 在中国,经过十年的发展,云计算产业已走过概念普及的1.0时期,进入"上云"和落地的2. 0阶段,企业上云意识不断增强,越来越多的企业选择部署多云和混合IT. 如今,云计算生 ...
- 2023年资深C#开发者的思考
2023年转眼间就这样过掉了,作为一名资深C#的开发员人员,年龄也大了1岁,从最早接触C#开始,算下来已经超过15年以上了,随着工作经验的不断增加,物价不断的飞涨以及家庭支出的不断上涨,工作1份工资已 ...
- android ProgressBar样式
实现进度条由浅黄(#ffff33)到深黄色(#ff6600)的渐变样式. 与进度条自动从0加载到99,进度条每次加1 android:max:进度条的最大值. android:progressDraw ...
- 文心一言 VS 讯飞星火 VS chatgpt (56)-- 算法导论6.3 2题
文心一言 VS 讯飞星火 VS chatgpt (56)-- 算法导论6.3 2题 对于 BUILD-MAX-HEAP 中第 2行的循环控制变量 i 来说,为什么我们要求它是从A.length/2到1 ...