diff --git a/public/index.html b/public/index.html index d1a5ed4..04a7bb7 100644 --- a/public/index.html +++ b/public/index.html @@ -5,17 +5,20 @@ <%= htmlWebpackPlugin.options.title %> - +
+ +
+
- + diff --git a/src/global.scss b/src/global.scss index 3b467b8..0d1c53c 100644 --- a/src/global.scss +++ b/src/global.scss @@ -144,11 +144,6 @@ html { } } -// 阿里防刷 待加 -.alsc { - margin: 0 !important; -} - // PC 模版展示 .comWrapperPC { min-height: 667px !important; diff --git a/src/router/index.ts b/src/router/index.ts index 64c1d81..8e9821a 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -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; diff --git a/src/shims-vue.d.ts b/src/shims-vue.d.ts index 3804a43..3f632ac 100644 --- a/src/shims-vue.d.ts +++ b/src/shims-vue.d.ts @@ -4,3 +4,9 @@ declare module '*.vue' { const component: DefineComponent<{}, {}, any> export default component } + +interface Window { + CapCom: any; + CapTime: any; + initAliyunCaptcha: any; +} \ No newline at end of file diff --git a/src/utils/aliyunCaptcha.ts b/src/utils/aliyunCaptcha.ts new file mode 100644 index 0000000..b9a5924 --- /dev/null +++ b/src/utils/aliyunCaptcha.ts @@ -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; \ No newline at end of file diff --git a/src/utils/methods.ts b/src/utils/methods.ts index f11c006..c511191 100644 --- a/src/utils/methods.ts +++ b/src/utils/methods.ts @@ -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((resolve: any, reject) => { + showConfirmDialog({ + message: '是否确认兑换该商品?', + }) + .then(() => { + resolve(true) + }) + .catch(() => { + resolve(false) + }) + }); + return confirmRes; +} + /** * 公有的一些正则表达式 */ diff --git a/src/utils/request/index.ts b/src/utils/request/index.ts index ee58525..a471d4d 100644 --- a/src/utils/request/index.ts +++ b/src/utils/request/index.ts @@ -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 {}; } ); diff --git a/src/views/pages/comProduct/index.vue b/src/views/pages/comProduct/index.vue index f74d46a..2227a56 100644 --- a/src/views/pages/comProduct/index.vue +++ b/src/views/pages/comProduct/index.vue @@ -1,6 +1,6 @@