From 10d6cce1bfe0419eb3ac0a6769c9c3539aa129b8 Mon Sep 17 00:00:00 2001 From: lijun Date: Sun, 12 Oct 2025 15:22:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=8C=E6=AC=A1=E8=AE=A4?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 151 +++++++++++++++++++++++++++++++++++- package.json | 1 + src/api/user.ts | 36 ++++++++- src/views/pages/login.vue | 82 +++++++++++++++++++- src/views/pages/ucenter.vue | 96 ++++++++++++++++++++++- yarn.lock | 96 ++++++++++++++++++++++- 6 files changed, 456 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 751afe8..9c69bac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "vue-cropper": "1.1.1", "vue-cropperjs": "^5.0.0", "vue-echarts": "^6.6.9", + "vue-qr": "^4.0.9", "vue-router": "^4.2.5", "vue-schart": "^2.0.0", "xlsx": "^0.18.5" @@ -2564,6 +2565,20 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deepmerge": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", @@ -3355,6 +3370,11 @@ "node": ">=0.8" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3528,6 +3548,21 @@ "url": "https://opencollective.com/immer" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", @@ -3665,6 +3700,11 @@ "node": ">=14" } }, + "node_modules/js-binary-schema-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz", + "integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==" + }, "node_modules/js-cookie": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", @@ -4598,11 +4638,21 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4740,6 +4790,14 @@ "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -4761,6 +4819,11 @@ "path-to-regexp": "~1.2.1" } }, + "node_modules/parenthesis": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/parenthesis/-/parenthesis-3.1.8.tgz", + "integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==" + }, "node_modules/path-data-parser": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", @@ -5207,6 +5270,49 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/slate": { "version": "0.72.8", "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz", @@ -5284,6 +5390,14 @@ "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz", "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==" }, + "node_modules/string-split-by": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string-split-by/-/string-split-by-1.0.0.tgz", + "integrity": "sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==", + "dependencies": { + "parenthesis": "^3.1.5" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -5912,6 +6026,36 @@ } } }, + "node_modules/vue-qr": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/vue-qr/-/vue-qr-4.0.9.tgz", + "integrity": "sha512-pAISV94T0MNEYA3NGjykUpsXRE2QfaNxlu9ZhEL6CERgqNc21hJYuP3hRVzAWfBQlgO18DPmZTbrFerJC3+Ikw==", + "dependencies": { + "glob": "^8.0.1", + "js-binary-schema-parser": "^2.0.2", + "simple-get": "^4.0.1", + "string-split-by": "^1.0.0" + } + }, + "node_modules/vue-qr/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/vue-route": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/vue-route/-/vue-route-1.5.1.tgz", @@ -6101,6 +6245,11 @@ "node": ">=8" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "node_modules/xlsx": { "version": "0.18.5", "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", diff --git a/package.json b/package.json index 5b43344..c467712 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "vue-cropper": "1.1.1", "vue-cropperjs": "^5.0.0", "vue-echarts": "^6.6.9", + "vue-qr": "^4.0.9", "vue-router": "^4.2.5", "vue-schart": "^2.0.0", "xlsx": "^0.18.5" diff --git a/src/api/user.ts b/src/api/user.ts index f0fe9e9..545fd9f 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -245,7 +245,7 @@ export const getGithubLoginUrl = (Data) => { //获取第三方登录状态 export const getThirdPartyLoginStatus = (Data) => { - let url ='/user/oAuth' + "?uuid=" + Data.uuid + let url ='/user/oAuth' + "?uuid=" + Data.uuid + "&host_id=" + Data.host_id return request.get(url) } @@ -285,7 +285,41 @@ export const getTokenByCode = (Data) => { }) } +//生成totp密钥 +export const genTOTPSecret = (Data) => { + return request.get('/tool/gen_totp_secret', { + headers: { + 'token': Data.token, + } + }) +} +export const getTOTPSecretInfo = (Data) => { + return request.get('/tool/get_totp_secret_info', { + headers: { + 'token': Data.token, + } + }) +} +export const unBindTOTPSecretService = (Data) => { + return request.delete('/tool/del_totp_secret', { + headers: { + 'token': Data.token, + } + }) +} + +export const secondAuthLoginService = (Data) => { + let token = Data.token + delete Data.token + return request.post('/user/second_auth' , Data, { + headers: { + 'token': token, + 'Content-Type': 'application/json' // 设置请求头为 JSON 格式 + } + }) + +} export const fetchUserData = () => { return { "list": [ diff --git a/src/views/pages/login.vue b/src/views/pages/login.vue index 9a46ab0..abec6a8 100644 --- a/src/views/pages/login.vue +++ b/src/views/pages/login.vue @@ -109,6 +109,35 @@ + + + 请选择二次认证方式 + + + + + 输入验证码 + + + + + + + + + + @@ -122,7 +151,7 @@ import { UserToken } from "@/types/user"; import { getBrowserFingerprint,getStoredFingerprint } from "@/utils/fingerprint"; import { usePermissStore } from "@/store/permiss"; import Cookies from 'js-cookie'; -import {getThirdPartyUUID,getThirdPartyLoginStatus,getThirdPartyLoginUrl,sendLoginCode, loginByCode} from "@/api/user"; +import {getThirdPartyUUID,getThirdPartyLoginStatus,getThirdPartyLoginUrl,sendLoginCode, loginByCode, secondAuthLoginService} from "@/api/user"; import { log, time } from "console"; import { pa } from "element-plus/es/locale"; // 从本地存储获取登录参数 @@ -137,6 +166,7 @@ const countdown = ref(0); //倒计时 const router = useRouter(); const route = useRoute(); +const second_auth_visible = ref(false); //二次认证弹窗 // 登录表单数据 const param = reactive({ username: defParam ? defParam.username : "", @@ -175,6 +205,38 @@ const maxLoginRepeatRequest = 60; //最大请求次数 const currentLoginRequest = ref(0); //当前请求次数 const timer = ref(null); //定时器 +const secondAuthLogin = async () => { + if(!second_auth_method.value){ + ElMessage.error("请选择认证方式"); + return; + } + if(!second_auth_code.value){ + ElMessage.error("请输入验证码"); + return; + } + let req = { + state: second_auth_state_key.value, + type: second_auth_method.value, + code: second_auth_code.value + }; + let result = await secondAuthLoginService(req); + if (result["code"] === 0) { + ElMessage.success("登录成功"); + let userTokenInfo: UserToken = result["data"]; + globalData["token"] = result.data; + localStorage.setItem("token", userTokenInfo.access_token); + localStorage.setItem("refresh_token", userTokenInfo.refresh_token); + localStorage.setItem("userId", userTokenInfo.user_id.toString()); + localStorage.setItem("username", userTokenInfo.username); + let now = new Date(); + localStorage.setItem("end_time", (now.setDate(now.getHours())).toString()); //过期时间 + await getMyUserInfo(userTokenInfo.user_id); + }else{ + ElMessage.error(result["message"] || "登录失败!请稍后再试"); + return; + } +}; + const thirdPartyLogoInfoList = ref([ { name: "github", @@ -234,6 +296,10 @@ var loginData = ref({ fingerprint: '' // 浏览器指纹 }); const querySite =ref(""); +const second_auth_state_key = ref(""); //二次认证状态key +const second_auth_method = ref(""); +const second_auth_type_list = ref([]); +const second_auth_code = ref(""); //二次认证验证码 onMounted(async () => { let fp = await getStoredFingerprint(); @@ -291,7 +357,7 @@ const thirdLogin = async (type) => { ElMessage.error("登录超时,请重新登录!"); return; } - let statusResp = await getThirdPartyLoginStatus({uuid: uuid}); + let statusResp = await getThirdPartyLoginStatus({uuid: uuid,host_id:loginData.value.fingerprint}); if (statusResp["code"] !== 0) { ElMessage.error("获取登录状态失败!请稍后再试"); clearInterval(timer.value); @@ -408,6 +474,18 @@ const onLogin = async () => { console.log("login result:", result); if (result["code"] === 0) { ElMessage.success("登录成功"); + }else if (result["code"] == 1102) { + //需二次认证,支持方式 + second_auth_visible.value = true; + second_auth_state_key.value = result["data"]["state"]; + let types = result["data"]["type"]; + second_auth_type_list.value = types.split(","); + //删除''空值 + second_auth_type_list.value = second_auth_type_list.value.filter(item => item); + second_auth_method.value = second_auth_type_list.value[0]; + console.log("second_auth_type_list:", second_auth_type_list.value); + return; + }else if(result["code"] === 1101){ ElMessage.error(result["message"] || "该账号已被禁用,请联系管理员!"); return; diff --git a/src/views/pages/ucenter.vue b/src/views/pages/ucenter.vue index ada095b..d3a710e 100644 --- a/src/views/pages/ucenter.vue +++ b/src/views/pages/ucenter.vue @@ -109,6 +109,28 @@ + +
+

