From 2fca178eeb886282429331a3b357a749d40617e7 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Mon, 15 Jan 2024 13:20:53 +0800 Subject: [PATCH] fix --- package-lock.json | 23 +++ package.json | 2 + src/main.ts | 15 +- src/router/index.ts | 5 + src/tool/cookie.js | 2 +- src/tool/https.js | 3 +- src/tool/util.js | 279 +++++++++++++++++--------------- src/views/LoginPage.vue | 2 + src/views/setIdentification.vue | 102 ++++++++++++ 9 files changed, 302 insertions(+), 131 deletions(-) create mode 100644 src/views/setIdentification.vue diff --git a/package-lock.json b/package-lock.json index c3a21f93..1ba6e98f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,14 @@ "dependencies": { "@ans1998/vue3-color": "^3.0.7", "@flaticon/flaticon-uicons": "^2.3.0", + "@types/fingerprintjs2": "^2.0.0", "ant-design-vue": "^3.2.12", "axios": "^1.4.0", "core-js": "^3.8.3", "driver.js": "^1.3.1", "element-plus": "^2.4.2", "file-saver": "^2.0.5", + "fingerprintjs2": "^2.1.4", "html2canvas": "^1.4.1", "jszip": "^3.10.1", "md5": "^2.3.0", @@ -2304,6 +2306,11 @@ "@types/range-parser": "*" } }, + "node_modules/@types/fingerprintjs2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/fingerprintjs2/-/fingerprintjs2-2.0.0.tgz", + "integrity": "sha512-isSTwNnW5I6zGZnpkinmVcV9pJqr7cLELns+tXDYzskIOAb2J+iCQ0mQJ9bRjHJhZfdlTFXZoCYK9ZgT3oMWXQ==" + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmmirror.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -6515,6 +6522,12 @@ "node": ">=8" } }, + "node_modules/fingerprintjs2": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/fingerprintjs2/-/fingerprintjs2-2.1.4.tgz", + "integrity": "sha512-veP2yVsnYvjDVkzZMyIEwpqCAQfsBLH+U4PK5MlFAnLjZrttbdRqEArE1fPcnJFz5oS5CrdONbsV7J6FGpIJEQ==", + "deprecated": "Package has been renamed to @fingerprintjs/fingerprintjs. Install @fingerprintjs/fingerprintjs to get updates." + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz", @@ -14057,6 +14070,11 @@ "@types/range-parser": "*" } }, + "@types/fingerprintjs2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/fingerprintjs2/-/fingerprintjs2-2.0.0.tgz", + "integrity": "sha512-isSTwNnW5I6zGZnpkinmVcV9pJqr7cLELns+tXDYzskIOAb2J+iCQ0mQJ9bRjHJhZfdlTFXZoCYK9ZgT3oMWXQ==" + }, "@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmmirror.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -17428,6 +17446,11 @@ "path-exists": "^4.0.0" } }, + "fingerprintjs2": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/fingerprintjs2/-/fingerprintjs2-2.1.4.tgz", + "integrity": "sha512-veP2yVsnYvjDVkzZMyIEwpqCAQfsBLH+U4PK5MlFAnLjZrttbdRqEArE1fPcnJFz5oS5CrdONbsV7J6FGpIJEQ==" + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz", diff --git a/package.json b/package.json index 04a4ba0d..58f8e4ba 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,14 @@ "dependencies": { "@ans1998/vue3-color": "^3.0.7", "@flaticon/flaticon-uicons": "^2.3.0", + "@types/fingerprintjs2": "^2.0.0", "ant-design-vue": "^3.2.12", "axios": "^1.4.0", "core-js": "^3.8.3", "driver.js": "^1.3.1", "element-plus": "^2.4.2", "file-saver": "^2.0.5", + "fingerprintjs2": "^2.1.4", "html2canvas": "^1.4.1", "jszip": "^3.10.1", "md5": "^2.3.0", diff --git a/src/main.ts b/src/main.ts index 68213234..6ae2b416 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,12 +13,23 @@ import VueLazyload from "vue-lazyload"; import i18n from './lang/index' import GO from './tool/GO' import "../node_modules/@flaticon/flaticon-uicons/css/all/all.css" +import Fingerprint2 from 'fingerprintjs2';//获取浏览器唯一标识 flexible() import { useI18n } from 'vue-i18n'; // console.log(process.env) - +Fingerprint2.get(function(components) { + const values = components.map(function(component,index) { + if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样 + return component.value.replace(/\bNetType\/\w+\b/, '') + } + return component.value + }) + // 生成最终id murmur + const murmur = Fingerprint2.x64hash128(values.join(''), 31); + console.log('浏览器指纹码:'+murmur ) + }) let loadingParam = { loading: require('./assets/images/homePage/loading.gif'), attempt: 1 - } +} createApp(App).use(store).use(router).use(Antd).use(VueLazyload,loadingParam).use(i18n).mount('#app') diff --git a/src/router/index.ts b/src/router/index.ts index 02565bfa..f5fa627d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -44,6 +44,11 @@ const routes: Array = [ name: 'trialApproval', component: _import('trialApproval') }, + { + path: '/setIdentification', + name: 'setIdentification', + component: _import('setIdentification') + }, ] const router = createRouter({ diff --git a/src/tool/cookie.js b/src/tool/cookie.js index b916e204..c2623f49 100644 --- a/src/tool/cookie.js +++ b/src/tool/cookie.js @@ -1,7 +1,7 @@ const setCookie = (name,value) => { var Days = 30; var exp = new Date(); - exp.setTime(exp.getTime() + Days*24*60*60*30); + exp.setTime(exp.getTime() + Days*24*60*60*1000); document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString(); } diff --git a/src/tool/https.js b/src/tool/https.js index 6f8eb4b2..e1be8478 100644 --- a/src/tool/https.js +++ b/src/tool/https.js @@ -80,7 +80,7 @@ axios.interceptors.response.use((res) =>{ } }, function(error) { - if(error?.response?.status === 401){ + if(error?.response?.status === 401&&router.currentRoute._value.name != 'setIdentification'){//如果是记录浏览器页面就不跳转login router.replace('/login') return Promise.reject() } @@ -89,7 +89,6 @@ axios.interceptors.response.use((res) =>{ return Promise.reject(data_new); }); - export const Https = { httpUrls: { interfaceUrl: '', diff --git a/src/tool/util.js b/src/tool/util.js index 6710e317..59406259 100644 --- a/src/tool/util.js +++ b/src/tool/util.js @@ -1,170 +1,197 @@ -const isEmail = (email)=>{ - let reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/ - let result = reg.test(email) - return result +const isEmail = (email) => { + let reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/ + let result = reg.test(email) + return result +} + +const getUploadUrl = () => { + let url = process.env.VUE_APP_BASE_URL || '' + // let url = "http://18.167.251.121:10086" + return url } -const getUploadUrl = () =>{ - let url = process.env.VUE_APP_BASE_URL || '' - // let url = "http://18.167.251.121:10086" - return url -} - function dataURLtoBlob(dataurl) { - var arr = dataurl.split(','); - var mime = arr[0].match(/:(.*?);/)[1]; - var bstr =atob(arr[1]); - var n = bstr.length; - var u8arr =new Uint8Array(n); - while (n--) { - u8arr[n] = bstr.charCodeAt(n); - } - return new Blob([u8arr], {type: mime }); + var arr = dataurl.split(','); + var mime = arr[0].match(/:(.*?);/)[1]; + var bstr = atob(arr[1]); + var n = bstr.length; + var u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new Blob([u8arr], { type: mime }); } -function blobToFile(blob, fileName){ - blob.lastModifiedDate =new Date(); - blob.name = fileName; - return blob; +function blobToFile(blob, fileName) { + blob.lastModifiedDate = new Date(); + blob.name = fileName; + return blob; } //下载图片 -function downloadIamge (imgsrc, name) { // 下载图片地址和图片名 +function downloadIamge(imgsrc, name) { // 下载图片地址和图片名 var image = new Image() // 解决跨域 Canvas 污染问题 image.setAttribute('crossOrigin', 'anonymous') image.onload = function () { - var canvas = document.createElement('canvas') - canvas.width = image.width - canvas.height = image.height - var context = canvas.getContext('2d') - context.drawImage(image, 0, 0, image.width, image.height) - var url = canvas.toDataURL('image/jpeg') // 得到图片的base64编码数据 - var a = document.createElement('a') // 生成一个a元素 - var event = new MouseEvent('click') // 创建一个单击事件 - a.download = name || 'generate' // 设置图片名称 - a.href = url // 将生成的URL设置为a.href属性 - a.target='_blank' - a.dispatchEvent(event) // 触发a的单击事件 + var canvas = document.createElement('canvas') + canvas.width = image.width + canvas.height = image.height + var context = canvas.getContext('2d') + context.drawImage(image, 0, 0, image.width, image.height) + var url = canvas.toDataURL('image/jpeg') // 得到图片的base64编码数据 + var a = document.createElement('a') // 生成一个a元素 + var event = new MouseEvent('click') // 创建一个单击事件 + a.download = name || 'generate' // 设置图片名称 + a.href = url // 将生成的URL设置为a.href属性 + a.target = '_blank' + a.dispatchEvent(event) // 触发a的单击事件 } image.src = imgsrc } -function dataURLtoFile(dataurl, filename){ - var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], - bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); - while(n--){ - u8arr[n] = bstr.charCodeAt(n); - } - var blob = dataURLtoBlob(dataurl); - return blobToFile(blob, filename); +function dataURLtoFile(dataurl, filename) { + var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + var blob = dataURLtoBlob(dataurl); + return blobToFile(blob, filename); } const base64toFile = (dataurl, filename = 'file') => { - let arr = dataurl.split(',') - let mime = arr[0].match(/:(.*?);/)[1] - let suffix = mime.split('/')[1] - let bstr = atob(arr[1]) - let n = bstr.length - let u8arr = new Uint8Array(n) - while (n--) { - u8arr[n] = bstr.charCodeAt(n) - } - return new File([u8arr], `${filename}.${suffix}`, { - type: mime - }) + let arr = dataurl.split(',') + let mime = arr[0].match(/:(.*?);/)[1] + let suffix = mime.split('/')[1] + let bstr = atob(arr[1]) + let n = bstr.length + let u8arr = new Uint8Array(n) + while (n--) { + u8arr[n] = bstr.charCodeAt(n) + } + return new File([u8arr], `${filename}.${suffix}`, { + type: mime + }) } function rgbToHsv([R, G, B]) { - R /= 255 - G /= 255 - B /= 255 - const max = Math.max(R, G, B) - const min = Math.min(R, G, B) - const delta = max - min - var H,S,V + R /= 255 + G /= 255 + B /= 255 + const max = Math.max(R, G, B) + const min = Math.min(R, G, B) + const delta = max - min + var H, S, V if (delta === 0) { - H = 0; + H = 0; } else if (max === R) { - H = ((G - B) / delta) % 6; + H = ((G - B) / delta) % 6; } else if (max === G) { - H = (B - R) / delta + 2; + H = (B - R) / delta + 2; } else { // max === B - H = (R - G) / delta + 4; + H = (R - G) / delta + 4; } H = Math.round(H * 60); // 范围为 0-360 - if(H<0){ - H = 360+H + if (H < 0) { + H = 360 + H } if (max === 0) { - S = 0; + S = 0; } else { - S = delta / max; + S = delta / max; } - S = Math.round(S*100); // 范围为 0-100 - V = Math.round(max*100); // 范围为 0-100 - return [H, S, V] - } + S = Math.round(S * 100); // 范围为 0-100 + V = Math.round(max * 100); // 范围为 0-100 + return [H, S, V] +} - const formatTime = (timestamp, fmt) =>{ - // date = new Date(), fmt = 'MM/dd/yyyy'; - let date = new Date(); - date.setTime(timestamp * 1000); +const formatTime = (timestamp, fmt) => { + // date = new Date(), fmt = 'MM/dd/yyyy'; + let date = new Date(); + date.setTime(timestamp * 1000); - if (!fmt) { - formatRule ? (fmt = formatRule) : (fmt = "YYYY-MM-DD hh:mm:ss"); - } - // console.log(formatRule) - let o = { - 'M+': date.getMonth() + 1, // 月份 - 'D+': date.getDate(), // 日 - 'h+': date.getHours(), // 小时 - 'm+': date.getMinutes(), // 分 - 's+': date.getSeconds(), // 秒 - 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度 - 'S+': date.getMilliseconds(), // 毫秒 - 'a': date.getHours() > 12 - ? 'PM' - : 'AM' // 上午还是下午 - }; - if (/(Y+)/.test(fmt)) { - fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); - } - if(/(a)/.test(fmt)&&o['h+']>12){ - o['h+'] = o['h+'] - 12 - } - for (let k in o) { - if (new RegExp('(' + k + ')').test(fmt)) { - fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) - ? (o[k]) - : (('00' + o[k]).substr(('' + o[k]).length))); - } - } + if (!fmt) { + formatRule ? (fmt = formatRule) : (fmt = "YYYY-MM-DD hh:mm:ss"); + } + // console.log(formatRule) + let o = { + 'M+': date.getMonth() + 1, // 月份 + 'D+': date.getDate(), // 日 + 'h+': date.getHours(), // 小时 + 'm+': date.getMinutes(), // 分 + 's+': date.getSeconds(), // 秒 + 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度 + 'S+': date.getMilliseconds(), // 毫秒 + 'a': date.getHours() > 12 + ? 'PM' + : 'AM' // 上午还是下午 + }; + if (/(Y+)/.test(fmt)) { + fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); + } + if (/(a)/.test(fmt) && o['h+'] > 12) { + o['h+'] = o['h+'] - 12 + } + for (let k in o) { + if (new RegExp('(' + k + ')').test(fmt)) { + fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) + ? (o[k]) + : (('00' + o[k]).substr(('' + o[k]).length))); + } + } - return fmt; + return fmt; } const isMoible = () => { - let is_mobile = navigator.userAgent.toLowerCase().match(/(ipad|ipod|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i) != null; - if(is_mobile){ - return true - }else{ - return false - } + let is_mobile = navigator.userAgent.toLowerCase().match(/(ipad|ipod|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i) != null; + if (is_mobile) { + return true + } else { + return false + } } - -export{ - isEmail, - getUploadUrl, - dataURLtoFile, - blobToFile, - base64toFile, - rgbToHsv, - formatTime, - dataURLtoBlob, - isMoible, +function getBrowserInfo() {//获取是什么浏览器 + var agent = navigator.userAgent.toLowerCase(); + var userAgent = navigator.userAgent; + var regStr_ie = /msie [\d.]+;/gi; + var regStr_ff = /firefox\/[\d.]+/gi + var regStr_chrome = /chrome\/[\d.]+/gi; + var regStr_saf = /safari\/[\d.]+/gi; + var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器 + var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器 + console.log(isIE,isEdge); + //IE + if (agent.indexOf("msie") > 0) { + return agent.match(regStr_ie); + } + //firefox + if (agent.indexOf("firefox") > 0) { + return agent.match(regStr_ff); + } + //Chrome + if (agent.indexOf("chrome") > 0) { + return agent.match(regStr_chrome); + } + //Safari + if (agent.indexOf("safari") > 0 && agent.indexOf("chrome") < 0) { + return agent.match(regStr_saf); + } +} +export { + isEmail, + getUploadUrl, + dataURLtoFile, + blobToFile, + base64toFile, + rgbToHsv, + formatTime, + dataURLtoBlob, + isMoible, downloadIamge, + getBrowserInfo, } \ No newline at end of file diff --git a/src/views/LoginPage.vue b/src/views/LoginPage.vue index 40b4c13a..da3d0a9e 100644 --- a/src/views/LoginPage.vue +++ b/src/views/LoginPage.vue @@ -463,6 +463,8 @@ export default defineComponent({ Https.axiosPost(Https.httpUrls.accountLogin, data).then( (rv: any) => { if (rv) { + console.log(rv); + this.createTimer(); let isTest = rv.isTrial == 1?true:false let isBeginner = rv.isBeginner == 1?true:false diff --git a/src/views/setIdentification.vue b/src/views/setIdentification.vue new file mode 100644 index 00000000..3f748a8f --- /dev/null +++ b/src/views/setIdentification.vue @@ -0,0 +1,102 @@ + + + \ No newline at end of file