abab2320 3 weeks ago
parent b796dab689
commit 990ffb8886

@ -25,9 +25,15 @@
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.7.0", "@vue/tsconfig": "^0.7.0",
"msw": "^2.8.6",
"sass-embedded": "^1.88.0", "sass-embedded": "^1.88.0",
"typescript": "~5.7.2", "typescript": "~5.7.2",
"vite": "^6.2.0", "vite": "^6.2.0",
"vue-tsc": "^2.2.4" "vue-tsc": "^2.2.4"
},
"msw": {
"workerDirectory": [
"public"
]
} }
} }

@ -51,6 +51,9 @@ importers:
'@vue/tsconfig': '@vue/tsconfig':
specifier: ^0.7.0 specifier: ^0.7.0
version: 0.7.0(typescript@5.7.3)(vue@3.5.13(typescript@5.7.3)) version: 0.7.0(typescript@5.7.3)(vue@3.5.13(typescript@5.7.3))
msw:
specifier: ^2.8.6
version: 2.8.6(typescript@5.7.3)
sass-embedded: sass-embedded:
specifier: ^1.88.0 specifier: ^1.88.0
version: 1.88.0 version: 1.88.0
@ -86,6 +89,15 @@ packages:
'@bufbuild/protobuf@2.4.0': '@bufbuild/protobuf@2.4.0':
resolution: {integrity: sha512-RN9M76x7N11QRihKovEglEjjVCQEA9PRBVnDgk9xw8JHLrcUrp4FpAVSPSH91cNbcTft3u2vpLN4GMbiKY9PJw==} resolution: {integrity: sha512-RN9M76x7N11QRihKovEglEjjVCQEA9PRBVnDgk9xw8JHLrcUrp4FpAVSPSH91cNbcTft3u2vpLN4GMbiKY9PJw==}
'@bundled-es-modules/cookie@2.0.1':
resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==}
'@bundled-es-modules/statuses@1.0.1':
resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==}
'@bundled-es-modules/tough-cookie@0.1.6':
resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==}
'@ctrl/tinycolor@3.6.1': '@ctrl/tinycolor@3.6.1':
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -254,9 +266,53 @@ packages:
'@floating-ui/utils@0.2.9': '@floating-ui/utils@0.2.9':
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
'@inquirer/confirm@5.1.12':
resolution: {integrity: sha512-dpq+ielV9/bqgXRUbNH//KsY6WEw9DrGPmipkpmgC1Y46cwuBTNx7PXFWTjc3MQ+urcc0QxoVHcMI0FW4Ok0hg==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/core@10.1.13':
resolution: {integrity: sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/figures@1.0.12':
resolution: {integrity: sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ==}
engines: {node: '>=18'}
'@inquirer/type@3.0.7':
resolution: {integrity: sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@jridgewell/sourcemap-codec@1.5.0': '@jridgewell/sourcemap-codec@1.5.0':
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
'@mswjs/interceptors@0.38.7':
resolution: {integrity: sha512-Jkb27iSn7JPdkqlTqKfhncFfnEZsIJVYxsFbUSWEkxdIPdsyngrhoDBk0/BGD2FQcRH99vlRrkHpNTyKqI+0/w==}
engines: {node: '>=18'}
'@open-draft/deferred-promise@2.2.0':
resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==}
'@open-draft/logger@0.3.0':
resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==}
'@open-draft/until@2.1.0':
resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==}
'@rollup/rollup-android-arm-eabi@4.35.0': '@rollup/rollup-android-arm-eabi@4.35.0':
resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==} resolution: {integrity: sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==}
cpu: [arm] cpu: [arm]
@ -355,6 +411,9 @@ packages:
'@sxzz/popperjs-es@2.11.7': '@sxzz/popperjs-es@2.11.7':
resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
'@types/cookie@0.6.0':
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
'@types/estree@1.0.6': '@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
@ -364,6 +423,12 @@ packages:
'@types/lodash@4.17.16': '@types/lodash@4.17.16':
resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==}
'@types/statuses@2.0.5':
resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==}
'@types/tough-cookie@4.0.5':
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
'@types/trusted-types@2.0.7': '@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
@ -461,6 +526,18 @@ packages:
alien-signals@1.0.4: alien-signals@1.0.4:
resolution: {integrity: sha512-DJqqQD3XcsaQcQ1s+iE2jDUZmmQpXwHiR6fCAim/w87luaW+vmLY8fMlrdkmRwzaFXhkxf3rqPCR59tKVv1MDw==} resolution: {integrity: sha512-DJqqQD3XcsaQcQ1s+iE2jDUZmmQpXwHiR6fCAim/w87luaW+vmLY8fMlrdkmRwzaFXhkxf3rqPCR59tKVv1MDw==}
ansi-escapes@4.3.2:
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
engines: {node: '>=8'}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
async-validator@4.2.5: async-validator@4.2.5:
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
@ -486,6 +563,21 @@ packages:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
cli-width@4.1.0:
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
engines: {node: '>= 12'}
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
colorjs.io@0.5.2: colorjs.io@0.5.2:
resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
@ -493,6 +585,10 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
cookie@0.7.2:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'}
copy-anything@3.0.5: copy-anything@3.0.5:
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
engines: {node: '>=12.13'} engines: {node: '>=12.13'}
@ -522,6 +618,9 @@ packages:
peerDependencies: peerDependencies:
vue: ^3.2.0 vue: ^3.2.0
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
entities@4.5.0: entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@ -547,6 +646,10 @@ packages:
engines: {node: '>=18'} engines: {node: '>=18'}
hasBin: true hasBin: true
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
escape-html@1.0.3: escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
@ -574,6 +677,10 @@ packages:
function-bind@1.1.2: function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
get-intrinsic@1.3.0: get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -586,6 +693,10 @@ packages:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
graphql@16.11.0:
resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==}
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
has-flag@4.0.0: has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -606,6 +717,9 @@ packages:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true hasBin: true
headers-polyfill@4.0.3:
resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==}
highlight.js@11.11.1: highlight.js@11.11.1:
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
@ -616,6 +730,13 @@ packages:
immutable@5.1.2: immutable@5.1.2:
resolution: {integrity: sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==} resolution: {integrity: sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==}
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
is-node-process@1.2.0:
resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==}
is-what@4.1.16: is-what@4.1.16:
resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
engines: {node: '>=12.13'} engines: {node: '>=12.13'}
@ -668,9 +789,23 @@ packages:
mitt@3.0.1: mitt@3.0.1:
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
msw@2.8.6:
resolution: {integrity: sha512-fpwS5PnENnf7q7VF2ev00yfzmNXW78McKNgyaHaXQgz7p9pV8b2qQx1FoI0QA4BOxaVGBB6zBQUV4QWaK3G40g==}
engines: {node: '>=18'}
hasBin: true
peerDependencies:
typescript: '>= 4.8.x'
peerDependenciesMeta:
typescript:
optional: true
muggle-string@0.4.1: muggle-string@0.4.1:
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
mute-stream@2.0.0:
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
engines: {node: ^18.17.0 || >=20.5.0}
nanoid@3.3.9: nanoid@3.3.9:
resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@ -679,9 +814,15 @@ packages:
normalize-wheel-es@1.2.0: normalize-wheel-es@1.2.0:
resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
outvariant@1.4.3:
resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==}
path-browserify@1.0.1: path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
path-to-regexp@6.3.0:
resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
perfect-debounce@1.0.0: perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
@ -698,6 +839,23 @@ packages:
proxy-from-env@1.1.0: proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
psl@1.15.0:
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
rfdc@1.4.1: rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
@ -834,6 +992,10 @@ packages:
engines: {node: '>=16.0.0'} engines: {node: '>=16.0.0'}
hasBin: true hasBin: true
signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
source-map-js@1.2.1: source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -842,6 +1004,21 @@ packages:
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
statuses@2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
strict-event-emitter@0.5.1:
resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
superjson@2.2.2: superjson@2.2.2:
resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==}
engines: {node: '>=16'} engines: {node: '>=16'}
@ -864,9 +1041,17 @@ packages:
toposort@2.0.2: toposort@2.0.2:
resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==}
tough-cookie@4.1.4:
resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
engines: {node: '>=6'}
tslib@2.8.1: tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
type-fest@0.21.3:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
type-fest@2.19.0: type-fest@2.19.0:
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
engines: {node: '>=12.20'} engines: {node: '>=12.20'}
@ -880,6 +1065,13 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
universalify@0.2.0:
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
engines: {node: '>= 4.0.0'}
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
varint@6.0.0: varint@6.0.0:
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
@ -961,6 +1153,30 @@ packages:
typescript: typescript:
optional: true optional: true
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
yargs@17.7.2:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
yoctocolors-cjs@2.1.2:
resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
engines: {node: '>=18'}
yup@1.6.1: yup@1.6.1:
resolution: {integrity: sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==} resolution: {integrity: sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==}
@ -981,6 +1197,19 @@ snapshots:
'@bufbuild/protobuf@2.4.0': {} '@bufbuild/protobuf@2.4.0': {}
'@bundled-es-modules/cookie@2.0.1':
dependencies:
cookie: 0.7.2
'@bundled-es-modules/statuses@1.0.1':
dependencies:
statuses: 2.0.1
'@bundled-es-modules/tough-cookie@0.1.6':
dependencies:
'@types/tough-cookie': 4.0.5
tough-cookie: 4.1.4
'@ctrl/tinycolor@3.6.1': {} '@ctrl/tinycolor@3.6.1': {}
'@element-plus/icons-vue@2.3.1(vue@3.5.13(typescript@5.7.3))': '@element-plus/icons-vue@2.3.1(vue@3.5.13(typescript@5.7.3))':
@ -1073,8 +1302,46 @@ snapshots:
'@floating-ui/utils@0.2.9': {} '@floating-ui/utils@0.2.9': {}
'@inquirer/confirm@5.1.12':
dependencies:
'@inquirer/core': 10.1.13
'@inquirer/type': 3.0.7
'@inquirer/core@10.1.13':
dependencies:
'@inquirer/figures': 1.0.12
'@inquirer/type': 3.0.7
ansi-escapes: 4.3.2
cli-width: 4.1.0
mute-stream: 2.0.0
signal-exit: 4.1.0
wrap-ansi: 6.2.0
yoctocolors-cjs: 2.1.2
'@inquirer/figures@1.0.12': {}
'@inquirer/type@3.0.7': {}
'@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/sourcemap-codec@1.5.0': {}
'@mswjs/interceptors@0.38.7':
dependencies:
'@open-draft/deferred-promise': 2.2.0
'@open-draft/logger': 0.3.0
'@open-draft/until': 2.1.0
is-node-process: 1.2.0
outvariant: 1.4.3
strict-event-emitter: 0.5.1
'@open-draft/deferred-promise@2.2.0': {}
'@open-draft/logger@0.3.0':
dependencies:
is-node-process: 1.2.0
outvariant: 1.4.3
'@open-draft/until@2.1.0': {}
'@rollup/rollup-android-arm-eabi@4.35.0': '@rollup/rollup-android-arm-eabi@4.35.0':
optional: true optional: true
@ -1134,6 +1401,8 @@ snapshots:
'@sxzz/popperjs-es@2.11.7': {} '@sxzz/popperjs-es@2.11.7': {}
'@types/cookie@0.6.0': {}
'@types/estree@1.0.6': {} '@types/estree@1.0.6': {}
'@types/lodash-es@4.17.12': '@types/lodash-es@4.17.12':
@ -1142,6 +1411,10 @@ snapshots:
'@types/lodash@4.17.16': {} '@types/lodash@4.17.16': {}
'@types/statuses@2.0.5': {}
'@types/tough-cookie@4.0.5': {}
'@types/trusted-types@2.0.7': '@types/trusted-types@2.0.7':
optional: true optional: true
@ -1282,6 +1555,16 @@ snapshots:
alien-signals@1.0.4: {} alien-signals@1.0.4: {}
ansi-escapes@4.3.2:
dependencies:
type-fest: 0.21.3
ansi-regex@5.0.1: {}
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
async-validator@4.2.5: {} async-validator@4.2.5: {}
asynckit@0.4.0: {} asynckit@0.4.0: {}
@ -1309,12 +1592,28 @@ snapshots:
es-errors: 1.3.0 es-errors: 1.3.0
function-bind: 1.1.2 function-bind: 1.1.2
cli-width@4.1.0: {}
cliui@8.0.1:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
colorjs.io@0.5.2: {} colorjs.io@0.5.2: {}
combined-stream@1.0.8: combined-stream@1.0.8:
dependencies: dependencies:
delayed-stream: 1.0.0 delayed-stream: 1.0.0
cookie@0.7.2: {}
copy-anything@3.0.5: copy-anything@3.0.5:
dependencies: dependencies:
is-what: 4.1.16 is-what: 4.1.16
@ -1358,6 +1657,8 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
emoji-regex@8.0.0: {}
entities@4.5.0: {} entities@4.5.0: {}
es-define-property@1.0.1: {} es-define-property@1.0.1: {}
@ -1403,6 +1704,8 @@ snapshots:
'@esbuild/win32-ia32': 0.25.1 '@esbuild/win32-ia32': 0.25.1
'@esbuild/win32-x64': 0.25.1 '@esbuild/win32-x64': 0.25.1
escalade@3.2.0: {}
escape-html@1.0.3: {} escape-html@1.0.3: {}
estree-walker@2.0.2: {} estree-walker@2.0.2: {}
@ -1421,6 +1724,8 @@ snapshots:
function-bind@1.1.2: {} function-bind@1.1.2: {}
get-caller-file@2.0.5: {}
get-intrinsic@1.3.0: get-intrinsic@1.3.0:
dependencies: dependencies:
call-bind-apply-helpers: 1.0.2 call-bind-apply-helpers: 1.0.2
@ -1441,6 +1746,8 @@ snapshots:
gopd@1.2.0: {} gopd@1.2.0: {}
graphql@16.11.0: {}
has-flag@4.0.0: {} has-flag@4.0.0: {}
has-symbols@1.1.0: {} has-symbols@1.1.0: {}
@ -1455,12 +1762,18 @@ snapshots:
he@1.2.0: {} he@1.2.0: {}
headers-polyfill@4.0.3: {}
highlight.js@11.11.1: {} highlight.js@11.11.1: {}
hookable@5.5.3: {} hookable@5.5.3: {}
immutable@5.1.2: {} immutable@5.1.2: {}
is-fullwidth-code-point@3.0.0: {}
is-node-process@1.2.0: {}
is-what@4.1.16: {} is-what@4.1.16: {}
lodash-es@4.17.21: {} lodash-es@4.17.21: {}
@ -1499,14 +1812,45 @@ snapshots:
mitt@3.0.1: {} mitt@3.0.1: {}
msw@2.8.6(typescript@5.7.3):
dependencies:
'@bundled-es-modules/cookie': 2.0.1
'@bundled-es-modules/statuses': 1.0.1
'@bundled-es-modules/tough-cookie': 0.1.6
'@inquirer/confirm': 5.1.12
'@mswjs/interceptors': 0.38.7
'@open-draft/deferred-promise': 2.2.0
'@open-draft/until': 2.1.0
'@types/cookie': 0.6.0
'@types/statuses': 2.0.5
graphql: 16.11.0
headers-polyfill: 4.0.3
is-node-process: 1.2.0
outvariant: 1.4.3
path-to-regexp: 6.3.0
picocolors: 1.1.1
strict-event-emitter: 0.5.1
type-fest: 4.37.0
yargs: 17.7.2
optionalDependencies:
typescript: 5.7.3
transitivePeerDependencies:
- '@types/node'
muggle-string@0.4.1: {} muggle-string@0.4.1: {}
mute-stream@2.0.0: {}
nanoid@3.3.9: {} nanoid@3.3.9: {}
normalize-wheel-es@1.2.0: {} normalize-wheel-es@1.2.0: {}
outvariant@1.4.3: {}
path-browserify@1.0.1: {} path-browserify@1.0.1: {}
path-to-regexp@6.3.0: {}
perfect-debounce@1.0.0: {} perfect-debounce@1.0.0: {}
picocolors@1.1.1: {} picocolors@1.1.1: {}
@ -1521,6 +1865,18 @@ snapshots:
proxy-from-env@1.1.0: {} proxy-from-env@1.1.0: {}
psl@1.15.0:
dependencies:
punycode: 2.3.1
punycode@2.3.1: {}
querystringify@2.2.0: {}
require-directory@2.1.1: {}
requires-port@1.0.0: {}
rfdc@1.4.1: {} rfdc@1.4.1: {}
rollup@4.35.0: rollup@4.35.0:
@ -1644,10 +2000,26 @@ snapshots:
sass-embedded-win32-ia32: 1.88.0 sass-embedded-win32-ia32: 1.88.0
sass-embedded-win32-x64: 1.88.0 sass-embedded-win32-x64: 1.88.0
signal-exit@4.1.0: {}
source-map-js@1.2.1: {} source-map-js@1.2.1: {}
speakingurl@14.0.1: {} speakingurl@14.0.1: {}
statuses@2.0.1: {}
strict-event-emitter@0.5.1: {}
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
superjson@2.2.2: superjson@2.2.2:
dependencies: dependencies:
copy-anything: 3.0.5 copy-anything: 3.0.5
@ -1666,14 +2038,30 @@ snapshots:
toposort@2.0.2: {} toposort@2.0.2: {}
tough-cookie@4.1.4:
dependencies:
psl: 1.15.0
punycode: 2.3.1
universalify: 0.2.0
url-parse: 1.5.10
tslib@2.8.1: {} tslib@2.8.1: {}
type-fest@0.21.3: {}
type-fest@2.19.0: {} type-fest@2.19.0: {}
type-fest@4.37.0: {} type-fest@4.37.0: {}
typescript@5.7.3: {} typescript@5.7.3: {}
universalify@0.2.0: {}
url-parse@1.5.10:
dependencies:
querystringify: 2.2.0
requires-port: 1.0.0
varint@6.0.0: {} varint@6.0.0: {}
vee-validate@4.15.0(vue@3.5.13(typescript@5.7.3)): vee-validate@4.15.0(vue@3.5.13(typescript@5.7.3)):
@ -1718,6 +2106,34 @@ snapshots:
optionalDependencies: optionalDependencies:
typescript: 5.7.3 typescript: 5.7.3
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
y18n@5.0.8: {}
yargs-parser@21.1.1: {}
yargs@17.7.2:
dependencies:
cliui: 8.0.1
escalade: 3.2.0
get-caller-file: 2.0.5
require-directory: 2.1.1
string-width: 4.2.3
y18n: 5.0.8
yargs-parser: 21.1.1
yoctocolors-cjs@2.1.2: {}
yup@1.6.1: yup@1.6.1:
dependencies: dependencies:
property-expr: 2.0.6 property-expr: 2.0.6