TOTP密钥

+ 生成TOTP密钥 +
+ +

使用支持TOTP的应用(如Google Authenticator、Authy等)扫描二维码或手动输入密钥进行绑定。

+

请妥善保存您的TOTP密钥,只能查看一次,若丢失请解绑后重新生成。

+ 点击复制密钥 + +
+ + + 密钥创建时间:{{ totp_secret_created_at }} + + + 解绑 + + +
+ +
@@ -121,7 +143,7 @@ import { VueCropper } from 'vue-cropper'; import 'vue-cropper/dist/index.css'; import avatar from '@/assets/img/img.jpg'; import TabsComp from '../element/tabs.vue'; -import {GetUserInfoService} from "@/api/user"; +import {GetUserInfoService, genTOTPSecret, unBindTOTPSecretService, getTOTPSecretInfo} from "@/api/user"; import { GetUserStatisticService } from "@/api/user"; import { UploadFileService } from "@/api/tool"; import { UserInfo } from '@/types/user'; @@ -133,6 +155,7 @@ import {genResetPassword} from "@/api/user"; import {updateUserInfoService} from "@/api/user"; import { useRouter } from "vue-router"; import {getThirdPartyUUID,getThirdPartyLoginStatus,getThirdPartyLoginUrl, getThirdPartyInfo, deleteThirdPartyInfo} from "@/api/user"; +import vueQr from 'vue-qr/src/packages/vue-qr.vue' const name = localStorage.getItem('ms_username'); const qqButtonBgImage = ref('https://wiki.connect.qq.com/wp-content/uploads/2016/12/Connect_logo_4.png'); @@ -147,6 +170,7 @@ const userStatistic = reactive({ total: 0, file_count: 0, }); +const gen_totp_secret = ref(false); const userInfo = ref(); const isUserInfoLoaded = ref(false); const globalData = inject("globalData"); @@ -160,6 +184,9 @@ const cropImg = ref(''); const cropper: any = ref(); const maxLoginRepeatRequest = 60; //最大请求次数 const currentLoginRequest = ref(0); //当前请求次数 +const totp_secret = ref(''); +const totp_url = ref(''); +const totp_secret_created_at = ref(''); const thirdPartyUserInfo = ref([]); @@ -174,7 +201,74 @@ const thirdPartyPlatform = ref([ { label: "Gitea自建", value: "my_gitea"}, { label: "Microsoft", value: "microsoft"} ]); +const onCopyTOTPSecret = () => { + navigator.clipboard.writeText(totp_secret.value).then(() => { + ElMessage.success('复制成功!'); + }).catch(() => { + ElMessage.error('复制失败,请手动复制'); + }); +}; +const unBindTOTPSecret =async () => { + let req = { + token: localStorage.getItem('token'), + }; + try{ + let result = await unBindTOTPSecretService(req); + if (result["code"] == 0) { + ElMessage.success("解绑成功"); + totp_secret.value = ''; + totp_url.value = ''; + totp_secret_created_at.value = ''; + gen_totp_secret.value = false; + }else{ + ElMessage.error(result["msg"]); + } + }catch(e){ + console.log(e); + } +} + +const GenTOTPSecret = async () => { + let req = { + token: localStorage.getItem('token'), + }; + try{ + let result = await genTOTPSecret(req); + if (result["code"] == 0) { + totp_secret.value = result["data"]["secret"]; + totp_url.value = result["data"]["url"]; + gen_totp_secret.value = true; + ElMessage.success("TOTP密钥生成成功,请妥善保存,建议使用Google Authenticator等支持TOTP的应用扫码保存,只能查询一次"); + //生成显示二维码 + }else{ + ElMessage.error(result["msg"]); + } + }catch(e){ + console.log(e); + } +}; + +const GetTOTPSecret = async () => { + let req = { + token: localStorage.getItem('token'), + }; + try{ + let result = await getTOTPSecretInfo(req); + if (result["code"] == 0) { + if (result["data"]["ID"] != 0) { + totp_secret_created_at.value = result["data"]["CreatedAt"]; + gen_totp_secret.value = true; + } + }else{ + ElMessage.error(result["msg"]); + } + }catch(e){ + console.log(e); + } +}; + +GetTOTPSecret(); const reset_password = () => { localStorage.removeItem("ms_username"); diff --git a/yarn.lock b/yarn.lock index c837c5f..0e3d563 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1821,6 +1821,13 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + deepmerge@^1.2.0: version "1.5.2" resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz" @@ -2143,6 +2150,11 @@ frac@~1.1.2: resolved "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz" integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -2167,6 +2179,17 @@ glob@^10.4.2: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" +glob@^8.0.1: + version "8.1.0" + resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + globals@^15.14.0: version "15.15.0" resolved "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz" @@ -2239,6 +2262,19 @@ immer@^9.0.6: resolved "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz" integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + ini@^1.3.4: version "1.3.8" resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" @@ -2335,6 +2371,11 @@ js-beautify@^1.14.9: js-cookie "^3.0.5" nopt "^7.2.1" +js-binary-schema-parser@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz" + integrity sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg== + js-cookie@^3.0.5: version "3.0.5" resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz" @@ -2960,7 +3001,12 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" -minimatch@^5.1.1: +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimatch@^5.0.1, minimatch@^5.1.1: version "5.1.6" resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== @@ -3058,6 +3104,13 @@ nprogress@^0.2.0: resolved "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz" integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== +once@^1.3.0, once@^1.3.1: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + package-json-from-dist@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz" @@ -3077,6 +3130,11 @@ page@^1.5.0: dependencies: path-to-regexp "~1.2.1" +parenthesis@^3.1.5: + version "3.1.8" + resolved "https://registry.npmjs.org/parenthesis/-/parenthesis-3.1.8.tgz" + integrity sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw== + path-data-parser@^0.1.0, path-data-parser@0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz" @@ -3360,6 +3418,20 @@ signal-exit@^4.0.1: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + slate-history@^0.66.0: version "0.66.0" resolved "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz" @@ -3416,6 +3488,13 @@ ssr-window@^3.0.0-alpha.1: resolved "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz" integrity sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA== +string-split-by@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/string-split-by/-/string-split-by-1.0.0.tgz" + integrity sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A== + dependencies: + parenthesis "^3.1.5" + "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -3762,6 +3841,16 @@ vue-echarts@^6.6.9: resize-detector "^0.3.0" vue-demi "^0.13.11" +vue-qr@^4.0.9: + version "4.0.9" + resolved "https://registry.npmjs.org/vue-qr/-/vue-qr-4.0.9.tgz" + integrity sha512-pAISV94T0MNEYA3NGjykUpsXRE2QfaNxlu9ZhEL6CERgqNc21hJYuP3hRVzAWfBQlgO18DPmZTbrFerJC3+Ikw== + dependencies: + glob "^8.0.1" + js-binary-schema-parser "^2.0.2" + simple-get "^4.0.1" + string-split-by "^1.0.0" + vue-route@^1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/vue-route/-/vue-route-1.5.1.tgz" @@ -3874,6 +3963,11 @@ wrap-ansi@^8.1.0: string-width "^5.0.1" strip-ansi "^7.0.1" +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + xlsx@^0.18.5: version "0.18.5" resolved "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz"