update @智能防刷验证 二次兑换弹窗验证
This commit is contained in:
parent
99aacf4b33
commit
2118efffd6
|
@ -5,17 +5,20 @@
|
|||
<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" />
|
||||
<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>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<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>
|
||||
var vConsole = new window.VConsole();
|
||||
</script>
|
||||
</script> -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -144,11 +144,6 @@ html {
|
|||
}
|
||||
}
|
||||
|
||||
// 阿里防刷 待加
|
||||
.alsc {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
// PC 模版展示
|
||||
.comWrapperPC {
|
||||
min-height: 667px !important;
|
||||
|
|
|
@ -3,6 +3,7 @@ import {
|
|||
createWebHashHistory,
|
||||
createWebHistory,
|
||||
} from "vue-router";
|
||||
import Cap from "@/utils/aliyunCaptcha";
|
||||
|
||||
// 公共路由
|
||||
const routePublic = [
|
||||
|
@ -82,6 +83,12 @@ const router = createRouter({
|
|||
});
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
// 默认全局 智能验证防刷
|
||||
if (!window.CapCom && !window.CapTime) {
|
||||
znInit();
|
||||
}
|
||||
|
||||
// 首页 /XXX 获取 key
|
||||
const rouList = routes.filter(
|
||||
(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;
|
||||
|
|
|
@ -4,3 +4,9 @@ declare module '*.vue' {
|
|||
const component: DefineComponent<{}, {}, any>
|
||||
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 { 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(
|
||||
(response: AxiosResponse) => {
|
||||
const data = response.data;
|
||||
if ([401, 4001].includes(data.code)) {
|
||||
location.replace(`${location.origin}/yxh5/home?loginBack=${location.href}`);
|
||||
}
|
||||
return data || {};
|
||||
},
|
||||
(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 {};
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<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">
|
||||
<template v-for="(item) in showData" :key="item">
|
||||
<li
|
||||
|
@ -556,7 +556,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pageBody {
|
||||
.comProductBody {
|
||||
width: 375px;
|
||||
min-height: 100vh;
|
||||
background-color: #ffffff;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<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">
|
||||
<ul class="listBox">
|
||||
<li @click="toDetail(item)" v-for="(item, index) in listData" :key="index">
|
||||
|
@ -79,7 +79,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pageBody {
|
||||
.orderListBody {
|
||||
width: 375px;
|
||||
min-height: 100vh;
|
||||
background-color: #f9fafb;
|
||||
|
|
|
@ -78,7 +78,7 @@ import "./index.scss";
|
|||
import { DETAIL_QUERY, EXCHANGE, ORDER_QUERY } from "@/router/api";
|
||||
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
||||
import { channelJudge } from "@/utils/empower";
|
||||
import { phoneRegex, startsWith, urlToLocal } from "@/utils/methods";
|
||||
import { phoneRegex, receiveAgain, startsWith, urlToLocal } from "@/utils/methods";
|
||||
|
||||
export default {
|
||||
name: "cmsCash",
|
||||
|
@ -226,6 +226,7 @@ export default {
|
|||
}
|
||||
// 针对 支付宝-官方领取/微信 需要授权场景 判断
|
||||
if (!account) return channelJudge(this.cash.channel, this.cash.receive_mode, { id: this.goodId });
|
||||
if (!await receiveAgain()) return;
|
||||
this.overlayLoad = true;
|
||||
const res = await EXCHANGE({
|
||||
key: this.key,
|
||||
|
|
|
@ -173,4 +173,7 @@
|
|||
color: #45464b !important;
|
||||
word-wrap: break-word; /* 强制换行 */
|
||||
}
|
||||
}
|
||||
.van-overflow-hidden {
|
||||
overflow: visible !important;
|
||||
}
|
|
@ -73,7 +73,7 @@
|
|||
import "./index.scss";
|
||||
import config from "./config";
|
||||
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 { startsWith } from "@/utils/methods";
|
||||
|
||||
|
@ -273,6 +273,7 @@ export default {
|
|||
}
|
||||
account = this.inputVal;
|
||||
}
|
||||
if (!await receiveAgain()) return;
|
||||
this.overlayLoad = true;
|
||||
const res = await EXCHANGE({
|
||||
key: this.key,
|
||||
|
|
|
@ -71,7 +71,7 @@ import "./index.scss";
|
|||
import config from "./config";
|
||||
import { GET_THEME, DETAIL_QUERY, ORDER_QUERY, EXCHANGE } from "@/router/api";
|
||||
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";
|
||||
|
||||
// 立减金 手输配置页 (支付宝账号领取、云闪付)
|
||||
|
@ -290,6 +290,7 @@ export default {
|
|||
} else {
|
||||
return showToast('仅支持支付宝-账号领取或云闪付');
|
||||
}
|
||||
if (!await receiveAgain()) return;
|
||||
this.overlayLoad = true;
|
||||
const res = await EXCHANGE({
|
||||
key: this.key,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
v-else
|
||||
:slides-per-view="3"
|
||||
:space-between="8"
|
||||
:loop="true"
|
||||
:loop="pageData.length >=3"
|
||||
:loopAdditionalSlides="2"
|
||||
:centered-slides="true"
|
||||
:initialSlide="initialSlide"
|
||||
|
@ -110,7 +110,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
// modules: [ Pagination, Autoplay ],
|
||||
initialSlide: 1,
|
||||
initialSlide: 0,
|
||||
key: this.$route.query.key || localStorage.getItem('key'),
|
||||
// jumpPath: sessionStorage.getItem('jumpPath'),
|
||||
loadingStatus: false,
|
||||
|
@ -235,8 +235,9 @@ export default {
|
|||
...this.cssData,
|
||||
...JSON.parse(res.data.config)
|
||||
};
|
||||
this.pageData = this.cssData.contentType === 1 ? [ ...changeData, ...changeData ] : [ ...changeData ]; // 处理轮播样式
|
||||
this.initialSlide = changeData.length;
|
||||
const lbBool = ((this.cssData.contentType === 1) && (changeData.length >= 3));
|
||||
this.pageData = lbBool ? [ ...changeData, ...changeData ] : [ ...changeData ]; // 处理轮播样式
|
||||
this.initialSlide = lbBool ? changeData.length : 0;
|
||||
this.loadingStatus = false;
|
||||
} else {
|
||||
showToast(res?.message || '请求失败');
|
||||
|
|
|
@ -57,7 +57,7 @@ import "./index.scss";
|
|||
import { DETAIL_QUERY, EXCHANGE, ORDER_QUERY } from "@/router/api";
|
||||
import { btnMap, btnHighLight, btnPoll, pollTimeNum } from "@/utils/datas";
|
||||
import { channelJudge } from "@/utils/empower";
|
||||
import { startsWith, urlToLocal } from "@/utils/methods";
|
||||
import { startsWith, urlToLocal, receiveAgain } from "@/utils/methods";
|
||||
|
||||
export default {
|
||||
name: "cmsVoucher",
|
||||
|
@ -154,6 +154,7 @@ export default {
|
|||
}
|
||||
// 针对 支付宝-官方领取/微信 需要授权场景 判断
|
||||
if (!account) return channelJudge(this.info.channel, this.info.receive_mode, { id: this.goodId });
|
||||
if (!await receiveAgain()) return;
|
||||
this.overlayLoad = true;
|
||||
const res = await EXCHANGE({
|
||||
key: this.key,
|
||||
|
|
Loading…
Reference in New Issue