@ -0,0 +1,307 @@
/* eslint-disable */
/* tslint:disable */
/**
* Mock Service Worker.
* @see https://github.com/mswjs/msw
* - Please do NOT modify this file.
* - Please do NOT serve this file on production.
*/
const PACKAGE_VERSION = '2.8.6'
const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f'
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const activeClientIds = new Set()
self.addEventListener('install', function () {
self.skipWaiting()
})
self.addEventListener('activate', function (event) {
event.waitUntil(self.clients.claim())
})
self.addEventListener('message', async function (event) {
const clientId = event.source.id
if (!clientId || !self.clients) {
return
}
const client = await self.clients.get(clientId)
if (!client) {
return
}
const allClients = await self.clients.matchAll({
type: 'window',
})
switch (event.data) {
case 'KEEPALIVE_REQUEST': {
sendToClient(client, {
type: 'KEEPALIVE_RESPONSE',
})
break
}
case 'INTEGRITY_CHECK_REQUEST': {
sendToClient(client, {
type: 'INTEGRITY_CHECK_RESPONSE',
payload: {
packageVersion: PACKAGE_VERSION,
checksum: INTEGRITY_CHECKSUM,
},
})
break
}
case 'MOCK_ACTIVATE': {
activeClientIds.add(clientId)
sendToClient(client, {
type: 'MOCKING_ENABLED',
payload: {
client: {
id: client.id,
frameType: client.frameType,
},
},
})
break
}
case 'MOCK_DEACTIVATE': {
activeClientIds.delete(clientId)
break
}
case 'CLIENT_CLOSED': {
activeClientIds.delete(clientId)
const remainingClients = allClients.filter((client) => {
return client.id !== clientId
})
// Unregister itself when there are no more clients
if (remainingClients.length === 0) {
self.registration.unregister()
}
break
}
}
})
self.addEventListener('fetch', function (event) {
const { request } = event
// Bypass navigation requests.
if (request.mode === 'navigate') {
return
}
// Opening the DevTools triggers the "only-if-cached" request
// that cannot be handled by the worker. Bypass such requests.
if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') {
return
}
// Bypass all requests when there are no active clients.
// Prevents the self-unregistered worked from handling requests
// after it's been deleted (still remains active until the next reload).
if (activeClientIds.size === 0) {
return
}
// Generate unique request ID.
const requestId = crypto.randomUUID()
event.respondWith(handleRequest(event, requestId))
})
async function handleRequest(event, requestId) {
const client = await resolveMainClient(event)
const response = await getResponse(event, client, requestId)
// Send back the response clone for the "response:*" life-cycle events.
// Ensure MSW is active and ready to handle the message, otherwise
// this message will pend indefinitely.
if (client && activeClientIds.has(client.id)) {
;(async function () {
const responseClone = response.clone()
sendToClient(
client,
{
type: 'RESPONSE',
payload: {
requestId,
isMockedResponse: IS_MOCKED_RESPONSE in response,
type: responseClone.type,
status: responseClone.status,
statusText: responseClone.statusText,
body: responseClone.body,
headers: Object.fromEntries(responseClone.headers.entries()),
},
},
[responseClone.body],
)
})()
}
return response
}
// Resolve the main client for the given event.
// Client that issues a request doesn't necessarily equal the client
// that registered the worker. It's with the latter the worker should
// communicate with during the response resolving phase.
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId)
if (activeClientIds.has(event.clientId)) {
return client
}
if (client?.frameType === 'top-level') {
return client
}
const allClients = await self.clients.matchAll({
type: 'window',
})
return allClients
.filter((client) => {
// Get only those clients that are currently visible.
return client.visibilityState === 'visible'
})
.find((client) => {
// Find the client ID that's recorded in the
// set of clients that have registered the worker.
return activeClientIds.has(client.id)
})
}
async function getResponse(event, client, requestId) {
const { request } = event
// Clone the request because it might've been already used
// (i.e. its body has been read and sent to the client).
const requestClone = request.clone()
function passthrough() {
// Cast the request headers to a new Headers instance
// so the headers can be manipulated with.
const headers = new Headers(requestClone.headers)
// Remove the "accept" header value that marked this request as passthrough.
// This prevents request alteration and also keeps it compliant with the
// user-defined CORS policies.
const acceptHeader = headers.get('accept')
if (acceptHeader) {
const values = acceptHeader.split(',').map((value) => value.trim())
const filteredValues = values.filter(
(value) => value !== 'msw/passthrough',
)
if (filteredValues.length > 0) {
headers.set('accept', filteredValues.join(', '))
} else {
headers.delete('accept')
}
}
return fetch(requestClone, { headers })
}
// Bypass mocking when the client is not active.
if (!client) {
return passthrough()
}
// Bypass initial page load requests (i.e. static assets).
// The absence of the immediate/parent client in the map of the active clients
// means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
// and is not ready to handle requests.
if (!activeClientIds.has(client.id)) {
return passthrough()
}
// Notify the client that a request has been intercepted.
const requestBuffer = await request.arrayBuffer()
const clientMessage = await sendToClient(
client,
{
type: 'REQUEST',
payload: {
id: requestId,
url: request.url,
mode: request.mode,
method: request.method,
headers: Object.fromEntries(request.headers.entries()),
cache: request.cache,
credentials: request.credentials,
destination: request.destination,
integrity: request.integrity,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
body: requestBuffer,
keepalive: request.keepalive,
},
},
[requestBuffer],
)
switch (clientMessage.type) {
case 'MOCK_RESPONSE': {
return respondWithMock(clientMessage.data)
}
case 'PASSTHROUGH': {
return passthrough()
}
}
return passthrough()
}
function sendToClient(client, message, transferrables = []) {
return new Promise((resolve, reject) => {
const channel = new MessageChannel()
channel.port1.onmessage = (event) => {
if (event.data && event.data.error) {
return reject(event.data.error)
}
resolve(event.data)
}
client.postMessage(
message,
[channel.port2].concat(transferrables.filter(Boolean)),
)
})
}
async function respondWithMock(response) {
// Setting response status code to 0 is a no-op.
// However, when responding with a "Response.error()", the produced Response
// instance will have status code set to 0. Since it's not possible to create
// a Response instance with status code 0, handle that use-case separately.
if (response.status === 0) {
return Response.error()
}
const mockedResponse = new Response(response.body, response)
Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
value: true,
enumerable: true,
})
return mockedResponse
}

