123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- <template>
- <div style="position: relative">
- <div
- v-if="type === '2'"
- class="verify-img-out"
- :style="{ height: parseInt(setSize.imgHeight) + vSpace + 'px' }"
- >
- <div
- class="verify-img-panel"
- :style="{ width: setSize.imgWidth, height: setSize.imgHeight }"
- >
- <img
- :src="
- backImgBase ? 'data:image/png;base64,' + backImgBase : defaultImg
- "
- alt=""
- style="width: 100%; height: 100%; display: block"
- />
- <div v-show="showRefresh" class="verify-refresh" @click="refresh">
- <i class="iconfont icon-refresh" />
- </div>
- <transition name="tips">
- <span
- v-if="tipWords"
- class="verify-tips"
- :class="passFlag ? 'suc-bg' : 'err-bg'"
- >{{ tipWords }}</span
- >
- </transition>
- </div>
- </div>
- <!-- 公共部分 -->
- <div
- class="verify-bar-area"
- :style="{
- width: setSize.imgWidth,
- height: barSize.height,
- 'line-height': barSize.height,
- }"
- >
- <span class="verify-msg" v-text="text" />
- <div
- class="verify-left-bar"
- :style="{
- width: leftBarWidth !== undefined ? leftBarWidth : barSize.height,
- height: barSize.height,
- 'border-color': leftBarBorderColor,
- transaction: transitionWidth,
- }"
- >
- <span class="verify-msg" v-text="finishText" />
- <div
- class="verify-move-block"
- :style="{
- width: barSize.height,
- height: barSize.height,
- 'background-color': moveBlockBackgroundColor,
- left: moveBlockLeft,
- transition: transitionLeft,
- }"
- @touchstart="start"
- @mousedown="start"
- >
- <i
- :class="['verify-icon iconfont', iconClass]"
- :style="{ color: iconColor }"
- />
- <div
- v-if="type === '2'"
- class="verify-sub-block"
- :style="{
- width: Math.floor((parseInt(setSize.imgWidth) * 47) / 310) + 'px',
- height: setSize.imgHeight,
- top: '-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
- 'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
- }"
- >
- <img
- :src="'data:image/png;base64,' + blockBackImgBase"
- alt=""
- style="width: 100%; height: 100%; display: block"
- />
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script type="text/babel">
- /**
- * VerifySlide
- * @description 滑块
- * */
- import { aesEncrypt } from './../utils/ase';
- import { resetSize } from './../utils/util';
- // "captchaType":"blockPuzzle",
- export default {
- name: 'VerifySlide',
- props: {
- captchaType: {
- type: String,
- },
- type: {
- type: String,
- default: '1',
- },
- // 弹出式pop,固定fixed
- mode: {
- type: String,
- default: 'fixed',
- },
- vSpace: {
- type: Number,
- default: 5,
- },
- explain: {
- type: String,
- default: '向右滑动完成验证',
- },
- imgSize: {
- type: Object,
- default() {
- return {
- width: '310px',
- height: '155px',
- };
- },
- },
- blockSize: {
- type: Object,
- default() {
- return {
- width: '50px',
- height: '50px',
- };
- },
- },
- barSize: {
- type: Object,
- default() {
- return {
- width: '310px',
- height: '50px',
- };
- },
- },
- defaultImg: {
- type: String,
- default: '',
- },
- },
- data() {
- return {
- secretKey: '', // 后端返回的加密秘钥 字段
- passFlag: '', // 是否通过的标识
- backImgBase: '', // 验证码背景图片
- blockBackImgBase: '', // 验证滑块的背景图片
- backToken: '', // 后端返回的唯一token值
- startMoveTime: '', // 移动开始的时间
- endMovetime: '', // 移动结束的时间
- tipsBackColor: '', // 提示词的背景颜色
- tipWords: '',
- text: '',
- finishText: '',
- setSize: {
- imgHeight: 0,
- imgWidth: 0,
- barHeight: 0,
- barWidth: 0,
- },
- top: 0,
- left: 0,
- moveBlockLeft: undefined,
- leftBarWidth: undefined,
- // 移动中样式
- moveBlockBackgroundColor: undefined,
- leftBarBorderColor: '#ddd',
- iconColor: undefined,
- iconClass: 'icon-right',
- status: false, // 鼠标状态
- isEnd: false, // 是够验证完成
- showRefresh: true,
- transitionLeft: '',
- transitionWidth: '',
- };
- },
- computed: {
- barArea() {
- return this.$el.querySelector('.verify-bar-area');
- },
- resetSize() {
- return resetSize;
- },
- },
- watch: {
- // type变化则全面刷新
- type: {
- immediate: true,
- handler() {
- this.init();
- },
- },
- },
- mounted() {
- let verifyMoveBlock = document.querySelector('.verify-move-block');
- verifyMoveBlock.addEventListener('touchmove', function (event) {
- // 阻止默认的滑动行为
- event.preventDefault();
- });
- // 禁止拖拽
- this.$el.onselectstart = function () {
- return false;
- };
- console.log(this.defaultImg);
- },
- methods: {
- init() {
- this.text = this.explain;
- this.getPictrue();
- this.$nextTick(() => {
- const setSize = this.resetSize(this); // 重新设置宽度高度
- for (const key in setSize) {
- this.$set(this.setSize, key, setSize[key]);
- }
- this.$parent.$emit('ready', this);
- });
- var _this = this;
- window.removeEventListener('touchmove', function (e) {
- _this.move(e);
- });
- window.removeEventListener('mousemove', function (e) {
- _this.move(e);
- });
- // 鼠标松开
- window.removeEventListener('touchend', function () {
- _this.end();
- });
- window.removeEventListener('mouseup', function () {
- _this.end();
- });
- window.addEventListener('touchmove', function (e) {
- _this.move(e);
- });
- window.addEventListener('mousemove', function (e) {
- _this.move(e);
- });
- // 鼠标松开
- window.addEventListener('touchend', function () {
- _this.end();
- });
- window.addEventListener('mouseup', function () {
- _this.end();
- });
- },
- // 鼠标按下
- start: function (e) {
- e = e || window.event;
- let x = null;
- if (!e.touches) {
- // 兼容PC端
- x = e.clientX;
- } else {
- // 兼容移动端
- x = e.touches[0].pageX;
- }
- this.startLeft = Math.floor(
- x - this.barArea.getBoundingClientRect().left,
- );
- this.startMoveTime = +new Date(); // 开始滑动的时间
- if (this.isEnd == false) {
- this.text = '';
- this.moveBlockBackgroundColor = '#337ab7';
- this.leftBarBorderColor = '#337AB7';
- this.iconColor = '#fff';
- // e.stopPropagation();
- this.status = true;
- }
- },
- // 鼠标移动
- move: function (e) {
- e = e || window.event;
- if (this.status && this.isEnd == false) {
- if (!e.touches) {
- // 兼容PC端
- var x = e.clientX;
- } else {
- // 兼容移动端
- var x = e.touches[0].pageX;
- }
- var bar_area_left = this.barArea.getBoundingClientRect().left;
- var move_block_left = x - bar_area_left; // 小方块相对于父元素的left值
- if (
- move_block_left >=
- this.barArea.offsetWidth -
- parseInt(parseInt(this.blockSize.width) / 2) -
- 2
- ) {
- move_block_left =
- this.barArea.offsetWidth -
- parseInt(parseInt(this.blockSize.width) / 2) -
- 2;
- }
- if (move_block_left <= 0) {
- move_block_left = parseInt(parseInt(this.blockSize.width) / 2);
- }
- // 拖动后小方块的left值
- this.moveBlockLeft = move_block_left - this.startLeft + 'px';
- this.leftBarWidth = move_block_left - this.startLeft + 'px';
- }
- },
- // 鼠标松开
- end: function () {
- this.endMovetime = +new Date();
- var _this = this;
- // 判断是否重合
- if (this.status && this.isEnd == false) {
- var moveLeftDistance = parseInt(
- (this.moveBlockLeft || '').replace('px', ''),
- );
- moveLeftDistance =
- (moveLeftDistance * 310) / parseInt(this.setSize.imgWidth);
- const data = {
- captchaType: this.captchaType,
- pointJson: this.secretKey
- ? aesEncrypt(
- JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
- this.secretKey,
- )
- : JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
- token: this.backToken,
- };
- this.$axios.$post('activity/captcha/check', data).then((res) => {
- if (res.repCode == '0000') {
- this.moveBlockBackgroundColor = '#5cb85c';
- this.leftBarBorderColor = '#5cb85c';
- this.iconColor = '#fff';
- this.iconClass = 'icon-check';
- this.showRefresh = false;
- this.isEnd = true;
- if (this.mode == 'pop') {
- setTimeout(() => {
- this.$parent.clickShow = false;
- this.refresh();
- }, 1500);
- }
- this.passFlag = true;
- this.tipWords = `${(
- (this.endMovetime - this.startMoveTime) /
- 1000
- ).toFixed(2)}s验证成功`;
- var captchaVerification = this.secretKey
- ? aesEncrypt(
- this.backToken +
- '---' +
- JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
- this.secretKey,
- )
- : this.backToken +
- '---' +
- JSON.stringify({ x: moveLeftDistance, y: 5.0 });
- setTimeout(() => {
- this.tipWords = '';
- this.$parent.closeBox();
- this.$parent.$emit('success', { captchaVerification });
- }, 1000);
- } else {
- this.moveBlockBackgroundColor = '#d9534f';
- this.leftBarBorderColor = '#d9534f';
- this.iconColor = '#fff';
- this.iconClass = 'icon-close';
- this.passFlag = false;
- setTimeout(function () {
- _this.refresh();
- }, 1000);
- this.$parent.$emit('error', this);
- this.tipWords = '验证失败';
- setTimeout(() => {
- this.tipWords = '';
- }, 1000);
- }
- });
- this.status = false;
- }
- },
- refresh: function () {
- this.showRefresh = true;
- this.finishText = '';
- this.transitionLeft = 'left .3s';
- this.moveBlockLeft = 0;
- this.leftBarWidth = undefined;
- this.transitionWidth = 'width .3s';
- this.leftBarBorderColor = '#ddd';
- this.moveBlockBackgroundColor = '#fff';
- this.iconColor = '#000';
- this.iconClass = 'icon-right';
- this.isEnd = false;
- this.getPictrue();
- setTimeout(() => {
- this.transitionWidth = '';
- this.transitionLeft = '';
- this.text = this.explain;
- }, 300);
- },
- // 请求背景图片和验证图片
- getPictrue() {
- const data = {
- captchaType: this.captchaType,
- clientUid: localStorage.getItem('slider'),
- ts: Date.now(), // 现在的时间戳
- };
- this.$axios.$post('activity/captcha/get', data).then((res) => {
- if (res.repCode == '0000') {
- this.backImgBase = res.repData.originalImageBase64;
- this.blockBackImgBase = res.repData.jigsawImageBase64;
- this.backToken = res.repData.token;
- this.secretKey = res.repData.secretKey;
- } else {
- this.tipWords = res.repMsg;
- }
- // 判断接口请求次数是否失效
- if (res.repCode == '6201') {
- this.backImgBase = null;
- this.blockBackImgBase = null;
- }
- });
- },
- },
- };
- </script>
|