VerifyPoints.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <template>
  2. <div style="position: relative">
  3. <div class="verify-img-out">
  4. <div
  5. class="verify-img-panel"
  6. :style="{
  7. width: setSize.imgWidth,
  8. height: setSize.imgHeight,
  9. 'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
  10. 'margin-bottom': vSpace + 'px',
  11. }"
  12. >
  13. <div
  14. v-show="showRefresh"
  15. class="verify-refresh"
  16. style="z-index: 3"
  17. @click="refresh"
  18. >
  19. <i class="iconfont icon-refresh" />
  20. </div>
  21. <img
  22. ref="canvas"
  23. :src="
  24. pointBackImgBase
  25. ? 'data:image/png;base64,' + pointBackImgBase
  26. : defaultImg
  27. "
  28. alt=""
  29. style="width: 100%; height: 100%; display: block"
  30. @click="bindingClick ? canvasClick($event) : undefined"
  31. />
  32. <div
  33. v-for="(tempPoint, index) in tempPoints"
  34. :key="index"
  35. class="point-area"
  36. :style="{
  37. 'background-color': '#1abd6c',
  38. color: '#fff',
  39. 'z-index': 9999,
  40. width: '20px',
  41. height: '20px',
  42. 'text-align': 'center',
  43. 'line-height': '20px',
  44. 'border-radius': '50%',
  45. position: 'absolute',
  46. top: parseInt(tempPoint.y - 10) + 'px',
  47. left: parseInt(tempPoint.x - 10) + 'px',
  48. }"
  49. >
  50. {{ index + 1 }}
  51. </div>
  52. </div>
  53. </div>
  54. <!-- 'height': this.barSize.height, -->
  55. <div
  56. class="verify-bar-area"
  57. :style="{
  58. width: setSize.imgWidth,
  59. color: this.barAreaColor,
  60. 'border-color': this.barAreaBorderColor,
  61. 'line-height': this.barSize.height,
  62. }"
  63. >
  64. <span class="verify-msg">{{ text }}</span>
  65. </div>
  66. </div>
  67. </template>
  68. <script type="text/babel">
  69. /**
  70. * VerifyPoints
  71. * @description 点选
  72. * */
  73. import {
  74. resetSize,
  75. _code_chars,
  76. _code_color1,
  77. _code_color2,
  78. } from './../utils/util';
  79. import { aesEncrypt } from './../utils/ase';
  80. export default {
  81. name: 'VerifyPoints',
  82. props: {
  83. // 弹出式pop,固定fixed
  84. mode: {
  85. type: String,
  86. default: 'fixed',
  87. },
  88. captchaType: {
  89. type: String,
  90. },
  91. // 间隔
  92. vSpace: {
  93. type: Number,
  94. default: 5,
  95. },
  96. imgSize: {
  97. type: Object,
  98. default() {
  99. return {
  100. width: '310px',
  101. height: '155px',
  102. };
  103. },
  104. },
  105. barSize: {
  106. type: Object,
  107. default() {
  108. return {
  109. width: '310px',
  110. height: '40px',
  111. };
  112. },
  113. },
  114. defaultImg: {
  115. type: String,
  116. default: '',
  117. },
  118. },
  119. data() {
  120. return {
  121. secretKey: '', // 后端返回的ase加密秘钥
  122. checkNum: 3, // 默认需要点击的字数
  123. fontPos: [], // 选中的坐标信息
  124. checkPosArr: [], // 用户点击的坐标
  125. num: 1, // 点击的记数
  126. pointBackImgBase: '', // 后端获取到的背景图片
  127. poinTextList: [], // 后端返回的点击字体顺序
  128. backToken: '', // 后端返回的token值
  129. setSize: {
  130. imgHeight: 0,
  131. imgWidth: 0,
  132. barHeight: 0,
  133. barWidth: 0,
  134. },
  135. tempPoints: [],
  136. text: '',
  137. barAreaColor: undefined,
  138. barAreaBorderColor: undefined,
  139. showRefresh: true,
  140. bindingClick: true,
  141. };
  142. },
  143. computed: {
  144. resetSize() {
  145. return resetSize;
  146. },
  147. },
  148. watch: {
  149. // type变化则全面刷新
  150. type: {
  151. immediate: true,
  152. handler() {
  153. this.init();
  154. },
  155. },
  156. },
  157. mounted() {
  158. // 禁止拖拽
  159. this.$el.onselectstart = function () {
  160. return false;
  161. };
  162. },
  163. methods: {
  164. init() {
  165. // 加载页面
  166. this.fontPos.splice(0, this.fontPos.length);
  167. this.checkPosArr.splice(0, this.checkPosArr.length);
  168. this.num = 1;
  169. this.getPictrue();
  170. this.$nextTick(() => {
  171. this.setSize = this.resetSize(this); // 重新设置宽度高度
  172. this.$parent.$emit('ready', this);
  173. });
  174. },
  175. canvasClick(e) {
  176. this.checkPosArr.push(this.getMousePos(this.$refs.canvas, e));
  177. if (this.num == this.checkNum) {
  178. this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e));
  179. // 按比例转换坐标值
  180. this.checkPosArr = this.pointTransfrom(this.checkPosArr, this.setSize);
  181. // 等创建坐标执行完
  182. setTimeout(() => {
  183. // var flag = this.comparePos(this.fontPos, this.checkPosArr);
  184. // 发送后端请求
  185. var captchaVerification = this.secretKey
  186. ? aesEncrypt(
  187. this.backToken + '---' + JSON.stringify(this.checkPosArr),
  188. this.secretKey,
  189. )
  190. : this.backToken + '---' + JSON.stringify(this.checkPosArr);
  191. const data = {
  192. captchaType: this.captchaType,
  193. pointJson: this.secretKey
  194. ? aesEncrypt(JSON.stringify(this.checkPosArr), this.secretKey)
  195. : JSON.stringify(this.checkPosArr),
  196. token: this.backToken,
  197. };
  198. this.$axios.$post('activity/captcha/check', data).then((res) => {
  199. if (res.repCode == '0000') {
  200. this.barAreaColor = '#4cae4c';
  201. this.barAreaBorderColor = '#5cb85c';
  202. this.text = '验证成功';
  203. this.bindingClick = false;
  204. if (this.mode == 'pop') {
  205. setTimeout(() => {
  206. this.$parent.clickShow = false;
  207. this.refresh();
  208. }, 1500);
  209. }
  210. this.$parent.$emit('success', { captchaVerification });
  211. } else {
  212. this.$parent.$emit('error', this);
  213. this.barAreaColor = '#d9534f';
  214. this.barAreaBorderColor = '#d9534f';
  215. this.text = '验证失败';
  216. setTimeout(() => {
  217. this.refresh();
  218. }, 700);
  219. }
  220. });
  221. }, 400);
  222. }
  223. if (this.num < this.checkNum) {
  224. this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e));
  225. }
  226. },
  227. // 获取坐标
  228. getMousePos: function (obj, e) {
  229. var x = e.offsetX;
  230. var y = e.offsetY;
  231. return { x, y };
  232. },
  233. // 创建坐标点
  234. createPoint: function (pos) {
  235. this.tempPoints.push(Object.assign({}, pos));
  236. return ++this.num;
  237. },
  238. refresh: function () {
  239. this.tempPoints.splice(0, this.tempPoints.length);
  240. this.barAreaColor = '#000';
  241. this.barAreaBorderColor = '#ddd';
  242. this.bindingClick = true;
  243. this.fontPos.splice(0, this.fontPos.length);
  244. this.checkPosArr.splice(0, this.checkPosArr.length);
  245. this.num = 1;
  246. this.getPictrue();
  247. this.text = '验证失败';
  248. this.showRefresh = true;
  249. },
  250. // 请求背景图片和验证图片
  251. getPictrue() {
  252. const data = {
  253. captchaType: this.captchaType,
  254. clientUid: localStorage.getItem('point'),
  255. ts: Date.now(), // 现在的时间戳
  256. };
  257. this.$axios.$post('/captcha/get', data).then((res) => {
  258. console.log(res);
  259. if (res.repCode == '0000') {
  260. console.log(123456);
  261. this.pointBackImgBase = res.repData.originalImageBase64;
  262. this.backToken = res.repData.token;
  263. this.secretKey = res.repData.secretKey;
  264. this.poinTextList = res.repData.wordList;
  265. this.text = '请依次点击【' + this.poinTextList.join(',') + '】';
  266. } else {
  267. this.text = res.repMsg;
  268. }
  269. // 判断接口请求次数是否失效
  270. if (res.repCode == '6201') {
  271. this.pointBackImgBase = null;
  272. }
  273. });
  274. },
  275. // 坐标转换函数
  276. pointTransfrom(pointArr, imgSize) {
  277. var newPointArr = pointArr.map((p) => {
  278. const x = Math.round((310 * p.x) / parseInt(imgSize.imgWidth));
  279. const y = Math.round((155 * p.y) / parseInt(imgSize.imgHeight));
  280. return { x, y };
  281. });
  282. // console.log(newPointArr,"newPointArr");
  283. return newPointArr;
  284. },
  285. },
  286. };
  287. </script>