@ -1,11 +1,17 @@
<script setup> <script setup>
import { House, Cloudy, User, Cpu, Message, HomeFilled, MessageBox, Calendar } from '@element-plus/icons-vue' import { House, Cloudy, User, Cpu, Message, HomeFilled, MessageBox, Calendar } from '@element-plus/icons-vue'
import {useRoute,useRouter } from 'vue-router' import {useRoute,useRouter } from 'vue-router'
import { hasToken } from '@/utils/token';
import { ref } from 'vue' import { ref } from 'vue'
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const searchText = ref('') const searchText = ref('')
const isLogin = hasToken(); //
const userInfoStr = localStorage.getItem('userInfo');
const userInfo = userInfoStr ? JSON.parse(userInfoStr) : null;
const userAvatar = userInfo?.avatar;
function goSearch() { function goSearch() {
if (searchText.value.trim()) { if (searchText.value.trim()) {
@ -64,17 +70,20 @@
<router-link to="/personal" class="user-entry" title="个人主页"> <router-link to="/personal" class="user-entry" title="个人主页">
<span>个人主页</span> <span>个人主页</span>
</router-link> </router-link>
<div v-if="!isLogin">
<router-link to="/log" class="icon-btn" title="登录"> <router-link to="/log" class="icon-btn" title="登录">
<el-icon class = "icon-btn" :size="24"> <el-icon class = "icon-btn" :size="24">
<User /> <User />
</el-icon> </el-icon>
</router-link> </router-link>
</div> </div>
<div v-else>
<img :src="userAvatar" alt="User Avatar" class="user-avatar" />
</div>
</div>
</header> </header>
</template> </template>
<style scoped> <style scoped>
.header-bar { .header-bar {
height: 70px; height: 70px;
@ -137,40 +146,11 @@
object-fit: cover; object-fit: cover;
} }
.header-search { .user-avatar {
display: flex; width: 40px;
align-items: center; height: 40px;
margin-left: 16px; border-radius: 50%;
} object-fit: cover;
margin-left: 10px;
.header-search input {
width: 180px;
padding: 6px 10px;
font-size: 14px;
border-radius: 4px 0 0 4px;
border: 1px solid #ccc;
outline: none;
transition: border-color 0.2s;
}
.header-search input:focus {
border-color: #765ce6;
}
.header-search button {
padding: 6px 12px;
border: none;
background-color: #765ce6;
color: white;
font-weight: 600;
cursor: pointer;
border-radius: 0 4px 4px 0;
transition: background-color 0.2s;
user-select: none;
}
.header-search button:hover {
background-color: #5a42b8;
} }
</style> </style>

@ -6,11 +6,29 @@ import 'element-plus/dist/index.css'
import router from './routers/routers' import router from './routers/routers'
import * as ElementPlusIconsVue from '@element-plus/icons-vue' import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
app.use(ElementPlus) async function prepareApp() {
app.use(router) if (import.meta.env.DEV) {
for(const [key, component] of Object.entries(ElementPlusIconsVue)) { const { worker } = await import('./mocks/browser');
app.component(key, component) await worker.start(); // 确保 MSW 启动完成
}
const app = createApp(App);
app.use(router);
app.use(ElementPlus);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component);
}
app.mount('#app');
} }
app.mount('#app')
prepareApp();
// const app = createApp(App)
// app.use(ElementPlus)
// app.use(router)
// for(const [key, component] of Object.entries(ElementPlusIconsVue)) {
// app.component(key, component)
// }
// app.mount('#app')

@ -0,0 +1,4 @@
import { setupWorker } from 'msw/browser';
import { handlers } from './handlers.ts';
export const worker = setupWorker(...handlers);

@ -0,0 +1,116 @@
import { http,HttpResponse } from 'msw';
import Avatar from '@/assets/images/默认头像.jpg'
import { Briefcase } from '@element-plus/icons-vue';
let mockUserData = {
userId: 1,
username: '测试员',
email: "test@example.com",
nickname: '测试员',
avatar: Avatar,
bio:"只要不出bug一切都好QAQ",
gender:'1',
birthday: '2000-01-01',
studentId:20220101001,
department: "计算机学院",
major: "软件工程",
grade: "2023级",
points: 100,
role: 0,
status:1,
isVerified: true,
};
export const handlers = [
http.post('/users/login', async ({request}) => {
const body = await request.json() as { data: { username: string; password: string } };
if (body.data.username === 'test@example.com' && body.data.password === '123456') {
return HttpResponse.json({
code: 200,
message: '登录成功',
data: {
token: 'mock-jwt-token-123',
userInfo: {
userId: mockUserData.userId,
username: mockUserData.username,
nickname: mockUserData.nickname,
avatar: mockUserData.avatar,
role: mockUserData.role,
isVerified: mockUserData.isVerified,
status: mockUserData.status,
}
}
});
}
return HttpResponse.json({ message: '用户名或密码错误' }, { status: 401 });
}),
//3.1获取用户个人信息
http.get('/users/info', async ({ request }) => {
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (token === 'mock-jwt-token-123') {
return HttpResponse.json({
code: 200,
message: '获取用户信息成功',
data: mockUserData,
});
}
return HttpResponse.json({ message: '未授权' }, { status: 401 });
}),
//3.2更新用户个人信息
http.put('/users/profile', async ({ request }) => {
const body = await request.json() as typeof mockUserData;
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (token === 'mock-jwt-token-123') {
// 更新 mock 数据
mockUserData = {
...mockUserData,
...body,
};
return HttpResponse.json({
code: 200,
message: '更新成功',
data: null,
});
}
return HttpResponse.json({ code: 401, message: '未授权' }, { status: 401 });
}),
//3.3修改用户密码
http.put('/users/password', async ({ request }) => {
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
if (token === 'mock-jwt-token-123') {
return HttpResponse.json({
code: 200,
message: '密码修改成功',
data: null,
});
}
return HttpResponse.json({ code: 401, message: '未授权' }, { status: 401 });
}),
//3.4上传用户头像
http.post('/users/avatar', async ({ request }) => {
const token = request.headers.get('Authorization')?.replace('Bearer ', '');
const body = await request.json() as { avatar: string };
if (token === 'mock-jwt-token-123') {
mockUserData.avatar = body.avatar;
// 模拟头像上传成功;
return HttpResponse.json({
code: 200,
message: '头像上传成功',
data: {
avatar: mockUserData.avatar,
},
});
}
return HttpResponse.json({ code: 401, message: '未授权' }, { status: 401 });
}),
];

@ -1,19 +1,20 @@
import axios from 'axios'; import axios from 'axios';
import {getToken} from '@/utils/token';
const service = axios.create({ const service = axios.create({
baseURL: 'http://localhost:8080', baseURL: '', //改成msw测试如果要测试真实的后端记得改回去
timeout: 5000 timeout: 5000
}); });
service.interceptors.request.use( service.interceptors.request.use(
config => { config => {
const token = localStorage.getItem('token'); const token = getToken();
if (token) { if (token) {
config.headers.Authorization = `Bearer ${token}`;
console.log("前端发送信息"); console.log("前端发送信息");
return config; return config;
} } else {
else console.log("没有token");
{ console.log("没有token");
return config; return config;
} }
}, },

@ -0,0 +1,17 @@
const TOKEN_KEY = 'forum_token'; // 存储 key可统一管理
export const setToken = (token: string) => {
localStorage.setItem(TOKEN_KEY, token);
};
export const getToken = (): string | null => {
return localStorage.getItem(TOKEN_KEY);
};
export const removeToken = () => {
localStorage.removeItem(TOKEN_KEY);
};
export const hasToken = (): boolean => {
return !!getToken();
};

@ -18,14 +18,22 @@ export default defineComponent({
//使ToolTip //使ToolTip
setup() { setup() {
const originData = ref({ const originData = ref({
username:"测试员", userId: '',
avatarUrl:'@/assets/images/默认头像.jpg', username: '',
gender:2, email: '',
introduction:'只要不出bug一切都好QAQ', nickname: '',
birthday:'2023-10-01', avatar: '',
email:"test@example.com", bio: '',
password:'123456', gender: '',
}) birthday: '',
studentId: '',
department: '',
major: '',
grade: '',
points: '',
role: '',
isVerified: true,
});
const formData = ref({...originData.value});// const formData = ref({...originData.value});//
// //
@ -125,7 +133,7 @@ export default defineComponent({
validationSchema:yup.object( validationSchema:yup.object(
{ {
username:yup.string().required('昵称不能为空'), username:yup.string().required('昵称不能为空'),
introduction:yup.string().required("自我介绍不能为空"), bio:yup.string().required("自我介绍不能为空"),
} }
) )
}) })
@ -210,17 +218,12 @@ export default defineComponent({
// //
async function getUserInfo() { async function getUserInfo() {
try { try {
const response = await request.get('/user/info'); const response = await request.get('/users/info');
console.log('获取用户信息成功:', response.data); console.log('获取用户信息成功:', response);
// //
originData.value.avatarUrl = response.data.avatar; originData.value = response.data;
originData.value.gender = response.data.gender; //formData
originData.value.email = response.data.email;
originData.value.introduction = response.data.bio;
originData.value.password = "123456";
originData.value.username = response.data.username;
originData.value.birthday = response.data.birthday;
formData.value = { ...originData.value }; formData.value = { ...originData.value };
} catch (error) { } catch (error) {
@ -234,13 +237,13 @@ export default defineComponent({
const res = request.put('/users/profile',{ const res = request.put('/users/profile',{
data:{ data:{
username:formData.value.username, username:formData.value.username,
bio:formData.value.introduction, bio:formData.value.bio,
gender:formData.value.gender, gender:formData.value.gender,
birthday:formData.value.birthday, birthday:formData.value.birthday,
} }
}) })
console.log("向后端发送数据成功:",formData.value); console.log("向后端发送数据成功:",formData.value);
return (await res).data; return (await res);
} }
catch(error) catch(error)
{ {
@ -342,7 +345,7 @@ export default defineComponent({
<div class="form-group"> <div class="form-group">
<label class="form-label">个人简介</label> <label class="form-label">个人简介</label>
<input type="text" class="form-input" v-model="formData.introduction" :readonly="!isEditable"> <input type="text" class="form-input" v-model="formData.bio" :readonly="!isEditable">
</div> </div>
<div class="form-group"> <div class="form-group">
@ -388,7 +391,7 @@ export default defineComponent({
<div class="form-group"> <div class="form-group">
<label class="form-label">修改密码</label> <label class="form-label">修改密码</label>
<div class="password-inputs" v-if = "!PasswordEdit"> <div class="password-inputs" v-if = "!PasswordEdit">
<input type="password" class="form-input" v-model = "formData.password" readonly> <input type="password" class="form-input" v-model = "formData.email" readonly>
</div> </div>
<div class = "password-inputs" v-if = "PasswordEdit"> <div class = "password-inputs" v-if = "PasswordEdit">
<input type="password" class="form-input" v-model = "newpassword" placeholder="新密码"/> <input type="password" class="form-input" v-model = "newpassword" placeholder="新密码"/>
@ -413,7 +416,7 @@ export default defineComponent({
<div class="card profile-preview-card"> <div class="card profile-preview-card">
<div class="preview-section"> <div class="preview-section">
<div class="avatar-wrapper" @click = "handleAvatarClick" @mouseenter = "hover = true" @mouseleave = "hover = false"> <div class="avatar-wrapper" @click = "handleAvatarClick" @mouseenter = "hover = true" @mouseleave = "hover = false">
<img :src="originData.avatarUrl" alt="用户头像" class = "avatar-image"> <img :src="originData.avatar" alt="用户头像" class = "avatar-image">
<div v-if = "hover" class = "avatar-hover-mask">更换头像</div> <div v-if = "hover" class = "avatar-hover-mask">更换头像</div>
</div> </div>
@ -442,7 +445,7 @@ export default defineComponent({
<p class="preview-email">{{ formData.email }}</p> <p class="preview-email">{{ formData.email }}</p>
<div class="preview-bio"> <div class="preview-bio">
{{ formData.introduction }} {{ formData.bio }}
</div> </div>
</div> </div>

@ -5,6 +5,7 @@ import {useRouter} from 'vue-router'
import { useField, useForm, } from 'vee-validate' import { useField, useForm, } from 'vee-validate'
import { ref } from 'vue' import { ref } from 'vue'
import { computed } from 'vue' import { computed } from 'vue'
import { setToken } from '@/utils/token'
const token = ref<string>('') const token = ref<string>('')
const router = useRouter() const router = useRouter()
@ -108,11 +109,11 @@ const onRegisterSubmit = () => {
RegisterForm.handleSubmit((values) => { RegisterForm.handleSubmit((values) => {
console.log('表单调用成功',values) console.log('表单调用成功',values)
testcode().then((res) => { testcode().then((res) => {
if(res.code === 200) { if(res.data.code === 200) {
register().then((res) => { register().then((res) => {
if(res.code === 200) { if(res.data.code === 200) {
console.log('注册成功') console.log('注册成功')
localStorage.setItem('token', res.data.token) setToken(res.data.token);
router.push({path:'/personal'}) router.push({path:'/personal'})
} else { } else {
console.log('注册失败') console.log('注册失败')
@ -135,20 +136,17 @@ const onLoginSubmit = () => {
RegisterForm.resetForm(); RegisterForm.resetForm();
LoginPasswordForm.handleSubmit((values) => { LoginPasswordForm.handleSubmit((values) => {
console.log('表单调用成功',values) console.log('表单调用成功',values)
if(login_password_email.value == testEmail.value && login_password.value == testPassword.value) {
console.log('测试登录成功')
console.log(router)
router.push({name:'Home'})
} else {
login().then((res) => { login().then((res) => {
console.log('后端返回信息', res);
if(res.code === 200) { if(res.code === 200) {
console.log('密码登录成功') console.log('密码登录成功')
localStorage.setItem('token', res.data.token) setToken(res.data.token);
localStorage.setItem('userInfo', JSON.stringify(res.data.userInfo));
router.push({path:'/personal'})
} else { } else {
console.log('登录失败') console.log('登录失败')
} }
}) });
}
}, },
(errors) => { (errors) => {
console.log('密码登录表单调用失败',errors) console.log('密码登录表单调用失败',errors)
@ -158,7 +156,7 @@ const onLoginSubmit = () => {
RegisterForm.resetForm(); RegisterForm.resetForm();
LoginEmailForm.handleSubmit(() => { LoginEmailForm.handleSubmit(() => {
testcode().then((res) => { testcode().then((res) => {
if(res.code === 200) { if(res.data.code === 200) {
console.log('邮箱登录成功') console.log('邮箱登录成功')
localStorage.setItem('token', res.data.token) localStorage.setItem('token', res.data.token)
} else { } else {
@ -220,11 +218,11 @@ async function register(){
async function login(){ async function login(){
const res = await request.post('/users/login', { const res = await request.post('/users/login', {
data:{ data:{
email: email.value, username: email.value,
password: password.value password: password.value
} }
}) })
return res.data; return res;
} }
</script> </script>

@ -79,3 +79,7 @@ pnpm add marked highlight.js
pnpm add dompurify pnpm add dompurify
``` ```
### 安装msw模拟后端
```
pnpm add msw -D
```
Loading…
Cancel
Save