update @智能防刷验证 二次兑换弹窗验证
This commit is contained in:
parent
99aacf4b33
commit
2118efffd6
|
@ -5,17 +5,20 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,viewport-fit=cover" />
|
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,viewport-fit=cover" />
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
<!-- <script src="https://g.alicdn.com/AWSC/AWSC/awsc.js"></script> -->
|
<script type="text/javascript" src="https://o.alicdn.com/captcha-frontend/aliyunCaptcha/AliyunCaptcha.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<!-- 智能验证防刷 -->
|
||||||
|
<div id="captcha-element"></div>
|
||||||
|
<div id="captcha-button"></div>
|
||||||
<!-- 仅开发/测试使用 -->
|
<!-- 仅开发/测试使用 -->
|
||||||
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
<!-- <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var vConsole = new window.VConsole();
|
var vConsole = new window.VConsole();
|
||||||
</script>
|
</script> -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -144,11 +144,6 @@ html {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 阿里防刷 待加
|
|
||||||
.alsc {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PC 模版展示
|
// PC 模版展示
|
||||||
.comWrapperPC {
|
.comWrapperPC {
|
||||||
min-height: 667px !important;
|
min-height: 667px !important;
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {
|
||||||
createWebHashHistory,
|
createWebHashHistory,
|
||||||
createWebHistory,
|
createWebHistory,
|
||||||
} from "vue-router";
|
} from "vue-router";
|
||||||
|
import Cap from "@/utils/aliyunCaptcha";
|
||||||
|
|
||||||
// 公共路由
|
// 公共路由
|
||||||
const routePublic = [
|
const routePublic = [
|
||||||
|
@ -82,6 +83,12 @@ const router = createRouter({
|
||||||
});
|
});
|
||||||
|
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
|
// 默认全局 智能验证防刷
|
||||||
|
if (!window.CapCom && !window.CapTime) {
|
||||||
|
znInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首页 /XXX 获取 key
|
||||||
const rouList = routes.filter(
|
const rouList = routes.filter(
|
||||||
(item) => item.path !== "/" && item.path === to.path
|
(item) => item.path !== "/" && item.path === to.path
|
||||||
);
|
);
|
||||||
|
@ -98,4 +105,21 @@ router.beforeEach(async (to, from, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function znInit() {
|
||||||
|
window.CapCom = new Cap({});
|
||||||
|
const CapCom = window.CapCom;
|
||||||
|
setTimeout(() => {
|
||||||
|
CapCom.popup('start'); // 首页触发之后,二次触发才唤起验证 todo: 无痕验证(首次验证 不会渲染图形验证)
|
||||||
|
}, 3 * 1000);
|
||||||
|
|
||||||
|
window.CapTime = setInterval(() => {
|
||||||
|
if (CapCom) {
|
||||||
|
CapCom.popup('click');
|
||||||
|
} else {
|
||||||
|
znInit();
|
||||||
|
}
|
||||||
|
}, 5 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
@ -4,3 +4,9 @@ declare module '*.vue' {
|
||||||
const component: DefineComponent<{}, {}, any>
|
const component: DefineComponent<{}, {}, any>
|
||||||
export default component
|
export default component
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Window {
|
||||||
|
CapCom: any;
|
||||||
|
CapTime: any;
|
||||||
|
initAliyunCaptcha: any;
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
let captcha = null;
|
||||||
|
let captchaButton: any = null;
|
||||||
|
let popType: any = '';
|
||||||
|
|
||||||
|
class Cap {
|
||||||
|
constructor (opt = {}) {
|
||||||
|
this.clear();
|
||||||
|
this.init(opt).then();
|
||||||
|
}
|
||||||
|
clear () {
|
||||||
|
// 初始化-重置
|
||||||
|
captcha = null;
|
||||||
|
captchaButton = null;
|
||||||
|
popType = '';
|
||||||
|
|
||||||
|
// 必须删除相关元素,否则再次 init 多次调用 initAliyunCaptcha 会导致多次回调 captchaVerifyCallback
|
||||||
|
document.getElementById('aliyunCaptcha-mask')?.remove();
|
||||||
|
document.getElementById('aliyunCaptcha-window-popup')?.remove();
|
||||||
|
}
|
||||||
|
init = async function (opt: any) {
|
||||||
|
captchaButton = document.getElementById('captcha-button');
|
||||||
|
|
||||||
|
window.initAliyunCaptcha({
|
||||||
|
SceneId: '1mjp887e', // 场景ID。根据步骤二新建验证场景后,您可以在验证码场景列表,获取该场景的场景ID
|
||||||
|
prefix: '1mpccr', // 身份标。开通阿里云验证码2.0后,您可以在控制台概览页面的实例基本信息卡片区域,获取身份标
|
||||||
|
mode: 'popup', // 验证码模式。popup表示要集成的验证码模式为弹出式。无需修改
|
||||||
|
element: '#captcha-element', // 页面上预留的渲染验证码的元素,与原代码中预留的页面元素保持一致。
|
||||||
|
button: '#captcha-button', // 触发验证码弹窗的元素。button表示单击登录按钮后,触发captchaVerifyCallback函数。您可以根据实际使用的元素修改element的值
|
||||||
|
captchaVerifyCallback: this.captchaVerifyCallback, // 业务请求(带验证码校验)回调函数,无需修改
|
||||||
|
onBizResultCallback: this.onBizResultCallback, // 业务请求结果回调函数,无需修改
|
||||||
|
getInstance: this.getInstance, // 绑定验证码实例函数,无需修改
|
||||||
|
slideStyle: {
|
||||||
|
width: 280,
|
||||||
|
height: 40,
|
||||||
|
}, // 滑块验证码样式,支持自定义宽度和高度,单位为px。其中,width最小值为320 px
|
||||||
|
language: 'cn', // 验证码语言类型,支持简体中文(cn)、繁体中文(tw)、英文(en)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getInstance(instance: any) {
|
||||||
|
captcha = instance;
|
||||||
|
}
|
||||||
|
async captchaVerifyCallback(captchaVerifyParam: any) {
|
||||||
|
// console.log('---业务请求(带验证码校验)回调函数---', captchaVerifyParam);
|
||||||
|
return {
|
||||||
|
captchaResult: true,
|
||||||
|
bizResult: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 验证通过后调用
|
||||||
|
onBizResultCallback() {
|
||||||
|
// console.log('---业务请求结果回调函数---');
|
||||||
|
if (popType === 'click') {
|
||||||
|
// showToast('验证成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 弹出验证框
|
||||||
|
popup(val: any) {
|
||||||
|
popType = val; // 'start': 初始化;'click':唤起验证框
|
||||||
|
captchaButton.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Cap;
|
|
@ -1,4 +1,5 @@
|
||||||
import { isObject } from "@/utils/index";
|
import { isObject } from "@/utils/index";
|
||||||
|
import { showConfirmDialog } from "vant";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 深拷贝
|
* 深拷贝
|
||||||
|
@ -73,6 +74,25 @@ export function urlToLocal(query: any) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 链接参数写入local
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export async function receiveAgain() {
|
||||||
|
const confirmRes: any = await new Promise<void>((resolve: any, reject) => {
|
||||||
|
showConfirmDialog({
|
||||||
|
message: '是否确认兑换该商品?',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
resolve(false)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return confirmRes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公有的一些正则表达式
|
* 公有的一些正则表达式
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -43,12 +43,14 @@ service.interceptors.request.use((config: AxiosRequestConfig) => {
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response: AxiosResponse) => {
|
(response: AxiosResponse) => {
|
||||||
const data = response.data;
|
const data = response.data;
|
||||||
if ([401, 4001].includes(data.code)) {
|
|
||||||
location.replace(`${location.origin}/yxh5/home?loginBack=${location.href}`);
|
|
||||||
}
|
|
||||||
return data || {};
|
return data || {};
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
|
// todo 待验证接口 token 失效情况
|
||||||
|
console.log('---err---', err);
|
||||||
|
if (err?.response?.status === 401 || err?.response?.code === 4001) {
|
||||||
|
location.replace(`${location.origin}/yxh5/home?loginBack=${location.href}`);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<van-loading v-if="loadingStatus" class="pageNoneLoading_Vant" size="24px" color="#0094ff" vertical>加载中...</van-loading>
|
<van-loading v-if="loadingStatus" class="pageNoneLoading_Vant" size="24px" color="#0094ff" vertical>加载中...</van-loading>
|
||||||
<div v-else class="pageBody">
|
<div v-else class="comProductBody">
|
||||||
<ul class="typeBox">
|
<ul class="typeBox">
|
||||||
<template v-for="(item) in showData" :key="item">
|
<template v-for="(item) in showData" :key="item">
|
||||||
<li
|
<li
|
||||||
|
@ -556,7 +556,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.pageBody {
|
.comProductBody {
|
||||||
width: 375px;
|
width: 375px;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<van-loading v-if="loadingStatus" class="pageNoneLoading_Vant" size="24px" color="#0094ff" vertical>加载中...</van-loading>
|
<van-loading v-if="loadingStatus" class="pageNoneLoading_Vant" size="24px" color="#0094ff" vertical>加载中...</van-loading>
|
||||||
<div v-else class="pageBody">
|
<div v-else class="orderListBody">
|
||||||
<van-pull-refresh class="refreshBody" v-model="refreshLoading" @refresh="onRefresh">
|
<van-pull-refresh class="refreshBody" v-model="refreshLoading" @refresh="onRefresh">
|
||||||
<ul class="listBox">
|
<ul class="listBox">
|
||||||
<li @click="toDetail(item)" v-for="(item, index) in listData" :key="index">
|
<li @click="toDetail(item)" v-for="(item, index) in listData" :key="index">
|
||||||
|
@ -79,7 +79,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.pageBody {
|
.orderListBody {
|
||||||
width: 375px;
|
width: 375px;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #f9fafb;
|
background-color: #f9fafb;
|
||||||
|
|
|
@ -78,7 +78,7 @@ import "./index.scss";
|
||||||
import { DETAIL_QUERY, EXCHANGE, ORDER_QUERY } from "@/router/api";
|
import { DETAIL_QUERY, EXCHANGE, ORDER_QUERY } from "@/router/api";
|
||||||
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
||||||
import { channelJudge } from "@/utils/empower";
|
import { channelJudge } from "@/utils/empower";
|
||||||
import { phoneRegex, startsWith, urlToLocal } from "@/utils/methods";
|
import { phoneRegex, receiveAgain, startsWith, urlToLocal } from "@/utils/methods";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "cmsCash",
|
name: "cmsCash",
|
||||||
|
@ -226,6 +226,7 @@ export default {
|
||||||
}
|
}
|
||||||
// 针对 支付宝-官方领取/微信 需要授权场景 判断
|
// 针对 支付宝-官方领取/微信 需要授权场景 判断
|
||||||
if (!account) return channelJudge(this.cash.channel, this.cash.receive_mode, { id: this.goodId });
|
if (!account) return channelJudge(this.cash.channel, this.cash.receive_mode, { id: this.goodId });
|
||||||
|
if (!await receiveAgain()) return;
|
||||||
this.overlayLoad = true;
|
this.overlayLoad = true;
|
||||||
const res = await EXCHANGE({
|
const res = await EXCHANGE({
|
||||||
key: this.key,
|
key: this.key,
|
||||||
|
|
|
@ -173,4 +173,7 @@
|
||||||
color: #45464b !important;
|
color: #45464b !important;
|
||||||
word-wrap: break-word; /* 强制换行 */
|
word-wrap: break-word; /* 强制换行 */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.van-overflow-hidden {
|
||||||
|
overflow: visible !important;
|
||||||
}
|
}
|
|
@ -73,7 +73,7 @@
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import config from "./config";
|
import config from "./config";
|
||||||
import { DETAIL_QUERY, GET_THEME, EXCHANGE, ORDER_QUERY, GET_SMS } from "@/router/api";
|
import { DETAIL_QUERY, GET_THEME, EXCHANGE, ORDER_QUERY, GET_SMS } from "@/router/api";
|
||||||
import { phoneRegex } from "@/utils/methods";
|
import { phoneRegex, receiveAgain } from "@/utils/methods";
|
||||||
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
||||||
import { startsWith } from "@/utils/methods";
|
import { startsWith } from "@/utils/methods";
|
||||||
|
|
||||||
|
@ -273,6 +273,7 @@ export default {
|
||||||
}
|
}
|
||||||
account = this.inputVal;
|
account = this.inputVal;
|
||||||
}
|
}
|
||||||
|
if (!await receiveAgain()) return;
|
||||||
this.overlayLoad = true;
|
this.overlayLoad = true;
|
||||||
const res = await EXCHANGE({
|
const res = await EXCHANGE({
|
||||||
key: this.key,
|
key: this.key,
|
||||||
|
|
|
@ -71,7 +71,7 @@ import "./index.scss";
|
||||||
import config from "./config";
|
import config from "./config";
|
||||||
import { GET_THEME, DETAIL_QUERY, ORDER_QUERY, EXCHANGE } from "@/router/api";
|
import { GET_THEME, DETAIL_QUERY, ORDER_QUERY, EXCHANGE } from "@/router/api";
|
||||||
import { btnHighLight, btnMap, btnPoll, pollTimeNum } from "@/utils/datas";
|
import { btnHighLight, btnMap, btnPoll, pollTimeNum } from "@/utils/datas";
|
||||||
import { phoneRegex, startsWith } from "@/utils/methods";
|
import { phoneRegex, receiveAgain, startsWith } from "@/utils/methods";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
// 立减金 手输配置页 (支付宝账号领取、云闪付)
|
// 立减金 手输配置页 (支付宝账号领取、云闪付)
|
||||||
|
@ -290,6 +290,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
return showToast('仅支持支付宝-账号领取或云闪付');
|
return showToast('仅支持支付宝-账号领取或云闪付');
|
||||||
}
|
}
|
||||||
|
if (!await receiveAgain()) return;
|
||||||
this.overlayLoad = true;
|
this.overlayLoad = true;
|
||||||
const res = await EXCHANGE({
|
const res = await EXCHANGE({
|
||||||
key: this.key,
|
key: this.key,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
v-else
|
v-else
|
||||||
:slides-per-view="3"
|
:slides-per-view="3"
|
||||||
:space-between="8"
|
:space-between="8"
|
||||||
:loop="true"
|
:loop="pageData.length >=3"
|
||||||
:loopAdditionalSlides="2"
|
:loopAdditionalSlides="2"
|
||||||
:centered-slides="true"
|
:centered-slides="true"
|
||||||
:initialSlide="initialSlide"
|
:initialSlide="initialSlide"
|
||||||
|
@ -110,7 +110,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// modules: [ Pagination, Autoplay ],
|
// modules: [ Pagination, Autoplay ],
|
||||||
initialSlide: 1,
|
initialSlide: 0,
|
||||||
key: this.$route.query.key || localStorage.getItem('key'),
|
key: this.$route.query.key || localStorage.getItem('key'),
|
||||||
// jumpPath: sessionStorage.getItem('jumpPath'),
|
// jumpPath: sessionStorage.getItem('jumpPath'),
|
||||||
loadingStatus: false,
|
loadingStatus: false,
|
||||||
|
@ -235,8 +235,9 @@ export default {
|
||||||
...this.cssData,
|
...this.cssData,
|
||||||
...JSON.parse(res.data.config)
|
...JSON.parse(res.data.config)
|
||||||
};
|
};
|
||||||
this.pageData = this.cssData.contentType === 1 ? [ ...changeData, ...changeData ] : [ ...changeData ]; // 处理轮播样式
|
const lbBool = ((this.cssData.contentType === 1) && (changeData.length >= 3));
|
||||||
this.initialSlide = changeData.length;
|
this.pageData = lbBool ? [ ...changeData, ...changeData ] : [ ...changeData ]; // 处理轮播样式
|
||||||
|
this.initialSlide = lbBool ? changeData.length : 0;
|
||||||
this.loadingStatus = false;
|
this.loadingStatus = false;
|
||||||
} else {
|
} else {
|
||||||
showToast(res?.message || '请求失败');
|
showToast(res?.message || '请求失败');
|
||||||
|
|
|
@ -57,7 +57,7 @@ import "./index.scss";
|
||||||
import { DETAIL_QUERY, EXCHANGE, ORDER_QUERY } from "@/router/api";
|
import { DETAIL_QUERY, EXCHANGE, ORDER_QUERY } from "@/router/api";
|
||||||
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
||||||
import { channelJudge } from "@/utils/empower";
|
import { channelJudge } from "@/utils/empower";
|
||||||
import { startsWith, urlToLocal } from "@/utils/methods";
|
import { startsWith, urlToLocal, receiveAgain } from "@/utils/methods";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "cmsVoucher",
|
name: "cmsVoucher",
|
||||||
|
@ -154,6 +154,7 @@ export default {
|
||||||
}
|
}
|
||||||
// 针对 支付宝-官方领取/微信 需要授权场景 判断
|
// 针对 支付宝-官方领取/微信 需要授权场景 判断
|
||||||
if (!account) return channelJudge(this.info.channel, this.info.receive_mode, { id: this.goodId });
|
if (!account) return channelJudge(this.info.channel, this.info.receive_mode, { id: this.goodId });
|
||||||
|
if (!await receiveAgain()) return;
|
||||||
this.overlayLoad = true;
|
this.overlayLoad = true;
|
||||||
const res = await EXCHANGE({
|
const res = await EXCHANGE({
|
||||||
key: this.key,
|
key: this.key,
|
||||||
|
|
Loading…
Reference in New Issue