mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-18 17:46:38 +08:00
feat(projects): 迁移登录完成
This commit is contained in:
parent
f5a36a05cb
commit
b93b80cb4b
@ -1,14 +1,61 @@
|
||||
import type { MockMethod } from 'vite-plugin-mock';
|
||||
|
||||
const token: ApiAuth.Token = {
|
||||
token: '__TEMP_TOKEN__',
|
||||
refreshToken: '__TEMP_REFRESH_TOKEN__'
|
||||
};
|
||||
|
||||
const apis: MockMethod[] = [
|
||||
// 获取验证码
|
||||
{
|
||||
url: '/mock/getUser',
|
||||
method: 'get',
|
||||
response: (): Service.BackendServiceResult => {
|
||||
url: '/mock/getSmsCode',
|
||||
method: 'post',
|
||||
response: (): Service.BackendServiceResult<boolean> => {
|
||||
return {
|
||||
code: 200,
|
||||
message: 'ok',
|
||||
data: '测试mock数据'
|
||||
data: true
|
||||
};
|
||||
}
|
||||
},
|
||||
// 密码登录
|
||||
{
|
||||
url: '/mock/loginByPwd',
|
||||
method: 'post',
|
||||
response: (): Service.BackendServiceResult<ApiAuth.Token> => {
|
||||
return {
|
||||
code: 200,
|
||||
message: 'ok',
|
||||
data: token
|
||||
};
|
||||
}
|
||||
},
|
||||
// 验证码登录
|
||||
{
|
||||
url: '/mock/loginByCode',
|
||||
method: 'post',
|
||||
response: (): Service.BackendServiceResult<ApiAuth.Token> => {
|
||||
return {
|
||||
code: 200,
|
||||
message: 'ok',
|
||||
data: token
|
||||
};
|
||||
}
|
||||
},
|
||||
// 获取用户信息(请求头携带token)
|
||||
{
|
||||
url: '/mock/getUserInfo',
|
||||
method: 'get',
|
||||
response: (): Service.BackendServiceResult<ApiAuth.UserInfo> => {
|
||||
return {
|
||||
code: 200,
|
||||
message: 'ok',
|
||||
data: {
|
||||
userId: '0',
|
||||
userName: 'Soybean',
|
||||
userPhone: '15170283876',
|
||||
userRole: 'super'
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ const routes: AuthRoute.Route[] = [
|
||||
|
||||
const routeHome: AuthRoute.RoutePath = '/dashboard/analysis';
|
||||
|
||||
const data: ApiRoute.ResponseRoute = {
|
||||
const data: ApiRoute.Route = {
|
||||
routes,
|
||||
home: routeHome
|
||||
};
|
||||
|
10
package.json
10
package.json
@ -37,13 +37,13 @@
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^16.0.1",
|
||||
"@commitlint/config-conventional": "^16.0.0",
|
||||
"@iconify/json": "^1.1.451",
|
||||
"@iconify/json": "^1.1.452",
|
||||
"@iconify/vue": "^3.1.1",
|
||||
"@types/crypto-js": "^4.1.0",
|
||||
"@types/node": "^17.0.6",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.8.1",
|
||||
"@typescript-eslint/parser": "^5.8.1",
|
||||
"@typescript-eslint/parser": "^5.9.0",
|
||||
"@vitejs/plugin-vue": "^2.0.1",
|
||||
"@vue/eslint-config-prettier": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
@ -54,11 +54,11 @@
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.2.0",
|
||||
"husky": "^7.0.4",
|
||||
"lint-staged": "^12.1.4",
|
||||
"lint-staged": "^12.1.5",
|
||||
"mockjs": "^1.1.0",
|
||||
"patch-package": "^6.4.7",
|
||||
"postinstall-postinstall": "^2.1.0",
|
||||
@ -72,7 +72,7 @@
|
||||
"vite-plugin-html": "^2.1.2",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-windicss": "^1.6.1",
|
||||
"vue-tsc": "^0.30.1",
|
||||
"vue-tsc": "^0.30.2",
|
||||
"vueuc": "^0.4.19",
|
||||
"windicss": "^3.4.2"
|
||||
}
|
||||
|
350
pnpm-lock.yaml
350
pnpm-lock.yaml
@ -3,13 +3,13 @@ lockfileVersion: 5.3
|
||||
specifiers:
|
||||
'@commitlint/cli': ^16.0.1
|
||||
'@commitlint/config-conventional': ^16.0.0
|
||||
'@iconify/json': ^1.1.451
|
||||
'@iconify/json': ^1.1.452
|
||||
'@iconify/vue': ^3.1.1
|
||||
'@types/crypto-js': ^4.1.0
|
||||
'@types/node': ^17.0.6
|
||||
'@types/qs': ^6.9.7
|
||||
'@typescript-eslint/eslint-plugin': ^5.8.1
|
||||
'@typescript-eslint/parser': ^5.8.1
|
||||
'@typescript-eslint/parser': ^5.9.0
|
||||
'@vitejs/plugin-vue': ^2.0.1
|
||||
'@vue/eslint-config-prettier': ^7.0.0
|
||||
'@vue/eslint-config-typescript': ^10.0.0
|
||||
@ -25,12 +25,12 @@ specifiers:
|
||||
eslint: ^8.6.0
|
||||
eslint-config-airbnb-base: ^15.0.0
|
||||
eslint-config-prettier: ^8.3.0
|
||||
eslint-plugin-import: ^2.25.3
|
||||
eslint-plugin-import: ^2.25.4
|
||||
eslint-plugin-prettier: ^4.0.0
|
||||
eslint-plugin-vue: ^8.2.0
|
||||
form-data: ^4.0.0
|
||||
husky: ^7.0.4
|
||||
lint-staged: ^12.1.4
|
||||
lint-staged: ^12.1.5
|
||||
lodash-es: ^4.17.21
|
||||
mockjs: ^1.1.0
|
||||
naive-ui: ^2.23.2
|
||||
@ -50,7 +50,7 @@ specifiers:
|
||||
vite-plugin-windicss: ^1.6.1
|
||||
vue: ^3.2.26
|
||||
vue-router: ^4.0.12
|
||||
vue-tsc: ^0.30.1
|
||||
vue-tsc: ^0.30.2
|
||||
vueuc: ^0.4.19
|
||||
windicss: ^3.4.2
|
||||
|
||||
@ -71,13 +71,13 @@ dependencies:
|
||||
devDependencies:
|
||||
'@commitlint/cli': registry.npmmirror.com/@commitlint/cli/16.0.1_@types+node@17.0.6
|
||||
'@commitlint/config-conventional': registry.npmmirror.com/@commitlint/config-conventional/16.0.0
|
||||
'@iconify/json': registry.npmmirror.com/@iconify/json/1.1.451
|
||||
'@iconify/json': registry.npmmirror.com/@iconify/json/1.1.452
|
||||
'@iconify/vue': registry.npmmirror.com/@iconify/vue/3.1.1_vue@3.2.26
|
||||
'@types/crypto-js': registry.npmmirror.com/@types/crypto-js/4.1.0
|
||||
'@types/node': registry.npmmirror.com/@types/node/17.0.6
|
||||
'@types/qs': registry.npmmirror.com/@types/qs/6.9.7
|
||||
'@typescript-eslint/eslint-plugin': registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.8.1_13039593e64cd539d0b4c5c2da390958
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.8.1_eslint@8.6.0+typescript@4.5.4
|
||||
'@typescript-eslint/eslint-plugin': registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.8.1_bd2fd93dbcc607ad2f21b784bccfe0c8
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.9.0_eslint@8.6.0+typescript@4.5.4
|
||||
'@vitejs/plugin-vue': registry.npmmirror.com/@vitejs/plugin-vue/2.0.1_vite@2.7.10+vue@3.2.26
|
||||
'@vue/eslint-config-prettier': registry.npmmirror.com/@vue/eslint-config-prettier/7.0.0_eslint@8.6.0+prettier@2.5.1
|
||||
'@vue/eslint-config-typescript': registry.npmmirror.com/@vue/eslint-config-typescript/10.0.0_57f850728139557a3a27f1248f77f964
|
||||
@ -86,13 +86,13 @@ devDependencies:
|
||||
cz-conventional-changelog: registry.nlark.com/cz-conventional-changelog/3.3.0_@types+node@17.0.6
|
||||
cz-customizable: registry.npmmirror.com/cz-customizable/6.3.0
|
||||
eslint: registry.npmmirror.com/eslint/8.6.0
|
||||
eslint-config-airbnb-base: registry.npmmirror.com/eslint-config-airbnb-base/15.0.0_b54597effeb7d09a84a334cc3c3dadae
|
||||
eslint-config-airbnb-base: registry.npmmirror.com/eslint-config-airbnb-base/15.0.0_b5a36b8c1535387c8dd00eff7ec6b551
|
||||
eslint-config-prettier: registry.nlark.com/eslint-config-prettier/8.3.0_eslint@8.6.0
|
||||
eslint-plugin-import: registry.npmmirror.com/eslint-plugin-import/2.25.3_eslint@8.6.0
|
||||
eslint-plugin-import: registry.npmmirror.com/eslint-plugin-import/2.25.4_eslint@8.6.0
|
||||
eslint-plugin-prettier: registry.npmmirror.com/eslint-plugin-prettier/4.0.0_1c588f61426b1faf18812943f1678311
|
||||
eslint-plugin-vue: registry.npmmirror.com/eslint-plugin-vue/8.2.0_eslint@8.6.0
|
||||
husky: registry.npmmirror.com/husky/7.0.4
|
||||
lint-staged: registry.npmmirror.com/lint-staged/12.1.4
|
||||
lint-staged: registry.npmmirror.com/lint-staged/12.1.5
|
||||
mockjs: registry.npmmirror.com/mockjs/1.1.0
|
||||
patch-package: registry.nlark.com/patch-package/6.4.7
|
||||
postinstall-postinstall: registry.npmmirror.com/postinstall-postinstall/2.1.0
|
||||
@ -106,7 +106,7 @@ devDependencies:
|
||||
vite-plugin-html: registry.npmmirror.com/vite-plugin-html/2.1.2_vite@2.7.10
|
||||
vite-plugin-mock: registry.npmmirror.com/vite-plugin-mock/2.9.6_mockjs@1.1.0+vite@2.7.10
|
||||
vite-plugin-windicss: registry.npmmirror.com/vite-plugin-windicss/1.6.1_vite@2.7.10
|
||||
vue-tsc: registry.npmmirror.com/vue-tsc/0.30.1_typescript@4.5.4
|
||||
vue-tsc: registry.npmmirror.com/vue-tsc/0.30.2_typescript@4.5.4
|
||||
vueuc: registry.npmmirror.com/vueuc/0.4.19_vue@3.2.26
|
||||
windicss: registry.npmmirror.com/windicss/3.4.2
|
||||
|
||||
@ -312,7 +312,7 @@ packages:
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
normalize-path: registry.nlark.com/normalize-path/3.0.0
|
||||
picomatch: registry.nlark.com/picomatch/2.3.0
|
||||
picomatch: registry.npmmirror.com/picomatch/2.3.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/argparse/2.0.1:
|
||||
@ -919,7 +919,7 @@ packages:
|
||||
version: 0.3.6
|
||||
dependencies:
|
||||
debug: registry.npmmirror.com/debug/3.2.7
|
||||
resolve: registry.nlark.com/resolve/1.20.0
|
||||
resolve: registry.npmmirror.com/resolve/1.20.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/eslint-utils/3.0.0_eslint@8.6.0:
|
||||
@ -1675,7 +1675,7 @@ packages:
|
||||
version: 1.0.0
|
||||
dependencies:
|
||||
is-promise: registry.nlark.com/is-promise/2.2.2
|
||||
promise: registry.nlark.com/promise/7.3.1
|
||||
promise: registry.npmmirror.com/promise/7.3.1
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/kind-of/6.0.3:
|
||||
@ -1806,7 +1806,7 @@ packages:
|
||||
engines: {node: '>=8.6'}
|
||||
dependencies:
|
||||
braces: registry.nlark.com/braces/3.0.2
|
||||
picomatch: registry.nlark.com/picomatch/2.3.0
|
||||
picomatch: registry.npmmirror.com/picomatch/2.3.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/mimic-fn/1.2.0:
|
||||
@ -1888,7 +1888,7 @@ packages:
|
||||
version: 2.5.0
|
||||
dependencies:
|
||||
hosted-git-info: registry.npmmirror.com/hosted-git-info/2.8.9
|
||||
resolve: registry.nlark.com/resolve/1.20.0
|
||||
resolve: registry.npmmirror.com/resolve/1.20.0
|
||||
semver: registry.nlark.com/semver/5.7.1
|
||||
validate-npm-package-license: registry.nlark.com/validate-npm-package-license/3.0.4
|
||||
dev: true
|
||||
@ -2186,14 +2186,6 @@ packages:
|
||||
fast-diff: registry.nlark.com/fast-diff/1.2.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/promise/7.3.1:
|
||||
resolution: {integrity: sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/promise/download/promise-7.3.1.tgz}
|
||||
name: promise
|
||||
version: 7.3.1
|
||||
dependencies:
|
||||
asap: registry.nlark.com/asap/2.0.6
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/pug-attrs/3.0.0:
|
||||
resolution: {integrity: sha1-sQRR4DSBZeMfrRzCPr3dncc0fEE=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/pug-attrs/download/pug-attrs-3.0.0.tgz}
|
||||
name: pug-attrs
|
||||
@ -2228,7 +2220,7 @@ packages:
|
||||
jstransformer: registry.nlark.com/jstransformer/1.0.0
|
||||
pug-error: registry.npmmirror.com/pug-error/2.0.0
|
||||
pug-walk: registry.nlark.com/pug-walk/2.0.0
|
||||
resolve: registry.nlark.com/resolve/1.20.0
|
||||
resolve: registry.npmmirror.com/resolve/1.20.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/pug-lexer/5.0.1:
|
||||
@ -2288,21 +2280,6 @@ packages:
|
||||
version: 2.0.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/pug/3.0.2:
|
||||
resolution: {integrity: sha1-81xxBzQ0VOQ7wnrg/3bHMbeOpTU=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/pug/download/pug-3.0.2.tgz}
|
||||
name: pug
|
||||
version: 3.0.2
|
||||
dependencies:
|
||||
pug-code-gen: registry.nlark.com/pug-code-gen/3.0.2
|
||||
pug-filters: registry.nlark.com/pug-filters/4.0.0
|
||||
pug-lexer: registry.nlark.com/pug-lexer/5.0.1
|
||||
pug-linker: registry.nlark.com/pug-linker/4.0.0
|
||||
pug-load: registry.nlark.com/pug-load/3.0.0
|
||||
pug-parser: registry.nlark.com/pug-parser/6.0.0
|
||||
pug-runtime: registry.nlark.com/pug-runtime/3.0.1
|
||||
pug-strip-comments: registry.nlark.com/pug-strip-comments/2.0.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/punycode/2.1.1:
|
||||
resolution: {integrity: sha1-tYsBCsQMIsVldhbI0sLALHv0eew=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/punycode/download/punycode-2.1.1.tgz}
|
||||
name: punycode
|
||||
@ -2352,7 +2329,7 @@ packages:
|
||||
version: 3.6.0
|
||||
engines: {node: '>=8.10.0'}
|
||||
dependencies:
|
||||
picomatch: registry.nlark.com/picomatch/2.3.0
|
||||
picomatch: registry.npmmirror.com/picomatch/2.3.0
|
||||
dev: true
|
||||
|
||||
registry.nlark.com/redent/3.0.0:
|
||||
@ -3386,10 +3363,10 @@ packages:
|
||||
version: 1.2.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@iconify/json/1.1.451:
|
||||
resolution: {integrity: sha512-A+GgU4xetmBfofDQSBNENRsbZo3vMZTF4pkCxFObWs+y9j/C/oGwJwqiV3yrU9jFecF/MkffBbwNFug8j5EAtw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@iconify/json/download/@iconify/json-1.1.451.tgz}
|
||||
registry.npmmirror.com/@iconify/json/1.1.452:
|
||||
resolution: {integrity: sha512-3eUNfCvfap5dE4JUePnul+3wCuWMSqD1zC9oGHqob5FRbJ05tGQ/n0FsL7WthqO5C+dLaMUMNRRG5VRwMzyYfA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@iconify/json/download/@iconify/json-1.1.452.tgz}
|
||||
name: '@iconify/json'
|
||||
version: 1.1.451
|
||||
version: 1.1.452
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@iconify/types/1.0.12:
|
||||
@ -3443,7 +3420,7 @@ packages:
|
||||
builtin-modules: registry.nlark.com/builtin-modules/3.2.0
|
||||
deepmerge: registry.nlark.com/deepmerge/4.2.2
|
||||
is-module: registry.npmmirror.com/is-module/1.0.0
|
||||
resolve: registry.nlark.com/resolve/1.20.0
|
||||
resolve: registry.npmmirror.com/resolve/1.20.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@rollup/pluginutils/3.1.0:
|
||||
@ -3456,7 +3433,7 @@ packages:
|
||||
dependencies:
|
||||
'@types/estree': registry.npmmirror.com/@types/estree/0.0.39
|
||||
estree-walker: registry.npmmirror.com/estree-walker/1.0.1
|
||||
picomatch: registry.nlark.com/picomatch/2.3.0
|
||||
picomatch: registry.npmmirror.com/picomatch/2.3.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@rollup/pluginutils/4.1.2:
|
||||
@ -3594,7 +3571,7 @@ packages:
|
||||
dependencies:
|
||||
'@types/yargs-parser': registry.npmmirror.com/@types/yargs-parser/20.2.1
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.8.1_13039593e64cd539d0b4c5c2da390958:
|
||||
registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.8.1_bd2fd93dbcc607ad2f21b784bccfe0c8:
|
||||
resolution: {integrity: sha512-wTZ5oEKrKj/8/366qTM366zqhIKAp6NCMweoRONtfuC07OAU9nVI2GZZdqQ1qD30WAAtcPdkH+npDwtRFdp4Rw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/download/@typescript-eslint/eslint-plugin-5.8.1.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.8.1
|
||||
name: '@typescript-eslint/eslint-plugin'
|
||||
@ -3609,7 +3586,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/experimental-utils': registry.npmmirror.com/@typescript-eslint/experimental-utils/5.8.1_eslint@8.6.0+typescript@4.5.4
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.8.1_eslint@8.6.0+typescript@4.5.4
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.9.0_eslint@8.6.0+typescript@4.5.4
|
||||
'@typescript-eslint/scope-manager': registry.npmmirror.com/@typescript-eslint/scope-manager/5.8.1
|
||||
debug: registry.npmmirror.com/debug/4.3.3
|
||||
eslint: registry.npmmirror.com/eslint/8.6.0
|
||||
@ -3644,11 +3621,11 @@ packages:
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/parser/5.8.1_eslint@8.6.0+typescript@4.5.4:
|
||||
resolution: {integrity: sha512-K1giKHAjHuyB421SoXMXFHHVI4NdNY603uKw92++D3qyxSeYvC10CBJ/GE5Thpo4WTUvu1mmJI2/FFkz38F2Gw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/parser/download/@typescript-eslint/parser-5.8.1.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/parser/5.8.1
|
||||
registry.npmmirror.com/@typescript-eslint/parser/5.9.0_eslint@8.6.0+typescript@4.5.4:
|
||||
resolution: {integrity: sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/parser/download/@typescript-eslint/parser-5.9.0.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/parser/5.9.0
|
||||
name: '@typescript-eslint/parser'
|
||||
version: 5.8.1
|
||||
version: 5.9.0
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
@ -3657,9 +3634,9 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': registry.npmmirror.com/@typescript-eslint/scope-manager/5.8.1
|
||||
'@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types/5.8.1
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree/5.8.1_typescript@4.5.4
|
||||
'@typescript-eslint/scope-manager': registry.npmmirror.com/@typescript-eslint/scope-manager/5.9.0
|
||||
'@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types/5.9.0
|
||||
'@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree/5.9.0_typescript@4.5.4
|
||||
debug: registry.npmmirror.com/debug/4.3.3
|
||||
eslint: registry.npmmirror.com/eslint/8.6.0
|
||||
typescript: registry.npmmirror.com/typescript/4.5.4
|
||||
@ -3677,6 +3654,16 @@ packages:
|
||||
'@typescript-eslint/visitor-keys': registry.npmmirror.com/@typescript-eslint/visitor-keys/5.8.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/scope-manager/5.9.0:
|
||||
resolution: {integrity: sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/scope-manager/download/@typescript-eslint/scope-manager-5.9.0.tgz}
|
||||
name: '@typescript-eslint/scope-manager'
|
||||
version: 5.9.0
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
'@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types/5.9.0
|
||||
'@typescript-eslint/visitor-keys': registry.npmmirror.com/@typescript-eslint/visitor-keys/5.9.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/types/5.8.1:
|
||||
resolution: {integrity: sha512-L/FlWCCgnjKOLefdok90/pqInkomLnAcF9UAzNr+DSqMC3IffzumHTQTrINXhP1gVp9zlHiYYjvozVZDPleLcA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/types/download/@typescript-eslint/types-5.8.1.tgz}
|
||||
name: '@typescript-eslint/types'
|
||||
@ -3684,6 +3671,13 @@ packages:
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/types/5.9.0:
|
||||
resolution: {integrity: sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/types/download/@typescript-eslint/types-5.9.0.tgz}
|
||||
name: '@typescript-eslint/types'
|
||||
version: 5.9.0
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/typescript-estree/5.8.1_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-26lQ8l8tTbG7ri7xEcCFT9ijU5Fk+sx/KRRyyzCv7MQ+rZZlqiDPtMKWLC8P7o+dtCnby4c+OlxuX1tp8WfafQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-5.8.1.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/typescript-estree/5.8.1
|
||||
@ -3708,6 +3702,30 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/typescript-estree/5.9.0_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/typescript-estree/download/@typescript-eslint/typescript-estree-5.9.0.tgz}
|
||||
id: registry.npmmirror.com/@typescript-eslint/typescript-estree/5.9.0
|
||||
name: '@typescript-eslint/typescript-estree'
|
||||
version: 5.9.0
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types/5.9.0
|
||||
'@typescript-eslint/visitor-keys': registry.npmmirror.com/@typescript-eslint/visitor-keys/5.9.0
|
||||
debug: registry.npmmirror.com/debug/4.3.3
|
||||
globby: registry.nlark.com/globby/11.0.4
|
||||
is-glob: registry.npmmirror.com/is-glob/4.0.3
|
||||
semver: registry.nlark.com/semver/7.3.5
|
||||
tsutils: registry.nlark.com/tsutils/3.21.0_typescript@4.5.4
|
||||
typescript: registry.npmmirror.com/typescript/4.5.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/visitor-keys/5.8.1:
|
||||
resolution: {integrity: sha512-SWgiWIwocK6NralrJarPZlWdr0hZnj5GXHIgfdm8hNkyKvpeQuFyLP6YjSIe9kf3YBIfU6OHSZLYkQ+smZwtNg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/visitor-keys/download/@typescript-eslint/visitor-keys-5.8.1.tgz}
|
||||
name: '@typescript-eslint/visitor-keys'
|
||||
@ -3718,6 +3736,16 @@ packages:
|
||||
eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/3.1.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@typescript-eslint/visitor-keys/5.9.0:
|
||||
resolution: {integrity: sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/visitor-keys/download/@typescript-eslint/visitor-keys-5.9.0.tgz}
|
||||
name: '@typescript-eslint/visitor-keys'
|
||||
version: 5.9.0
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
'@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types/5.9.0
|
||||
eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/3.1.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@vitejs/plugin-vue/2.0.1_vite@2.7.10+vue@3.2.26:
|
||||
resolution: {integrity: sha512-wtdMnGVvys9K8tg+DxowU1ytTrdVveXr3LzdhaKakysgGXyrsfaeds2cDywtvujEASjWOwWL/OgWM+qoeM8Plg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vitejs/plugin-vue/download/@vitejs/plugin-vue-2.0.1.tgz}
|
||||
id: registry.npmmirror.com/@vitejs/plugin-vue/2.0.1
|
||||
@ -3732,61 +3760,62 @@ packages:
|
||||
vue: registry.npmmirror.com/vue/3.2.26
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/code-gen/0.30.1:
|
||||
resolution: {integrity: sha512-qPT0ZGzLaaUArZ1b5qcso2GAFpgjxsPDRXnq0lgsSOpNO6lXJN5ZcWzFZXYPjMJSV1Rkm0ehK5tSUD+sD+pPWg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/code-gen/download/@volar/code-gen-0.30.1.tgz}
|
||||
registry.npmmirror.com/@volar/code-gen/0.30.2:
|
||||
resolution: {integrity: sha512-75rlb3rw/O/HiXxrOsVJ8JhEssqtN4dJ0i6oG4kL0udr+QM0TwN0PqaEhoMRyMFV6kBPPSunBBJQ3XNAb0PtGA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/code-gen/download/@volar/code-gen-0.30.2.tgz}
|
||||
name: '@volar/code-gen'
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.1
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.2
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/html2pug/0.30.1:
|
||||
resolution: {integrity: sha512-ojJPrb4qSLrVNl9LTtdjZ5MFyeHmwJK4OVPTgFc/lyQ94nPS9JHba86SaTwDb2XEgiXBWQVEo12bRr3lW9H2+Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/html2pug/download/@volar/html2pug-0.30.1.tgz}
|
||||
registry.npmmirror.com/@volar/html2pug/0.30.2:
|
||||
resolution: {integrity: sha512-k/DLGoXALaQgnacP1MoJ77AwnCHlKcsQKJJug8Qdou3+yOrzYjSSEP6uwG8BS0Fv1h4d4JYmlXsxW8gJPGXSQQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/html2pug/download/@volar/html2pug-0.30.2.tgz}
|
||||
name: '@volar/html2pug'
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
domelementtype: registry.nlark.com/domelementtype/2.2.0
|
||||
domhandler: registry.npmmirror.com/domhandler/4.3.0
|
||||
htmlparser2: registry.npmmirror.com/htmlparser2/7.2.0
|
||||
pug: registry.nlark.com/pug/3.0.2
|
||||
pug: registry.npmmirror.com/pug/3.0.2
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/shared/0.30.1:
|
||||
resolution: {integrity: sha512-6F5yQYeN+gbXAKplxHDvj4Ei+rHCjNhwkfZnGpaSpEU92uSI2vK/HfEdd/zTKdAZpwz0RjliNuFoXLi6umtQ0w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/shared/download/@volar/shared-0.30.1.tgz}
|
||||
registry.npmmirror.com/@volar/shared/0.30.2:
|
||||
resolution: {integrity: sha512-93Q7i758WjScg4ptvDcpk66r4Paz9StVMH/M5RCsU4/9F5a1xSCUJbkbpwE0zESkVzcuBatDqk79PaZ8TZKqRg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/shared/download/@volar/shared-0.30.2.tgz}
|
||||
name: '@volar/shared'
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
upath: registry.nlark.com/upath/2.0.1
|
||||
vscode-jsonrpc: registry.npmmirror.com/vscode-jsonrpc/8.0.0-next.4
|
||||
vscode-uri: registry.npmmirror.com/vscode-uri/3.0.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/source-map/0.30.1:
|
||||
resolution: {integrity: sha512-QGi36KBGHZ4gq81jPSi3W2wRcpso9Apd59AZOv/H98k5hU9zo8wA5hwartZHiybTlT1q/0Yno3agSj+vK2vocw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/source-map/download/@volar/source-map-0.30.1.tgz}
|
||||
registry.npmmirror.com/@volar/source-map/0.30.2:
|
||||
resolution: {integrity: sha512-gwa9OiSjUOZWYutJX53m/KDU/zaF0yN3RP2B8J0aMVyT5dE/VaIfknSxPAW5QFC6AT79Ea1HKGtChuSBgqHCfA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/source-map/download/@volar/source-map-0.30.2.tgz}
|
||||
name: '@volar/source-map'
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
vscode-languageserver-textdocument: registry.npmmirror.com/vscode-languageserver-textdocument/1.0.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/transforms/0.30.1:
|
||||
resolution: {integrity: sha512-dWFyfQGLoZ8LZI93zud0c5uoCdlkwDBi90G/XaaKfXxkX+3eiJrM0lJ/d1Nc0L04t9mb28I5hpVK68vH90+Tlw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/transforms/download/@volar/transforms-0.30.1.tgz}
|
||||
registry.npmmirror.com/@volar/transforms/0.30.2:
|
||||
resolution: {integrity: sha512-bc+55NGlBbMLHkpChqAEgsblYJxjNHiKVMbVUMi52xKa2l9gOWXNbn5WRsHfz4AR+Cq/Zm0AvVJ10ehLQsGsow==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/transforms/download/@volar/transforms-0.30.2.tgz}
|
||||
name: '@volar/transforms'
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
vscode-languageserver: registry.npmmirror.com/vscode-languageserver/8.0.0-next.5
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
vscode-languageserver-types: registry.npmmirror.com/vscode-languageserver-types/3.17.0-next.5
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/@volar/vue-code-gen/0.30.1:
|
||||
resolution: {integrity: sha512-+0egr84YOYLudP6jRXRm+xtAL92GTPaq0U0lsorLTBp/MB14Fap6HMUr/LEeNB5tnND36UQJiUWHM5eTDAAb4Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/vue-code-gen/download/@volar/vue-code-gen-0.30.1.tgz}
|
||||
registry.npmmirror.com/@volar/vue-code-gen/0.30.2:
|
||||
resolution: {integrity: sha512-kJyVkQFhMvVQ32aDaC6h5DdXG1GJbJjeeAkCnjfCJfMmuYjM5R4QNZHDz1TI0dETgF9vP+kbAukQKNWecHK3qg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@volar/vue-code-gen/download/@volar/vue-code-gen-0.30.2.tgz}
|
||||
name: '@volar/vue-code-gen'
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
'@volar/code-gen': registry.npmmirror.com/@volar/code-gen/0.30.1
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.1
|
||||
'@volar/code-gen': registry.npmmirror.com/@volar/code-gen/0.30.2
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.2
|
||||
'@vue/compiler-core': registry.npmmirror.com/@vue/compiler-core/3.2.26
|
||||
'@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom/3.2.26
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared/3.2.26
|
||||
@ -3881,8 +3910,8 @@ packages:
|
||||
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
|
||||
eslint-plugin-vue: ^8.0.1
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.8.1_13039593e64cd539d0b4c5c2da390958
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.8.1_eslint@8.6.0+typescript@4.5.4
|
||||
'@typescript-eslint/eslint-plugin': registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.8.1_bd2fd93dbcc607ad2f21b784bccfe0c8
|
||||
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.9.0_eslint@8.6.0+typescript@4.5.4
|
||||
eslint: registry.npmmirror.com/eslint/8.6.0
|
||||
eslint-plugin-vue: registry.npmmirror.com/eslint-plugin-vue/8.2.0_eslint@8.6.0
|
||||
vue-eslint-parser: registry.npmmirror.com/vue-eslint-parser/8.0.1_eslint@8.6.0
|
||||
@ -4766,7 +4795,7 @@ packages:
|
||||
esbuild-windows-arm64: registry.npmmirror.com/esbuild-windows-arm64/0.13.15
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/eslint-config-airbnb-base/15.0.0_b54597effeb7d09a84a334cc3c3dadae:
|
||||
registry.npmmirror.com/eslint-config-airbnb-base/15.0.0_b5a36b8c1535387c8dd00eff7ec6b551:
|
||||
resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint-config-airbnb-base/download/eslint-config-airbnb-base-15.0.0.tgz}
|
||||
id: registry.npmmirror.com/eslint-config-airbnb-base/15.0.0
|
||||
name: eslint-config-airbnb-base
|
||||
@ -4778,28 +4807,27 @@ packages:
|
||||
dependencies:
|
||||
confusing-browser-globals: registry.npmmirror.com/confusing-browser-globals/1.0.11
|
||||
eslint: registry.npmmirror.com/eslint/8.6.0
|
||||
eslint-plugin-import: registry.npmmirror.com/eslint-plugin-import/2.25.3_eslint@8.6.0
|
||||
eslint-plugin-import: registry.npmmirror.com/eslint-plugin-import/2.25.4_eslint@8.6.0
|
||||
object.assign: registry.nlark.com/object.assign/4.1.2
|
||||
object.entries: registry.npmmirror.com/object.entries/1.1.5
|
||||
semver: registry.nlark.com/semver/6.3.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/eslint-module-utils/2.7.1:
|
||||
resolution: {integrity: sha1-tDUAHJ+N1Kt/bQ78rkuWltTCS3w=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint-module-utils/download/eslint-module-utils-2.7.1.tgz}
|
||||
registry.npmmirror.com/eslint-module-utils/2.7.2:
|
||||
resolution: {integrity: sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint-module-utils/download/eslint-module-utils-2.7.2.tgz}
|
||||
name: eslint-module-utils
|
||||
version: 2.7.1
|
||||
version: 2.7.2
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
debug: registry.npmmirror.com/debug/3.2.7
|
||||
find-up: registry.npmmirror.com/find-up/2.1.0
|
||||
pkg-dir: registry.npmmirror.com/pkg-dir/2.0.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/eslint-plugin-import/2.25.3_eslint@8.6.0:
|
||||
resolution: {integrity: sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint-plugin-import/download/eslint-plugin-import-2.25.3.tgz}
|
||||
id: registry.npmmirror.com/eslint-plugin-import/2.25.3
|
||||
registry.npmmirror.com/eslint-plugin-import/2.25.4_eslint@8.6.0:
|
||||
resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint-plugin-import/download/eslint-plugin-import-2.25.4.tgz}
|
||||
id: registry.npmmirror.com/eslint-plugin-import/2.25.4
|
||||
name: eslint-plugin-import
|
||||
version: 2.25.3
|
||||
version: 2.25.4
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
@ -4810,13 +4838,13 @@ packages:
|
||||
doctrine: registry.nlark.com/doctrine/2.1.0
|
||||
eslint: registry.npmmirror.com/eslint/8.6.0
|
||||
eslint-import-resolver-node: registry.nlark.com/eslint-import-resolver-node/0.3.6
|
||||
eslint-module-utils: registry.npmmirror.com/eslint-module-utils/2.7.1
|
||||
eslint-module-utils: registry.npmmirror.com/eslint-module-utils/2.7.2
|
||||
has: registry.nlark.com/has/1.0.3
|
||||
is-core-module: registry.npmmirror.com/is-core-module/2.8.0
|
||||
is-glob: registry.npmmirror.com/is-glob/4.0.3
|
||||
minimatch: registry.nlark.com/minimatch/3.0.4
|
||||
object.values: registry.npmmirror.com/object.values/1.1.5
|
||||
resolve: registry.nlark.com/resolve/1.20.0
|
||||
resolve: registry.npmmirror.com/resolve/1.20.0
|
||||
tsconfig-paths: registry.npmmirror.com/tsconfig-paths/3.12.0
|
||||
dev: true
|
||||
|
||||
@ -5192,7 +5220,7 @@ packages:
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/htmlparser2/7.2.0:
|
||||
resolution: {integrity: sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/htmlparser2/download/htmlparser2-7.2.0.tgz?cache=0&sync_timestamp=1636641904600&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-7.2.0.tgz}
|
||||
resolution: {integrity: sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/htmlparser2/download/htmlparser2-7.2.0.tgz?cache=0&sync_timestamp=1636641716463&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-7.2.0.tgz}
|
||||
name: htmlparser2
|
||||
version: 7.2.0
|
||||
dependencies:
|
||||
@ -5380,10 +5408,10 @@ packages:
|
||||
version: 1.2.4
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/lint-staged/12.1.4:
|
||||
resolution: {integrity: sha512-RgDz9nsFsE0/5eL9Vat0AvCuk0+j5mEuzBIVfrRH5FRtt5wibYe8zTjZs2nuqLFrLAGQGYnj8+HJxolcj08i/A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lint-staged/download/lint-staged-12.1.4.tgz}
|
||||
registry.npmmirror.com/lint-staged/12.1.5:
|
||||
resolution: {integrity: sha512-WyKb+0sNKDTd1LwwAfTBPp0XmdaKkAOEbg4oHE4Kq2+oQVchg/VAcjVQtSqZih1izNsTURjc2EkhG/syRQUXdA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lint-staged/download/lint-staged-12.1.5.tgz}
|
||||
name: lint-staged
|
||||
version: 12.1.4
|
||||
version: 12.1.5
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@ -5599,7 +5627,7 @@ packages:
|
||||
version: 4.0.1
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
path-key: registry.nlark.com/path-key/3.1.1
|
||||
path-key: registry.npmmirror.com/path-key/3.1.1
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/object-inspect/1.12.0:
|
||||
@ -5683,11 +5711,25 @@ packages:
|
||||
lines-and-columns: registry.npmmirror.com/lines-and-columns/1.2.4
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/path-key/3.1.1:
|
||||
resolution: {integrity: sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/path-key/download/path-key-3.1.1.tgz}
|
||||
name: path-key
|
||||
version: 3.1.1
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/picocolors/1.0.0:
|
||||
resolution: {integrity: sha1-y1vcdP8/UYkiNur3nWi8RFZKuBw=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/picocolors/download/picocolors-1.0.0.tgz}
|
||||
name: picocolors
|
||||
version: 1.0.0
|
||||
|
||||
registry.npmmirror.com/picomatch/2.3.0:
|
||||
resolution: {integrity: sha1-8fBh3o9qS/AiiS4tEoI0+5gwKXI=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/picomatch/download/picomatch-2.3.0.tgz}
|
||||
name: picomatch
|
||||
version: 2.3.0
|
||||
engines: {node: '>=8.6'}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/pinia/2.0.9_typescript@4.5.4+vue@3.2.26:
|
||||
resolution: {integrity: sha512-iuYdxLJKQ07YPyOHYH05wNG9eKWqkP/4y4GE8+RqEYtz5fwHgPA5kr6zQbg/DoEJGnR2XCm1w1vdt6ppzL9ATg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pinia/download/pinia-2.0.9.tgz}
|
||||
id: registry.npmmirror.com/pinia/2.0.9
|
||||
@ -5709,15 +5751,6 @@ packages:
|
||||
vue-demi: registry.npmmirror.com/vue-demi/0.12.1_vue@3.2.26
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/pkg-dir/2.0.0:
|
||||
resolution: {integrity: sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pkg-dir/download/pkg-dir-2.0.0.tgz}
|
||||
name: pkg-dir
|
||||
version: 2.0.0
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
find-up: registry.npmmirror.com/find-up/2.1.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/postcss/8.4.5:
|
||||
resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/postcss/download/postcss-8.4.5.tgz}
|
||||
name: postcss
|
||||
@ -5761,12 +5794,35 @@ packages:
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/promise/7.3.1:
|
||||
resolution: {integrity: sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/promise/download/promise-7.3.1.tgz}
|
||||
name: promise
|
||||
version: 7.3.1
|
||||
dependencies:
|
||||
asap: registry.nlark.com/asap/2.0.6
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/pug-error/2.0.0:
|
||||
resolution: {integrity: sha1-XGIXPLCcNN4qLOBPF7it/sdNjKU=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pug-error/download/pug-error-2.0.0.tgz}
|
||||
name: pug-error
|
||||
version: 2.0.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/pug/3.0.2:
|
||||
resolution: {integrity: sha1-81xxBzQ0VOQ7wnrg/3bHMbeOpTU=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pug/download/pug-3.0.2.tgz}
|
||||
name: pug
|
||||
version: 3.0.2
|
||||
dependencies:
|
||||
pug-code-gen: registry.nlark.com/pug-code-gen/3.0.2
|
||||
pug-filters: registry.nlark.com/pug-filters/4.0.0
|
||||
pug-lexer: registry.nlark.com/pug-lexer/5.0.1
|
||||
pug-linker: registry.nlark.com/pug-linker/4.0.0
|
||||
pug-load: registry.nlark.com/pug-load/3.0.0
|
||||
pug-parser: registry.nlark.com/pug-parser/6.0.0
|
||||
pug-runtime: registry.nlark.com/pug-runtime/3.0.1
|
||||
pug-strip-comments: registry.nlark.com/pug-strip-comments/2.0.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/qs/6.10.2:
|
||||
resolution: {integrity: sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/qs/download/qs-6.10.2.tgz}
|
||||
name: qs
|
||||
@ -5805,6 +5861,15 @@ packages:
|
||||
version: 0.5.6
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/resolve/1.20.0:
|
||||
resolution: {integrity: sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/resolve/download/resolve-1.20.0.tgz}
|
||||
name: resolve
|
||||
version: 1.20.0
|
||||
dependencies:
|
||||
is-core-module: registry.npmmirror.com/is-core-module/2.8.0
|
||||
path-parse: registry.nlark.com/path-parse/1.0.7
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/reusify/1.0.4:
|
||||
resolution: {integrity: sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY=, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/reusify/download/reusify-1.0.4.tgz}
|
||||
name: reusify
|
||||
@ -6421,30 +6486,32 @@ packages:
|
||||
version: 5.0.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vscode-pug-languageservice/0.30.1:
|
||||
resolution: {integrity: sha512-ytco+lziRQNrpHpI8X+/rhYaX4KUWAnYZHd1f1epu2m+9WoIf9swbk8/slIOeyec1DPg4Y7AS8hTLcEfOfY71g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vscode-pug-languageservice/download/vscode-pug-languageservice-0.30.1.tgz}
|
||||
registry.npmmirror.com/vscode-pug-languageservice/0.30.2:
|
||||
resolution: {integrity: sha512-YkrBodqSzNrtLaEIeMnRJAcnqCWysIiOdkzxF6XHuOc+wDvbZ1U4XgxoLvNNjQdzNQIEYKbsLW0ldq5TYphjiA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vscode-pug-languageservice/download/vscode-pug-languageservice-0.30.2.tgz}
|
||||
name: vscode-pug-languageservice
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
'@volar/code-gen': registry.npmmirror.com/@volar/code-gen/0.30.1
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.1
|
||||
'@volar/transforms': registry.npmmirror.com/@volar/transforms/0.30.1
|
||||
'@volar/code-gen': registry.npmmirror.com/@volar/code-gen/0.30.2
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.2
|
||||
'@volar/transforms': registry.npmmirror.com/@volar/transforms/0.30.2
|
||||
pug-lexer: registry.nlark.com/pug-lexer/5.0.1
|
||||
pug-parser: registry.nlark.com/pug-parser/6.0.0
|
||||
vscode-languageserver: registry.npmmirror.com/vscode-languageserver/8.0.0-next.5
|
||||
vscode-languageserver-textdocument: registry.npmmirror.com/vscode-languageserver-textdocument/1.0.3
|
||||
vscode-languageserver-types: registry.npmmirror.com/vscode-languageserver-types/3.17.0-next.5
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vscode-typescript-languageservice/0.30.1:
|
||||
resolution: {integrity: sha512-7EBJiaLXThlrbm2K5VU+qWPR3z+RtmCFLWiZaNdJYO/E5UFBQiPmO8qXlxcB2x1N7zId2GZoogAbT15oexY2eQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vscode-typescript-languageservice/download/vscode-typescript-languageservice-0.30.1.tgz}
|
||||
registry.npmmirror.com/vscode-typescript-languageservice/0.30.2:
|
||||
resolution: {integrity: sha512-5l+gMfbHTZnJy7V7xdH78ai1ViR/scrIVQT5KFraDWLKTYHjGBkHDZ1E9fF+jbeyEizyy2ayldTQ7kCz8jWqVA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vscode-typescript-languageservice/download/vscode-typescript-languageservice-0.30.2.tgz}
|
||||
name: vscode-typescript-languageservice
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
semver: registry.nlark.com/semver/7.3.5
|
||||
upath: registry.nlark.com/upath/2.0.1
|
||||
vscode-languageserver: registry.npmmirror.com/vscode-languageserver/8.0.0-next.5
|
||||
vscode-languageserver-protocol: registry.npmmirror.com/vscode-languageserver-protocol/3.17.0-next.11
|
||||
vscode-languageserver-textdocument: registry.npmmirror.com/vscode-languageserver-textdocument/1.0.3
|
||||
vscode-nls: registry.npmmirror.com/vscode-nls/5.0.0
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vscode-uri/2.1.2:
|
||||
@ -6459,17 +6526,17 @@ packages:
|
||||
version: 3.0.3
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vscode-vue-languageservice/0.30.1:
|
||||
resolution: {integrity: sha512-l9R5vXkrGY0N4hA2o9ZFBIKL44z7UbHc45YjOmnslGwYL15YXfb7T4quW8VYSWJNRbiFBTNnNLWORIDEcWazBA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vscode-vue-languageservice/download/vscode-vue-languageservice-0.30.1.tgz}
|
||||
registry.npmmirror.com/vscode-vue-languageservice/0.30.2:
|
||||
resolution: {integrity: sha512-P0g92JmnVkV2zrWhDbT2zxuOUp0X2kMM9VHlrT7ALZq8wAhPOW0B4nhhb9a6jKBh6qqFBDquNeQRvTEZp4NJMA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vscode-vue-languageservice/download/vscode-vue-languageservice-0.30.2.tgz}
|
||||
name: vscode-vue-languageservice
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
dependencies:
|
||||
'@volar/code-gen': registry.npmmirror.com/@volar/code-gen/0.30.1
|
||||
'@volar/html2pug': registry.npmmirror.com/@volar/html2pug/0.30.1
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.1
|
||||
'@volar/transforms': registry.npmmirror.com/@volar/transforms/0.30.1
|
||||
'@volar/vue-code-gen': registry.npmmirror.com/@volar/vue-code-gen/0.30.1
|
||||
'@volar/code-gen': registry.npmmirror.com/@volar/code-gen/0.30.2
|
||||
'@volar/html2pug': registry.npmmirror.com/@volar/html2pug/0.30.2
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
'@volar/source-map': registry.npmmirror.com/@volar/source-map/0.30.2
|
||||
'@volar/transforms': registry.npmmirror.com/@volar/transforms/0.30.2
|
||||
'@volar/vue-code-gen': registry.npmmirror.com/@volar/vue-code-gen/0.30.2
|
||||
'@vscode/emmet-helper': registry.npmmirror.com/@vscode/emmet-helper/2.8.3
|
||||
'@vue/reactivity': registry.npmmirror.com/@vue/reactivity/3.2.26
|
||||
'@vue/shared': registry.npmmirror.com/@vue/shared/3.2.26
|
||||
@ -6479,9 +6546,10 @@ packages:
|
||||
vscode-html-languageservice: registry.npmmirror.com/vscode-html-languageservice/4.2.1
|
||||
vscode-json-languageservice: registry.npmmirror.com/vscode-json-languageservice/4.1.10
|
||||
vscode-languageserver: registry.npmmirror.com/vscode-languageserver/8.0.0-next.5
|
||||
vscode-languageserver-protocol: registry.npmmirror.com/vscode-languageserver-protocol/3.17.0-next.11
|
||||
vscode-languageserver-textdocument: registry.npmmirror.com/vscode-languageserver-textdocument/1.0.3
|
||||
vscode-pug-languageservice: registry.npmmirror.com/vscode-pug-languageservice/0.30.1
|
||||
vscode-typescript-languageservice: registry.npmmirror.com/vscode-typescript-languageservice/0.30.1
|
||||
vscode-pug-languageservice: registry.npmmirror.com/vscode-pug-languageservice/0.30.2
|
||||
vscode-typescript-languageservice: registry.npmmirror.com/vscode-typescript-languageservice/0.30.2
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vue-demi/0.12.1_vue@3.2.26:
|
||||
@ -6535,18 +6603,18 @@ packages:
|
||||
vue: registry.npmmirror.com/vue/3.2.26
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/vue-tsc/0.30.1_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-AVBPWF70LvuzAt6phaF3U8pg1WmjmZQBfZvkX4Ve9EHTPh4R2JiJnSjf3MQgnx03qF5w0PGkBJ90l12aaLZeKQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-tsc/download/vue-tsc-0.30.1.tgz}
|
||||
id: registry.npmmirror.com/vue-tsc/0.30.1
|
||||
registry.npmmirror.com/vue-tsc/0.30.2_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-A8KIk5KwQTbSdsrDxwJkFYLPqDJ1zM86w3X8cgpi6rveozKUGDMPt300awEz61sTuBM9fAfUhNRcsWbsJ1I+TQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-tsc/download/vue-tsc-0.30.2.tgz}
|
||||
id: registry.npmmirror.com/vue-tsc/0.30.2
|
||||
name: vue-tsc
|
||||
version: 0.30.1
|
||||
version: 0.30.2
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
dependencies:
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.1
|
||||
'@volar/shared': registry.npmmirror.com/@volar/shared/0.30.2
|
||||
typescript: registry.npmmirror.com/typescript/4.5.4
|
||||
vscode-vue-languageservice: registry.npmmirror.com/vscode-vue-languageservice/0.30.1
|
||||
vscode-vue-languageservice: registry.npmmirror.com/vscode-vue-languageservice/0.30.2
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/vue/3.2.26:
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<n-config-provider :theme-overrides="theme.naiveThemeOverrides" class="h-full">
|
||||
<n-config-provider :theme="theme.naiveTheme" :theme-overrides="theme.naiveThemeOverrides" class="h-full">
|
||||
<slot></slot>
|
||||
</n-config-provider>
|
||||
</template>
|
||||
|
48
src/components/business/LoginAgreement/index.vue
Normal file
48
src/components/business/LoginAgreement/index.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="w-full text-14px">
|
||||
<n-checkbox v-model:checked="checked">我已经仔细阅读并接受</n-checkbox>
|
||||
<n-button :text="true" type="primary" @click="handleClickProtocol">《用户协议》</n-button>
|
||||
<n-button :text="true" type="primary" @click="handleClickPolicy">《隐私权政策》</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { NCheckbox, NButton } from 'naive-ui';
|
||||
|
||||
interface Props {
|
||||
/** 是否勾选 */
|
||||
value?: boolean;
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:value', value: boolean): void;
|
||||
/** 点击协议 */
|
||||
(e: 'click-protocol'): void;
|
||||
/** 点击隐私政策 */
|
||||
(e: 'click-policy'): void;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
value: true
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const checked = computed({
|
||||
get() {
|
||||
return props.value;
|
||||
},
|
||||
set(newValue: boolean) {
|
||||
emit('update:value', newValue);
|
||||
}
|
||||
});
|
||||
|
||||
function handleClickProtocol() {
|
||||
emit('click-protocol');
|
||||
}
|
||||
function handleClickPolicy() {
|
||||
emit('click-policy');
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
3
src/components/business/index.ts
Normal file
3
src/components/business/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import LoginAgreement from './LoginAgreement/index.vue';
|
||||
|
||||
export { LoginAgreement };
|
39
src/components/common/DarkModeSwitch/index.vue
Normal file
39
src/components/common/DarkModeSwitch/index.vue
Normal file
@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="text-18px hover:text-primary cursor-pointer" @click="handleSwitch">
|
||||
<icon-mdi-moon-waning-crescent v-if="darkMode" />
|
||||
<icon-mdi-white-balance-sunny v-else />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
interface Props {
|
||||
/** 暗黑模式 */
|
||||
dark?: boolean;
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:dark', darkMode: boolean): void;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
dark: false
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const darkMode = computed({
|
||||
get() {
|
||||
return props.dark;
|
||||
},
|
||||
set(newValue: boolean) {
|
||||
emit('update:dark', newValue);
|
||||
}
|
||||
});
|
||||
|
||||
function handleSwitch() {
|
||||
darkMode.value = !darkMode.value;
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
@ -1,3 +1,4 @@
|
||||
import SystemLogo from './SystemLogo/index.vue';
|
||||
import DarkModeSwitch from './DarkModeSwitch/index.vue';
|
||||
|
||||
export { SystemLogo };
|
||||
export { SystemLogo, DarkModeSwitch };
|
||||
|
39
src/components/custom/ImageVerify/index.vue
Normal file
39
src/components/custom/ImageVerify/index.vue
Normal file
@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div>
|
||||
<canvas ref="domRef" width="152" height="40" class="cursor-pointer" @click="getImgCode"></canvas>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { watch } from 'vue';
|
||||
import { useImageVerify } from '@/hooks';
|
||||
|
||||
interface Props {
|
||||
code?: string;
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:code', code: string): void;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
code: ''
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const { domRef, imgCode, setImgCode, getImgCode } = useImageVerify();
|
||||
|
||||
watch(
|
||||
() => props.code,
|
||||
newValue => {
|
||||
setImgCode(newValue);
|
||||
}
|
||||
);
|
||||
watch(imgCode, newValue => {
|
||||
emit('update:code', newValue);
|
||||
});
|
||||
|
||||
defineExpose({ getImgCode });
|
||||
</script>
|
||||
<style scoped></style>
|
3
src/components/custom/index.ts
Normal file
3
src/components/custom/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import ImageVerify from './ImageVerify/index.vue';
|
||||
|
||||
export { ImageVerify };
|
@ -1 +1,3 @@
|
||||
export * from './common';
|
||||
export * from './custom';
|
||||
export * from './business';
|
||||
|
@ -1 +1,3 @@
|
||||
export * from './system';
|
||||
export * from './router';
|
||||
export * from './route';
|
||||
|
32
src/composables/common/route.ts
Normal file
32
src/composables/common/route.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { unref, computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { router } from '@/router';
|
||||
import { useRouteStore } from '@/store';
|
||||
|
||||
/**
|
||||
* 路由查询参数
|
||||
* @param inSetup - 是否在vue页面/组件的setup里面调用,在axios里面无法使用useRouter和useRoute
|
||||
*/
|
||||
export function useRouteQuery(inSetup: boolean = true) {
|
||||
const { getRouteName } = useRouteStore();
|
||||
|
||||
const route = getRouteInstance(inSetup);
|
||||
|
||||
/** 登录后跳转的地址 */
|
||||
const loginRedirect = computed(() => {
|
||||
let url: string | undefined;
|
||||
if (route.name === getRouteName('login')) {
|
||||
url = (route.query?.redirect as string) || '';
|
||||
}
|
||||
return url;
|
||||
});
|
||||
|
||||
return {
|
||||
loginRedirect
|
||||
};
|
||||
}
|
||||
|
||||
function getRouteInstance(inSetup: boolean = true) {
|
||||
const route = inSetup ? useRoute() : unref(router.currentRoute);
|
||||
return route;
|
||||
}
|
90
src/composables/common/router.ts
Normal file
90
src/composables/common/router.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { unref } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import type { RouteLocationRaw } from 'vue-router';
|
||||
import { router as globalRouter } from '@/router';
|
||||
import { useRouteStore } from '@/store';
|
||||
import { LoginModuleKey } from '@/interface';
|
||||
|
||||
/**
|
||||
* 路由跳转
|
||||
* @param inSetup - 是否在vue页面/组件的setup里面调用,在axios里面无法使用useRouter和useRoute
|
||||
*/
|
||||
export function useRouterPush(inSetup: boolean = true) {
|
||||
const { getRouteName } = useRouteStore();
|
||||
|
||||
const router = inSetup ? useRouter() : globalRouter;
|
||||
const route = inSetup ? useRoute() : unref(globalRouter.currentRoute);
|
||||
|
||||
/**
|
||||
* 路由跳转
|
||||
* @param to - 需要跳转的路由
|
||||
* @param newTab - 是否在新的浏览器Tab标签打开
|
||||
*/
|
||||
function routerPush(to: RouteLocationRaw, newTab = false) {
|
||||
if (newTab) {
|
||||
const routerData = router.resolve(to);
|
||||
window.open(routerData.href, '_blank');
|
||||
} else {
|
||||
router.push(to);
|
||||
}
|
||||
}
|
||||
|
||||
/** 返回上一级路由 */
|
||||
function routerBack() {
|
||||
router.go(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转首页
|
||||
* @param newTab - 在新的浏览器标签打开
|
||||
*/
|
||||
function toHome(newTab = false) {
|
||||
routerPush(getRouteName('root'), newTab);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转登录页面
|
||||
* @param loginModule - 展示的登录模块
|
||||
* @param redirectUrl - 重定向地址(登录成功后跳转的地址),默认undefined表示取当前地址为重定向地址
|
||||
*/
|
||||
function toLogin(loginModule?: LoginModuleKey, redirectUrl?: string) {
|
||||
const module: LoginModuleKey = loginModule || 'pwd-login';
|
||||
const routeLocation: RouteLocationRaw = {
|
||||
name: getRouteName('login'),
|
||||
params: { module }
|
||||
};
|
||||
const redirect = redirectUrl || route.fullPath;
|
||||
Object.assign(routeLocation, { query: { redirect } });
|
||||
routerPush(routeLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录页切换其他模块
|
||||
* @param module - 切换后的登录模块
|
||||
*/
|
||||
function toLoginModule(module: LoginModuleKey) {
|
||||
const { query } = route;
|
||||
routerPush({ name: getRouteName('login'), params: { module }, query });
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功后跳转重定向的地址
|
||||
* @param redirect - 重定向地址
|
||||
*/
|
||||
function toLoginRedirect(redirect?: string) {
|
||||
if (redirect) {
|
||||
routerPush(redirect);
|
||||
} else {
|
||||
toHome();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
routerPush,
|
||||
routerBack,
|
||||
toHome,
|
||||
toLogin,
|
||||
toLoginModule,
|
||||
toLoginRedirect
|
||||
};
|
||||
}
|
@ -1 +1,2 @@
|
||||
export * from './service';
|
||||
export * from './regexp';
|
||||
|
16
src/config/common/regexp.ts
Normal file
16
src/config/common/regexp.ts
Normal file
@ -0,0 +1,16 @@
|
||||
/** 手机号码正则 */
|
||||
export const REGEXP_PHONE =
|
||||
/^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$/;
|
||||
|
||||
/** 邮箱正则 */
|
||||
export const REGEXP_EMAIL = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
|
||||
|
||||
/** 密码正则(密码为8-18位数字/字符/符号的组合) */
|
||||
export const REGEXP_PWD =
|
||||
/^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$/;
|
||||
|
||||
/** 6位数字验证码正则 */
|
||||
export const REGEXP_CODE_SIX = /^\d{6}$/;
|
||||
|
||||
/** 4位数字验证码正则 */
|
||||
export const REGEXP_CODE_FOUR = /^\d{4}$/;
|
5
src/hooks/business/index.ts
Normal file
5
src/hooks/business/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import useCountDown from './useCountDown';
|
||||
import useSmsCode from './useSmsCode';
|
||||
import useImageVerify from './useImageVerify';
|
||||
|
||||
export { useCountDown, useSmsCode, useImageVerify };
|
52
src/hooks/business/useCountDown.ts
Normal file
52
src/hooks/business/useCountDown.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { ref, computed } from 'vue';
|
||||
import { useBoolean } from '../common';
|
||||
|
||||
/**
|
||||
* 倒计时
|
||||
* @param second - 倒计时的时间(s)
|
||||
*/
|
||||
export default function useCountDown(second: number) {
|
||||
if (second <= 0 && second % 1 !== 0) {
|
||||
throw Error('倒计时的时间应该为一个正整数!');
|
||||
}
|
||||
const { bool: isComplete, setTrue, setFalse } = useBoolean(false);
|
||||
|
||||
const counts = ref(0);
|
||||
const isCounting = computed(() => Boolean(counts.value));
|
||||
|
||||
let intervalId: any;
|
||||
|
||||
/**
|
||||
* 开始计时
|
||||
* @param updateSecond - 更改初时传入的倒计时时间
|
||||
*/
|
||||
function start(updateSecond: number = second) {
|
||||
if (!counts.value) {
|
||||
setFalse();
|
||||
counts.value = updateSecond;
|
||||
intervalId = setInterval(() => {
|
||||
counts.value -= 1;
|
||||
if (counts.value <= 0) {
|
||||
clearInterval(intervalId);
|
||||
setTrue();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止计时
|
||||
*/
|
||||
function stop() {
|
||||
intervalId = clearInterval(intervalId);
|
||||
counts.value = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
counts,
|
||||
isCounting,
|
||||
start,
|
||||
stop,
|
||||
isComplete
|
||||
};
|
||||
}
|
85
src/hooks/business/useImageVerify.ts
Normal file
85
src/hooks/business/useImageVerify.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
/**
|
||||
* 绘制图形验证码
|
||||
* @param width - 图形宽度
|
||||
* @param height - 图形高度
|
||||
*/
|
||||
export default function useImageVerify(width = 152, height = 40) {
|
||||
const domRef = ref<HTMLCanvasElement>();
|
||||
const imgCode = ref('');
|
||||
|
||||
function setImgCode(code: string) {
|
||||
imgCode.value = code;
|
||||
}
|
||||
|
||||
function getImgCode() {
|
||||
if (!domRef.value) return;
|
||||
imgCode.value = draw(domRef.value, width, height);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getImgCode();
|
||||
});
|
||||
|
||||
return {
|
||||
domRef,
|
||||
imgCode,
|
||||
setImgCode,
|
||||
getImgCode
|
||||
};
|
||||
}
|
||||
|
||||
function randomNum(min: number, max: number) {
|
||||
const num = Math.floor(Math.random() * (max - min) + min);
|
||||
return num;
|
||||
}
|
||||
|
||||
function randomColor(min: number, max: number) {
|
||||
const r = randomNum(min, max);
|
||||
const g = randomNum(min, max);
|
||||
const b = randomNum(min, max);
|
||||
return `rgb(${r},${g},${b})`;
|
||||
}
|
||||
|
||||
function draw(dom: HTMLCanvasElement, width: number, height: number) {
|
||||
let imgCode = '';
|
||||
|
||||
const NUMBER_STRING = '0123456789';
|
||||
|
||||
const ctx = dom.getContext('2d');
|
||||
if (!ctx) return imgCode;
|
||||
|
||||
ctx.fillStyle = randomColor(180, 230);
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
const text = NUMBER_STRING[randomNum(0, NUMBER_STRING.length)];
|
||||
imgCode += text;
|
||||
const fontSize = randomNum(18, 41);
|
||||
const deg = randomNum(-30, 30);
|
||||
ctx.font = `${fontSize}px Simhei`;
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillStyle = randomColor(80, 150);
|
||||
ctx.save();
|
||||
ctx.translate(30 * i + 23, 15);
|
||||
ctx.rotate((deg * Math.PI) / 180);
|
||||
ctx.fillText(text, -15 + 5, -15);
|
||||
ctx.restore();
|
||||
}
|
||||
for (let i = 0; i < 5; i += 1) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(randomNum(0, width), randomNum(0, height));
|
||||
ctx.lineTo(randomNum(0, width), randomNum(0, height));
|
||||
ctx.strokeStyle = randomColor(180, 230);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
for (let i = 0; i < 41; i += 1) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(randomNum(0, width), randomNum(0, height), 1, 0, 2 * Math.PI);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = randomColor(150, 200);
|
||||
ctx.fill();
|
||||
}
|
||||
return imgCode;
|
||||
}
|
59
src/hooks/business/useSmsCode.ts
Normal file
59
src/hooks/business/useSmsCode.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { computed } from 'vue';
|
||||
import { REGEXP_PHONE } from '@/config';
|
||||
import { fetchSmsCode } from '@/service';
|
||||
import { useLoading } from '../common';
|
||||
import useCountDown from './useCountDown';
|
||||
|
||||
export default function useSmsCode() {
|
||||
const { loading, startLoading, endLoading } = useLoading();
|
||||
const { counts, start, isCounting } = useCountDown(60);
|
||||
const initLabel = '获取验证码';
|
||||
const countingLabel = (second: number) => `${second}秒后重新获取`;
|
||||
const label = computed(() => {
|
||||
let text = initLabel;
|
||||
if (loading.value) {
|
||||
text = '';
|
||||
}
|
||||
if (isCounting.value) {
|
||||
text = countingLabel(counts.value);
|
||||
}
|
||||
return text;
|
||||
});
|
||||
|
||||
/** 判断手机号码格式是否正确 */
|
||||
function isPhoneValid(phone: string) {
|
||||
let valid = true;
|
||||
if (phone.trim() === '') {
|
||||
window.$message?.error('手机号码不能为空!');
|
||||
valid = false;
|
||||
} else if (!REGEXP_PHONE.test(phone)) {
|
||||
window.$message?.error('手机号码格式错误!');
|
||||
valid = false;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取短信验证码
|
||||
* @param phone - 手机号
|
||||
*/
|
||||
async function getSmsCode(phone: string) {
|
||||
const valid = isPhoneValid(phone);
|
||||
if (!valid || loading.value) return;
|
||||
startLoading();
|
||||
const { data } = await fetchSmsCode(phone);
|
||||
if (data) {
|
||||
window.$message?.success('验证码发送成功!');
|
||||
start();
|
||||
}
|
||||
endLoading();
|
||||
}
|
||||
|
||||
return {
|
||||
label,
|
||||
start,
|
||||
isCounting,
|
||||
getSmsCode,
|
||||
loading
|
||||
};
|
||||
}
|
@ -1 +1,2 @@
|
||||
export * from './common';
|
||||
export * from './business';
|
||||
|
@ -2,5 +2,3 @@ import { EnumLoginModule } from '@/enum';
|
||||
|
||||
/** 登录模块 */
|
||||
export type LoginModuleKey = keyof typeof EnumLoginModule;
|
||||
|
||||
export type LoginModuleRegexp = LoginModuleKey;
|
||||
|
@ -15,7 +15,7 @@ export async function handlePagePermission(
|
||||
|
||||
const permissions = to.meta.permissions || [];
|
||||
const needLogin = Boolean(to.meta?.requiresAuth) || Boolean(permissions.length);
|
||||
const hasPermission = !permissions.length || permissions.includes(auth.role);
|
||||
const hasPermission = !permissions.length || permissions.includes(auth.userInfo.userRole);
|
||||
|
||||
if (!route.isAddedDynamicRoute) {
|
||||
// 添加动态路由
|
||||
|
@ -1,4 +1,5 @@
|
||||
// import { getLoginModuleRegExp } from '@/utils';
|
||||
import { getLoginModuleRegExp } from '@/utils';
|
||||
import type { LoginModuleKey } from '@/interface';
|
||||
|
||||
/** 固定的路由 */
|
||||
const constantRoutes: AuthRoute.Route[] = [
|
||||
@ -12,8 +13,14 @@ const constantRoutes: AuthRoute.Route[] = [
|
||||
},
|
||||
{
|
||||
name: 'login',
|
||||
path: '/login',
|
||||
path: `/login/:module(${getLoginModuleRegExp()})?`,
|
||||
component: 'blank',
|
||||
props: route => {
|
||||
const moduleType = (route.params.module as LoginModuleKey) || 'pwd-login';
|
||||
return {
|
||||
module: moduleType
|
||||
};
|
||||
},
|
||||
meta: {
|
||||
title: '登录',
|
||||
single: true
|
||||
|
@ -1,15 +1,39 @@
|
||||
import { mockRequest } from '../request';
|
||||
import { userRoutesMiddleware } from '../middleware';
|
||||
|
||||
/**
|
||||
* 获取验证码
|
||||
* @param phone - 手机号
|
||||
* @returns - 返回boolean值表示是否发送成功
|
||||
*/
|
||||
export function fetchSmsCode(phone: string) {
|
||||
return mockRequest.post<boolean>('/getSmsCode', { phone });
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* @param phone - 手机号
|
||||
* @param pwdOrCode - 密码或验证码
|
||||
* @param type - 登录方式: pwd - 密码登录; sms - 验证码登录
|
||||
*/
|
||||
export function fetchLogin(phone: string, pwdOrCode: string, type: 'pwd' | 'sms') {
|
||||
if (type === 'pwd') {
|
||||
return mockRequest.post<ApiAuth.Token>('/loginByPwd', { phone, pwd: pwdOrCode });
|
||||
}
|
||||
return mockRequest.post<ApiAuth.Token>('/loginByCode', { phone, code: pwdOrCode });
|
||||
}
|
||||
|
||||
/** 获取用户信息 */
|
||||
export function fetchUserInfo() {
|
||||
return mockRequest.get<ApiAuth.UserInfo>('/getUserInfo');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户路由数据
|
||||
* @param userId - 用户id
|
||||
* @description 后端根据用户id查询到对应的角色类型,并将路由筛选出对应角色的路由数据返回前端
|
||||
*/
|
||||
export async function fetchUserRoutes(userId: string = 'soybean') {
|
||||
const { data } = await mockRequest<ApiRoute.ResponseRoute>(
|
||||
{ url: '/getUserRoutes', method: 'post', data: { userId } },
|
||||
false
|
||||
);
|
||||
const { data } = await mockRequest.post<ApiRoute.Route>('/getUserRoutes', { userId });
|
||||
return userRoutesMiddleware(data);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import { transformAuthRouteToVueRoute } from '@/utils';
|
||||
|
||||
export function userRoutesMiddleware(data: ApiRoute.ResponseRoute | null) {
|
||||
export function userRoutesMiddleware(data: ApiRoute.Route | null) {
|
||||
if (!data) return [];
|
||||
|
||||
const routes: RouteRecordRaw[] = data.routes.map(item => transformAuthRouteToVueRoute(item));
|
||||
|
@ -6,13 +6,6 @@ import CustomAxiosInstance from './instance';
|
||||
|
||||
type RequestMethod = 'get' | 'post' | 'put' | 'delete';
|
||||
|
||||
type RequestResultHook<T = any> = {
|
||||
data: Ref<T | null>;
|
||||
error: Ref<Service.RequestError | null>;
|
||||
loading: Ref<boolean>;
|
||||
network: Ref<boolean>;
|
||||
};
|
||||
|
||||
interface RequestParam {
|
||||
url: string;
|
||||
method?: RequestMethod;
|
||||
@ -20,9 +13,95 @@ interface RequestParam {
|
||||
axiosConfig?: AxiosRequestConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建请求
|
||||
* @param axiosConfig - axios配置
|
||||
*/
|
||||
export function createRequest(axiosConfig: AxiosRequestConfig) {
|
||||
const customInstance = new CustomAxiosInstance(axiosConfig);
|
||||
|
||||
/**
|
||||
* 异步promise请求
|
||||
* @param param - 请求参数
|
||||
* - url: 请求地址
|
||||
* - method: 请求方法(默认get)
|
||||
* - data: 请求的body的data
|
||||
* - axiosConfig: axios配置
|
||||
*/
|
||||
async function asyncRequest<T = any>(param: RequestParam): Promise<Service.RequestResult<T>> {
|
||||
const { url } = param;
|
||||
const method = param.method || 'get';
|
||||
const { instance } = customInstance;
|
||||
const res = (await getRequestResponse(
|
||||
instance,
|
||||
method,
|
||||
url,
|
||||
param.data,
|
||||
param.axiosConfig
|
||||
)) as Service.RequestResult<T>;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* get请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function get<T = any>(url: string, config?: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'get', axiosConfig: config });
|
||||
}
|
||||
|
||||
/**
|
||||
* post请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function post<T = any>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'post', data, axiosConfig: config });
|
||||
}
|
||||
/**
|
||||
* put请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function put<T = any>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'put', data, axiosConfig: config });
|
||||
}
|
||||
|
||||
/**
|
||||
* delete请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function handleDelete<T = any>(url: string, config: AxiosRequestConfig) {
|
||||
return asyncRequest<T>({ url, method: 'delete', axiosConfig: config });
|
||||
}
|
||||
|
||||
return {
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
delete: handleDelete
|
||||
};
|
||||
}
|
||||
|
||||
type RequestResultHook<T = any> = {
|
||||
data: Ref<T | null>;
|
||||
error: Ref<Service.RequestError | null>;
|
||||
loading: Ref<boolean>;
|
||||
network: Ref<boolean>;
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建hooks请求
|
||||
* @param axiosConfig - axios配置
|
||||
*/
|
||||
export function createHookRequest(axiosConfig: AxiosRequestConfig) {
|
||||
const customInstance = new CustomAxiosInstance(axiosConfig);
|
||||
|
||||
/**
|
||||
* hooks请求
|
||||
* @param param - 请求参数
|
||||
@ -30,33 +109,8 @@ export function createRequest(axiosConfig: AxiosRequestConfig) {
|
||||
* - method: 请求方法(默认get)
|
||||
* - data: 请求的body的data
|
||||
* - axiosConfig: axios配置
|
||||
* @param hookMode - 是否启用hook写法
|
||||
*/
|
||||
function request<T = any>(param: RequestParam, hookMode: true): RequestResultHook<T>;
|
||||
function request<T = any>(param: RequestParam, hookMode: false): Promise<Service.RequestResult<T>>;
|
||||
function request<T = any>(
|
||||
param: RequestParam,
|
||||
hookMode: boolean
|
||||
): RequestResultHook<T> | Promise<Service.RequestResult<T>> {
|
||||
const { url } = param;
|
||||
const method = param.method || 'get';
|
||||
const { instance } = customInstance;
|
||||
if (hookMode) {
|
||||
return useRequest(instance, method, url, param.data, param.axiosConfig);
|
||||
}
|
||||
return asyncRequest(instance, method, url, param.data, param.axiosConfig);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function useRequest<T = any>(
|
||||
instance: AxiosInstance,
|
||||
method: RequestMethod,
|
||||
url: string,
|
||||
bodyData?: any,
|
||||
config?: AxiosRequestConfig
|
||||
): RequestResultHook<T> {
|
||||
function useRequest<T = any>(param: RequestParam): RequestResultHook<T> {
|
||||
const { loading, startLoading, endLoading } = useLoading();
|
||||
const { bool: network, setBool: setNetwork } = useBoolean(window.navigator.onLine);
|
||||
|
||||
@ -72,7 +126,11 @@ function useRequest<T = any>(
|
||||
setNetwork(window.navigator.onLine);
|
||||
}
|
||||
|
||||
getRequestResponse(instance, method, url, bodyData, config).then(handleRequestResult);
|
||||
const { url } = param;
|
||||
const method = param.method || 'get';
|
||||
const { instance } = customInstance;
|
||||
|
||||
getRequestResponse(instance, method, url, param.data, param.axiosConfig).then(handleRequestResult);
|
||||
|
||||
return {
|
||||
data,
|
||||
@ -80,18 +138,51 @@ function useRequest<T = any>(
|
||||
loading,
|
||||
network
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function asyncRequest<T = any>(
|
||||
instance: AxiosInstance,
|
||||
method: RequestMethod,
|
||||
url: string,
|
||||
bodyData?: any,
|
||||
config?: AxiosRequestConfig
|
||||
): Promise<Service.RequestResult<T>> {
|
||||
const res = (await getRequestResponse(instance, method, url, bodyData, config)) as Service.RequestResult<T>;
|
||||
/**
|
||||
* get请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function get<T = any>(url: string, config?: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'get', axiosConfig: config });
|
||||
}
|
||||
|
||||
return res;
|
||||
/**
|
||||
* post请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function post<T = any>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'post', data, axiosConfig: config });
|
||||
}
|
||||
/**
|
||||
* put请求
|
||||
* @param url - 请求地址
|
||||
* @param data - 请求的body的data
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function put<T = any>(url: string, data?: any, config?: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'put', data, axiosConfig: config });
|
||||
}
|
||||
|
||||
/**
|
||||
* delete请求
|
||||
* @param url - 请求地址
|
||||
* @param config - axios配置
|
||||
*/
|
||||
function handleDelete<T = any>(url: string, config: AxiosRequestConfig) {
|
||||
return useRequest<T>({ url, method: 'delete', axiosConfig: config });
|
||||
}
|
||||
|
||||
return {
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
delete: handleDelete
|
||||
};
|
||||
}
|
||||
|
||||
async function getRequestResponse(
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { ref, computed, reactive } from 'vue';
|
||||
import { ref, computed, reactive, unref } from 'vue';
|
||||
import type { Ref, ComputedRef } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { getUserInfo, getToken } from '@/utils';
|
||||
import { router as globalRouter } from '@/router';
|
||||
import { useRouterPush, useRouteQuery } from '@/composables';
|
||||
import { useLoading } from '@/hooks';
|
||||
import { fetchLogin, fetchUserInfo } from '@/service';
|
||||
import { getUserInfo, getToken, setUserInfo, setToken, setRefreshToken, clearAuthStorage } from '@/utils';
|
||||
|
||||
interface AuthStore {
|
||||
/** 用户信息 */
|
||||
@ -10,21 +14,94 @@ interface AuthStore {
|
||||
token: Ref<string>;
|
||||
/** 是否登录 */
|
||||
isLogin: ComputedRef<boolean>;
|
||||
/** 用户角色 */
|
||||
role: Ref<Auth.RoleType>;
|
||||
/**
|
||||
* 重置authStore
|
||||
* 是否需要跳转页面(例如当前页面是需要权限的,登出后需要跳转到登录页面)
|
||||
*/
|
||||
resetAuthStore(pushRoute: boolean): void;
|
||||
/** 登录的加载状态 */
|
||||
loginLoding: Ref<boolean>;
|
||||
/**
|
||||
* 登录
|
||||
* @param phone - 手机号
|
||||
* @param pwdOrCode - 密码或验证码
|
||||
* @param type - 登录方式: pwd - 密码登录; sms - 验证码登录
|
||||
*/
|
||||
login(phone: string, pwdOrCode: string, type: 'pwd' | 'sms'): void;
|
||||
}
|
||||
|
||||
export const useAuthStore = defineStore('auth-store', () => {
|
||||
const { toLogin, toLoginRedirect } = useRouterPush(false);
|
||||
const { loginRedirect } = useRouteQuery(false);
|
||||
const { loading: loginLoding, startLoading: startLoginLoading, endLoading: endLoginLoading } = useLoading();
|
||||
|
||||
const userInfo: Auth.UserInfo = reactive(getUserInfo());
|
||||
function handleSetUserInfo(data: Auth.UserInfo) {
|
||||
Object.assign(userInfo, data);
|
||||
}
|
||||
|
||||
const token = ref(getToken());
|
||||
function handleSetToken(data: string) {
|
||||
token.value = data;
|
||||
}
|
||||
|
||||
const isLogin = computed(() => Boolean(token.value));
|
||||
const role = ref<Auth.RoleType>('super');
|
||||
|
||||
function resetAuthStore(pushRoute: boolean = true) {
|
||||
const auth = useAuthStore();
|
||||
const route = unref(globalRouter.currentRoute);
|
||||
|
||||
clearAuthStorage();
|
||||
auth.$reset();
|
||||
|
||||
if (pushRoute && route.meta.requiresAuth) {
|
||||
toLogin();
|
||||
}
|
||||
}
|
||||
|
||||
async function login(phone: string, pwdOrCode: string, type: 'pwd' | 'sms') {
|
||||
startLoginLoading();
|
||||
const { data } = await fetchLogin(phone, pwdOrCode, type);
|
||||
if (data) {
|
||||
await loginByToken(data);
|
||||
}
|
||||
endLoginLoading();
|
||||
}
|
||||
|
||||
async function loginByToken(backendToken: ApiAuth.Token) {
|
||||
// 1.先把token存储到缓存中
|
||||
const { token, refreshToken } = backendToken;
|
||||
setToken(token);
|
||||
setRefreshToken(refreshToken);
|
||||
|
||||
// 2.获取用户信息
|
||||
const { data } = await fetchUserInfo();
|
||||
if (data) {
|
||||
// 成功后把用户信息存储到缓存中
|
||||
setUserInfo(data);
|
||||
handleSetToken(token);
|
||||
handleSetUserInfo(data);
|
||||
// 3. 跳转登录后的地址
|
||||
toLoginRedirect(loginRedirect.value);
|
||||
// 4.登录成功弹出欢迎提示
|
||||
window.$notification?.success({
|
||||
title: '登录成功!',
|
||||
content: `欢迎回来,${userInfo.userName}!`,
|
||||
duration: 3000
|
||||
});
|
||||
} else {
|
||||
// 不成功则重置状态
|
||||
resetAuthStore(false);
|
||||
}
|
||||
}
|
||||
|
||||
const authStore: AuthStore = {
|
||||
userInfo,
|
||||
token,
|
||||
isLogin,
|
||||
role
|
||||
resetAuthStore,
|
||||
loginLoding,
|
||||
login
|
||||
};
|
||||
|
||||
return authStore;
|
||||
|
@ -26,7 +26,7 @@ interface RouteStore {
|
||||
* 获取路由路径
|
||||
* @description getRouteName 和 getRoutePath 优先使用 getRouteName
|
||||
*/
|
||||
getRoutePath(key: AuthRoute.RouteKey): AuthRoute.RoutePath<''> | undefined;
|
||||
getRoutePath(key: AuthRoute.RouteKey): AuthRoute.RoutePath | undefined;
|
||||
/** 获取路由路径 */
|
||||
getRouteTitle(key: AuthRoute.RouteKey): string | undefined;
|
||||
}
|
||||
|
@ -37,3 +37,27 @@ export function getThemeColors(colors: [ColorType, string][]) {
|
||||
|
||||
return themeColor;
|
||||
}
|
||||
|
||||
/** windicss 暗黑模式 */
|
||||
export function handleWindicssDarkMode() {
|
||||
const DARK_CLASS = 'dark';
|
||||
function getHtmlElement() {
|
||||
return document.querySelector('html');
|
||||
}
|
||||
function addDarkClass() {
|
||||
const html = getHtmlElement();
|
||||
if (html) {
|
||||
html.classList.add(DARK_CLASS);
|
||||
}
|
||||
}
|
||||
function removeDarkClass() {
|
||||
const html = getHtmlElement();
|
||||
if (html) {
|
||||
html.classList.remove(DARK_CLASS);
|
||||
}
|
||||
}
|
||||
return {
|
||||
addDarkClass,
|
||||
removeDarkClass
|
||||
};
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import type { Ref, ComputedRef } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useThemeVars } from 'naive-ui';
|
||||
import type { GlobalThemeOverrides } from 'naive-ui';
|
||||
import { useThemeVars, darkTheme, useOsTheme } from 'naive-ui';
|
||||
import type { GlobalThemeOverrides, GlobalTheme } from 'naive-ui';
|
||||
import { kebabCase } from 'lodash-es';
|
||||
import { useBoolean } from '@/hooks';
|
||||
import { getColorPalette } from '@/utils';
|
||||
import { getThemeColors } from './helpers';
|
||||
import { getThemeColors, handleWindicssDarkMode } from './helpers';
|
||||
|
||||
interface OtherColor {
|
||||
/** 信息 */
|
||||
@ -18,19 +19,31 @@ interface OtherColor {
|
||||
error: string;
|
||||
}
|
||||
|
||||
type BuiltInGlobalTheme = Omit<Required<GlobalTheme>, 'InternalSelectMenu' | 'InternalSelection'>;
|
||||
|
||||
interface ThemeStore {
|
||||
/** 暗黑模式 */
|
||||
darkMode: Ref<boolean>;
|
||||
/** 设置暗黑模式 */
|
||||
setDarkMode(dark: boolean): void;
|
||||
/** 切换/关闭 暗黑模式 */
|
||||
toggleDarkMode(dark: boolean): void;
|
||||
/** 主题颜色 */
|
||||
themeColor: Ref<string>;
|
||||
/** 其他颜色 */
|
||||
otherColor: ComputedRef<OtherColor>;
|
||||
/** naiveUI的主题配置 */
|
||||
naiveThemeOverrides: ComputedRef<GlobalThemeOverrides>;
|
||||
/** naive-ui暗黑主题 */
|
||||
naiveTheme: ComputedRef<BuiltInGlobalTheme | undefined>;
|
||||
}
|
||||
|
||||
type ThemeVarsKeys = keyof Exclude<GlobalThemeOverrides['common'], undefined>;
|
||||
|
||||
export const useThemeStore = defineStore('theme-store', () => {
|
||||
const themeVars = useThemeVars();
|
||||
const { bool: darkMode, setBool: setDarkMode, toggle: toggleDarkMode } = useBoolean();
|
||||
const { addDarkClass, removeDarkClass } = handleWindicssDarkMode();
|
||||
|
||||
const themeColor = ref('#1890ff');
|
||||
const otherColor = computed<OtherColor>(() => ({
|
||||
@ -62,6 +75,12 @@ export const useThemeStore = defineStore('theme-store', () => {
|
||||
};
|
||||
});
|
||||
|
||||
/** naive-ui暗黑主题 */
|
||||
const naiveTheme = computed(() => (darkMode.value ? darkTheme : undefined));
|
||||
|
||||
/** 操作系统暗黑主题 */
|
||||
const osTheme = useOsTheme();
|
||||
|
||||
/** 添加css vars至html */
|
||||
function addThemeCssVarsToHtml() {
|
||||
if (document.documentElement.style.cssText) return;
|
||||
@ -82,10 +101,40 @@ export const useThemeStore = defineStore('theme-store', () => {
|
||||
|
||||
init();
|
||||
|
||||
// 监听操作系统主题模式
|
||||
watch(
|
||||
osTheme,
|
||||
newValue => {
|
||||
const isDark = newValue === 'dark';
|
||||
if (isDark) {
|
||||
setDarkMode(true);
|
||||
} else {
|
||||
setDarkMode(false);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
// 监听主题的暗黑模式
|
||||
watch(
|
||||
() => darkMode.value,
|
||||
newValue => {
|
||||
if (newValue) {
|
||||
addDarkClass();
|
||||
} else {
|
||||
removeDarkClass();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const themeStore: ThemeStore = {
|
||||
darkMode,
|
||||
setDarkMode,
|
||||
toggleDarkMode,
|
||||
themeColor,
|
||||
otherColor,
|
||||
naiveThemeOverrides
|
||||
naiveThemeOverrides,
|
||||
naiveTheme
|
||||
};
|
||||
|
||||
return themeStore;
|
||||
|
10
src/typings/api/auth.d.ts
vendored
Normal file
10
src/typings/api/auth.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/** 后端返回的用户权益相关类型 */
|
||||
declare namespace ApiAuth {
|
||||
/** 返回的token和刷新token */
|
||||
interface Token {
|
||||
token: string;
|
||||
refreshToken: string;
|
||||
}
|
||||
/** 返回的用户信息 */
|
||||
type UserInfo = Auth.UserInfo;
|
||||
}
|
2
src/typings/api/route.d.ts
vendored
2
src/typings/api/route.d.ts
vendored
@ -1,7 +1,7 @@
|
||||
/** 后端返回的路由相关类型 */
|
||||
declare namespace ApiRoute {
|
||||
/** 后端返回的路由数据类型 */
|
||||
interface ResponseRoute {
|
||||
interface Route {
|
||||
/** 动态路由 */
|
||||
routes: AuthRoute.Route[];
|
||||
/** 路由首页对应的key */
|
||||
|
22
src/typings/business/auth.d.ts
vendored
22
src/typings/business/auth.d.ts
vendored
@ -1,15 +1,5 @@
|
||||
/** 用户相关模块 */
|
||||
declare namespace Auth {
|
||||
/** 用户信息 */
|
||||
interface UserInfo {
|
||||
/** 用户id */
|
||||
userId: string;
|
||||
/** 用户名 */
|
||||
userName: string;
|
||||
/** 用户手机号 */
|
||||
userPhone: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户角色类型
|
||||
* - super: 超级管理员
|
||||
@ -18,4 +8,16 @@ declare namespace Auth {
|
||||
* - visitor: 游客
|
||||
*/
|
||||
type RoleType = 'super' | 'admin' | 'test' | 'visitor';
|
||||
|
||||
/** 用户信息 */
|
||||
interface UserInfo {
|
||||
/** 用户id */
|
||||
userId: string;
|
||||
/** 用户名 */
|
||||
userName: string;
|
||||
/** 用户手机号 */
|
||||
userPhone: string;
|
||||
/** 用户角色类型 */
|
||||
userRole: RoleType;
|
||||
}
|
||||
}
|
||||
|
9
src/typings/common/route.d.ts
vendored
9
src/typings/common/route.d.ts
vendored
@ -24,7 +24,7 @@ declare namespace AuthRoute {
|
||||
: `/${Key}`;
|
||||
|
||||
/** 路由路径 */
|
||||
type RoutePath<Key extends string = string> =
|
||||
type RoutePath<Key extends string = '' | LoginPath> =
|
||||
| '/'
|
||||
| Exclude<KeyToPath<RouteKey>, '/root' | '/redirect'>
|
||||
| Key
|
||||
@ -65,8 +65,11 @@ declare namespace AuthRoute {
|
||||
order?: number;
|
||||
};
|
||||
|
||||
/** 登录路由路径 */
|
||||
type LoginPath = `/login/:module(${string})?`;
|
||||
|
||||
/** 单个路由的类型结构(后端返回此类型结构的路由) */
|
||||
interface Route<T extends string = ''> {
|
||||
interface Route<T extends string = '' | LoginPath> {
|
||||
/** 路由名称(路由唯一标识) */
|
||||
name: RouteKey;
|
||||
/** 路由路径 */
|
||||
@ -85,5 +88,7 @@ declare namespace AuthRoute {
|
||||
children?: Route[];
|
||||
/** 路由描述 */
|
||||
meta: RouteMeta;
|
||||
/** 属性 */
|
||||
props?: boolean | Record<string, any> | ((to: any) => Record<string, any>);
|
||||
}
|
||||
}
|
||||
|
2
src/typings/common/util.d.ts
vendored
2
src/typings/common/util.d.ts
vendored
@ -12,6 +12,4 @@ declare namespace Util {
|
||||
type UnionToTuple<T, U = T> = [T] extends [never]
|
||||
? []
|
||||
: [LastInUnion<T>, ...UnionToTuple<Exclude<U, LastInUnion<T>>>];
|
||||
|
||||
type Inter = UnionToTuple<'1' | '2'>;
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ export function getUserInfo() {
|
||||
const emptyInfo: Auth.UserInfo = {
|
||||
userId: '',
|
||||
userName: '',
|
||||
userPhone: ''
|
||||
userPhone: '',
|
||||
userRole: 'visitor'
|
||||
};
|
||||
const userInfo: Auth.UserInfo = getLocal<Auth.UserInfo>(EnumStorageKey['user-info']) || emptyInfo;
|
||||
return userInfo;
|
||||
|
@ -1,4 +1,5 @@
|
||||
export * from './typeof';
|
||||
export * from './console';
|
||||
export * from './color';
|
||||
export * from './number';
|
||||
export * from './design-pattern';
|
||||
|
23
src/utils/common/number.ts
Normal file
23
src/utils/common/number.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 根据数字获取对应的汉字
|
||||
* @param num - 数字(0-10)
|
||||
*/
|
||||
export function getHanByNumber(num: number) {
|
||||
const HAN_STR = '零一二三四五六七八九十';
|
||||
return HAN_STR.charAt(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将总秒数转换成 分:秒
|
||||
* @param seconds - 秒
|
||||
*/
|
||||
export function transformToTimeCountDown(seconds: number) {
|
||||
const SECONDS_A_MINUTE = 60;
|
||||
function fillZero(num: number) {
|
||||
return num.toString().padStart(2, '0');
|
||||
}
|
||||
const minuteNum = Math.floor(seconds / SECONDS_A_MINUTE);
|
||||
const minute = fillZero(minuteNum);
|
||||
const second = fillZero(seconds - minuteNum * SECONDS_A_MINUTE);
|
||||
return `${minute}: ${second}`;
|
||||
}
|
1
src/utils/form/index.ts
Normal file
1
src/utils/form/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './rule';
|
73
src/utils/form/rule.ts
Normal file
73
src/utils/form/rule.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import { Ref } from 'vue';
|
||||
import type { FormItemRule } from 'naive-ui';
|
||||
import { REGEXP_PHONE, REGEXP_PWD, REGEXP_CODE_SIX, REGEXP_EMAIL } from '@/config';
|
||||
|
||||
/** 表单规则 */
|
||||
interface CustomFormRules {
|
||||
/** 手机号码 */
|
||||
phone: FormItemRule[];
|
||||
/** 密码 */
|
||||
pwd: FormItemRule[];
|
||||
/** 验证码 */
|
||||
code: FormItemRule[];
|
||||
/** 邮箱 */
|
||||
email: FormItemRule[];
|
||||
}
|
||||
|
||||
/** 表单规则 */
|
||||
export const formRules: CustomFormRules = {
|
||||
phone: [
|
||||
{ required: true, message: '请输入手机号码' },
|
||||
{ pattern: REGEXP_PHONE, message: '手机号码格式错误', trigger: 'input' }
|
||||
],
|
||||
pwd: [
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ pattern: REGEXP_PWD, message: '密码为8-18位数字/字符/符号,至少2种组合', trigger: 'input' }
|
||||
],
|
||||
code: [
|
||||
{ required: true, message: '请输入验证码' },
|
||||
{ pattern: REGEXP_CODE_SIX, message: '验证码格式错误', trigger: 'input' }
|
||||
],
|
||||
email: [{ pattern: REGEXP_EMAIL, message: '邮箱格式错误', trigger: 'blur' }]
|
||||
};
|
||||
|
||||
/** 获取确认密码的表单规则 */
|
||||
export function getConfirmPwdRule(pwd: Ref<string>) {
|
||||
const confirmPwdRule: FormItemRule[] = [
|
||||
{ required: true, message: '请输入确认密码' },
|
||||
{
|
||||
validator: (rule, value) => {
|
||||
if (!isBlankString(value) && value !== pwd.value) {
|
||||
return Promise.reject(rule.message);
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
message: '输入的值与密码不一致',
|
||||
trigger: 'input'
|
||||
}
|
||||
];
|
||||
return confirmPwdRule;
|
||||
}
|
||||
|
||||
/** 获取图片验证码的表单规则 */
|
||||
export function getImgCodeRule(imgCode: Ref<string>) {
|
||||
const imgCodeRule: FormItemRule[] = [
|
||||
{ required: true, message: '请输入验证码' },
|
||||
{
|
||||
validator: (rule, value) => {
|
||||
if (!isBlankString(value) && value !== imgCode.value) {
|
||||
return Promise.reject(rule.message);
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
message: '验证码不正确',
|
||||
trigger: 'blur'
|
||||
}
|
||||
];
|
||||
return imgCodeRule;
|
||||
}
|
||||
|
||||
/** 是否为空字符串 */
|
||||
function isBlankString(str: string) {
|
||||
return str.trim() === '';
|
||||
}
|
@ -3,3 +3,4 @@ export * from './storage';
|
||||
export * from './service';
|
||||
export * from './auth';
|
||||
export * from './router';
|
||||
export * from './form';
|
||||
|
@ -40,12 +40,18 @@ export function transformAuthRouteToVueRoute(item: AuthRoute.Route) {
|
||||
consoleError('路由组件解析失败: ', item);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasProps(item) && !isSingleRoute(item)) {
|
||||
(itemRoute as any).props = item.props;
|
||||
}
|
||||
|
||||
if (isSingleRoute(item)) {
|
||||
itemRoute.children = [
|
||||
{
|
||||
path: '',
|
||||
name: item.name,
|
||||
component: getViewComponent(item.name)
|
||||
component: getViewComponent(item.name),
|
||||
props: hasProps(item) ? item.props : undefined
|
||||
}
|
||||
];
|
||||
} else if (hasChildren(item)) {
|
||||
@ -67,6 +73,10 @@ function hasChildren(item: AuthRoute.Route) {
|
||||
return Boolean(item.children && item.children.length);
|
||||
}
|
||||
|
||||
function hasProps(item: AuthRoute.Route) {
|
||||
return Boolean(item.props);
|
||||
}
|
||||
|
||||
function isSingleRoute(item: AuthRoute.Route) {
|
||||
return Boolean(item.meta.single);
|
||||
}
|
||||
|
61
src/views/system/login/components/BindWechat/index.vue
Normal file
61
src/views/system/login/components/BindWechat/index.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<n-form ref="formRef" :model="model" :rules="rules" size="large" :show-label="false">
|
||||
<n-form-item path="phone">
|
||||
<n-input v-model:value="model.phone" placeholder="手机号码" />
|
||||
</n-form-item>
|
||||
<n-form-item path="code">
|
||||
<div class="flex-y-center w-full">
|
||||
<n-input v-model:value="model.code" placeholder="验证码" />
|
||||
<div class="w-18px"></div>
|
||||
<n-button size="large" :disabled="isCounting" :loading="smsLoading" @click="handleSmsCode">
|
||||
{{ label }}
|
||||
</n-button>
|
||||
</div>
|
||||
</n-form-item>
|
||||
<n-space :vertical="true" size="large">
|
||||
<n-button type="primary" size="large" :block="true" :round="true" @click="handleSubmit">确定</n-button>
|
||||
<n-button size="large" :block="true" :round="true" @click="toLoginModule('pwd-login')">返回</n-button>
|
||||
</n-space>
|
||||
</n-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { NForm, NFormItem, NInput, NSpace, NButton } from 'naive-ui';
|
||||
import type { FormInst } from 'naive-ui';
|
||||
import { useRouterPush } from '@/composables';
|
||||
import { useSmsCode } from '@/hooks';
|
||||
import { formRules } from '@/utils';
|
||||
|
||||
const { toLoginModule } = useRouterPush();
|
||||
const { label, isCounting, loading: smsLoading, getSmsCode } = useSmsCode();
|
||||
|
||||
const formRef = ref<(HTMLElement & FormInst) | null>(null);
|
||||
const model = reactive({
|
||||
phone: '',
|
||||
code: '',
|
||||
imgCode: ''
|
||||
});
|
||||
const rules = {
|
||||
phone: formRules.phone,
|
||||
code: formRules.code
|
||||
};
|
||||
|
||||
function handleSmsCode() {
|
||||
getSmsCode(model.phone);
|
||||
}
|
||||
|
||||
function handleSubmit(e: MouseEvent) {
|
||||
if (!formRef.value) return;
|
||||
e.preventDefault();
|
||||
|
||||
formRef.value.validate(errors => {
|
||||
if (!errors) {
|
||||
window.$message?.success('验证成功');
|
||||
} else {
|
||||
window.$message?.error('验证失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
81
src/views/system/login/components/CodeLogin/index.vue
Normal file
81
src/views/system/login/components/CodeLogin/index.vue
Normal file
@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<n-form ref="formRef" :model="model" :rules="rules" size="large" :show-label="false">
|
||||
<n-form-item path="phone">
|
||||
<n-input v-model:value="model.phone" placeholder="手机号码" />
|
||||
</n-form-item>
|
||||
<n-form-item path="code">
|
||||
<div class="flex-y-center w-full">
|
||||
<n-input v-model:value="model.code" placeholder="验证码" />
|
||||
<div class="w-18px"></div>
|
||||
<n-button size="large" :disabled="isCounting" :loading="smsLoading" @click="handleSmsCode">
|
||||
{{ label }}
|
||||
</n-button>
|
||||
</div>
|
||||
</n-form-item>
|
||||
<n-form-item path="imgCode">
|
||||
<n-input v-model:value="model.imgCode" placeholder="验证码,点击图片刷新" />
|
||||
<div class="pl-8px">
|
||||
<image-verify v-model:code="imgCode" />
|
||||
</div>
|
||||
</n-form-item>
|
||||
<n-space :vertical="true" size="large">
|
||||
<n-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:block="true"
|
||||
:round="true"
|
||||
:loading="auth.loginLoding"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
确定
|
||||
</n-button>
|
||||
<n-button size="large" :block="true" :round="true" @click="toLoginModule('pwd-login')">返回</n-button>
|
||||
</n-space>
|
||||
</n-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { NForm, NFormItem, NInput, NSpace, NButton } from 'naive-ui';
|
||||
import type { FormInst } from 'naive-ui';
|
||||
import { ImageVerify } from '@/components';
|
||||
import { useAuthStore } from '@/store';
|
||||
import { useRouterPush } from '@/composables';
|
||||
import { useSmsCode } from '@/hooks';
|
||||
import { formRules, getImgCodeRule } from '@/utils';
|
||||
|
||||
const auth = useAuthStore();
|
||||
const { login } = useAuthStore();
|
||||
const { toLoginModule } = useRouterPush();
|
||||
const { label, isCounting, loading: smsLoading, getSmsCode } = useSmsCode();
|
||||
|
||||
const formRef = ref<(HTMLElement & FormInst) | null>(null);
|
||||
const model = reactive({
|
||||
phone: '',
|
||||
code: '',
|
||||
imgCode: ''
|
||||
});
|
||||
const imgCode = ref('');
|
||||
const rules = {
|
||||
phone: formRules.phone,
|
||||
code: formRules.code,
|
||||
imgCode: getImgCodeRule(imgCode)
|
||||
};
|
||||
|
||||
function handleSmsCode() {
|
||||
getSmsCode(model.phone);
|
||||
}
|
||||
|
||||
function handleSubmit(e: MouseEvent) {
|
||||
if (!formRef.value) return;
|
||||
e.preventDefault();
|
||||
|
||||
formRef.value.validate(errors => {
|
||||
if (!errors) {
|
||||
const { phone, code } = model;
|
||||
login(phone, code, 'sms');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="absolute-lt wh-full overflow-hidden">
|
||||
<div class="absolute-lt z-1 wh-full overflow-hidden">
|
||||
<div class="absolute -right-300px -top-900px">
|
||||
<corner-top :start-color="lightColor" :end-color="darkColor" />
|
||||
</div>
|
||||
|
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<n-space :vertical="true">
|
||||
<n-divider class="!mb-0 text-14px text-[#666]">其他登录方式</n-divider>
|
||||
<div class="flex-center">
|
||||
<n-button :text="true">
|
||||
<icon-mdi-wechat class="text-22px text-[#888] hover:text-[#52BF5E]" />
|
||||
</n-button>
|
||||
</div>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { NSpace, NDivider, NButton } from 'naive-ui';
|
||||
</script>
|
||||
<style scoped></style>
|
@ -0,0 +1,3 @@
|
||||
import OtherLogin from './OtherLogin.vue';
|
||||
|
||||
export { OtherLogin };
|
75
src/views/system/login/components/PwdLogin/index.vue
Normal file
75
src/views/system/login/components/PwdLogin/index.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<n-form ref="formRef" :model="model" :rules="rules" size="large" :show-label="false">
|
||||
<n-form-item path="phone">
|
||||
<n-input v-model:value="model.phone" placeholder="请输入手机号码" />
|
||||
</n-form-item>
|
||||
<n-form-item path="pwd">
|
||||
<n-input v-model:value="model.pwd" type="password" show-password-on="click" placeholder="请输入密码" />
|
||||
</n-form-item>
|
||||
<n-space :vertical="true" :size="24">
|
||||
<div class="flex-y-center justify-between">
|
||||
<n-checkbox v-model:checked="rememberMe">记住我</n-checkbox>
|
||||
<n-button :text="true">忘记密码?</n-button>
|
||||
</div>
|
||||
<n-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:block="true"
|
||||
:round="true"
|
||||
:loading="auth.loginLoding"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
确定
|
||||
</n-button>
|
||||
<div class="flex-y-center justify-between">
|
||||
<n-button class="flex-1" :block="true" @click="toLoginModule('code-login')">
|
||||
{{ EnumLoginModule['code-login'] }}
|
||||
</n-button>
|
||||
<div class="w-12px"></div>
|
||||
<n-button class="flex-1" :block="true" @click="toLoginModule('register')">
|
||||
{{ EnumLoginModule.register }}
|
||||
</n-button>
|
||||
</div>
|
||||
</n-space>
|
||||
<other-login />
|
||||
</n-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { NForm, NFormItem, NInput, NSpace, NCheckbox, NButton } from 'naive-ui';
|
||||
import type { FormInst, FormRules } from 'naive-ui';
|
||||
import { EnumLoginModule } from '@/enum';
|
||||
import { useAuthStore } from '@/store';
|
||||
import { useRouterPush } from '@/composables';
|
||||
import { formRules } from '@/utils';
|
||||
import { OtherLogin } from './components';
|
||||
|
||||
const auth = useAuthStore();
|
||||
const { login } = useAuthStore();
|
||||
const { toLoginModule } = useRouterPush();
|
||||
|
||||
const formRef = ref<(HTMLElement & FormInst) | null>(null);
|
||||
const model = reactive({
|
||||
phone: '',
|
||||
pwd: ''
|
||||
});
|
||||
const rules: FormRules = {
|
||||
phone: formRules.phone,
|
||||
pwd: formRules.pwd
|
||||
};
|
||||
const rememberMe = ref(false);
|
||||
|
||||
function handleSubmit(e: MouseEvent) {
|
||||
if (!formRef.value) return;
|
||||
e.preventDefault();
|
||||
|
||||
formRef.value.validate(errors => {
|
||||
if (!errors) {
|
||||
const { phone, pwd } = model;
|
||||
login(phone, pwd, 'pwd');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
75
src/views/system/login/components/Register/index.vue
Normal file
75
src/views/system/login/components/Register/index.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<n-form ref="formRef" :model="model" :rules="rules" size="large" :show-label="false">
|
||||
<n-form-item path="phone">
|
||||
<n-input v-model:value="model.phone" placeholder="手机号码" />
|
||||
</n-form-item>
|
||||
<n-form-item path="code">
|
||||
<div class="flex-y-center w-full">
|
||||
<n-input v-model:value="model.code" placeholder="验证码" />
|
||||
<div class="w-18px"></div>
|
||||
<n-button size="large" :disabled="isCounting" :loading="smsLoading" @click="handleSmsCode">
|
||||
{{ label }}
|
||||
</n-button>
|
||||
</div>
|
||||
</n-form-item>
|
||||
<n-form-item path="pwd">
|
||||
<n-input v-model:value="model.pwd" placeholder="密码" />
|
||||
</n-form-item>
|
||||
<n-form-item path="confirmPwd">
|
||||
<n-input v-model:value="model.confirmPwd" placeholder="确认密码" />
|
||||
</n-form-item>
|
||||
<n-space :vertical="true" size="large">
|
||||
<login-agreement v-model:value="agreement" />
|
||||
<n-button type="primary" size="large" :block="true" :round="true" @click="handleSubmit">确定</n-button>
|
||||
<n-button size="large" :block="true" :round="true" @click="toLoginModule('pwd-login')">返回</n-button>
|
||||
</n-space>
|
||||
</n-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, toRefs } from 'vue';
|
||||
import { NForm, NFormItem, NInput, NSpace, NButton } from 'naive-ui';
|
||||
import type { FormInst, FormRules } from 'naive-ui';
|
||||
import { LoginAgreement } from '@/components';
|
||||
import { useRouterPush } from '@/composables';
|
||||
import { useSmsCode } from '@/hooks';
|
||||
import { formRules, getConfirmPwdRule } from '@/utils';
|
||||
|
||||
const { toLoginModule } = useRouterPush();
|
||||
const { label, isCounting, loading: smsLoading, start } = useSmsCode();
|
||||
|
||||
const formRef = ref<(HTMLElement & FormInst) | null>(null);
|
||||
const model = reactive({
|
||||
phone: '',
|
||||
code: '',
|
||||
pwd: '',
|
||||
confirmPwd: ''
|
||||
});
|
||||
const rules: FormRules = {
|
||||
phone: formRules.phone,
|
||||
code: formRules.code,
|
||||
pwd: formRules.pwd,
|
||||
confirmPwd: getConfirmPwdRule(toRefs(model).pwd)
|
||||
};
|
||||
|
||||
const agreement = ref(false);
|
||||
|
||||
function handleSmsCode() {
|
||||
start();
|
||||
}
|
||||
|
||||
function handleSubmit(e: MouseEvent) {
|
||||
if (!formRef.value) return;
|
||||
e.preventDefault();
|
||||
|
||||
formRef.value.validate(errors => {
|
||||
if (!errors) {
|
||||
if (!agreement.value) return;
|
||||
window.$message?.success('验证成功');
|
||||
} else {
|
||||
window.$message?.error('验证失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
71
src/views/system/login/components/ResetPwd/index.vue
Normal file
71
src/views/system/login/components/ResetPwd/index.vue
Normal file
@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<n-form ref="formRef" :model="model" :rules="rules" size="large" :show-label="false">
|
||||
<n-form-item path="phone">
|
||||
<n-input v-model:value="model.phone" placeholder="手机号码" />
|
||||
</n-form-item>
|
||||
<n-form-item path="code">
|
||||
<div class="flex-y-center w-full">
|
||||
<n-input v-model:value="model.code" placeholder="验证码" />
|
||||
<div class="w-18px"></div>
|
||||
<n-button size="large" :disabled="isCounting" :loading="smsLoading" @click="handleSmsCode">
|
||||
{{ label }}
|
||||
</n-button>
|
||||
</div>
|
||||
</n-form-item>
|
||||
<n-form-item path="pwd">
|
||||
<n-input v-model:value="model.pwd" placeholder="密码" />
|
||||
</n-form-item>
|
||||
<n-form-item path="confirmPwd">
|
||||
<n-input v-model:value="model.confirmPwd" placeholder="确认密码" />
|
||||
</n-form-item>
|
||||
<n-space :vertical="true" size="large">
|
||||
<n-button type="primary" size="large" :block="true" :round="true" @click="handleSubmit">确定</n-button>
|
||||
<n-button size="large" :block="true" :round="true" @click="toLoginModule('pwd-login')">返回</n-button>
|
||||
</n-space>
|
||||
</n-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, toRefs } from 'vue';
|
||||
import { NForm, NFormItem, NInput, NSpace, NButton, useMessage } from 'naive-ui';
|
||||
import type { FormInst, FormRules } from 'naive-ui';
|
||||
import { useRouterPush } from '@/composables';
|
||||
import { useSmsCode } from '@/hooks';
|
||||
import { formRules, getConfirmPwdRule } from '@/utils';
|
||||
|
||||
const message = useMessage();
|
||||
const { toLoginModule } = useRouterPush();
|
||||
const { label, isCounting, loading: smsLoading, start } = useSmsCode();
|
||||
|
||||
const formRef = ref<(HTMLElement & FormInst) | null>(null);
|
||||
const model = reactive({
|
||||
phone: '',
|
||||
code: '',
|
||||
pwd: '',
|
||||
confirmPwd: ''
|
||||
});
|
||||
const rules: FormRules = {
|
||||
phone: formRules.phone,
|
||||
code: formRules.code,
|
||||
pwd: formRules.pwd,
|
||||
confirmPwd: getConfirmPwdRule(toRefs(model).pwd)
|
||||
};
|
||||
|
||||
function handleSmsCode() {
|
||||
start();
|
||||
}
|
||||
|
||||
function handleSubmit(e: MouseEvent) {
|
||||
if (!formRef.value) return;
|
||||
e.preventDefault();
|
||||
|
||||
formRef.value.validate(errors => {
|
||||
if (!errors) {
|
||||
message.success('验证成功');
|
||||
} else {
|
||||
message.error('验证失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
@ -1,3 +1,8 @@
|
||||
import LoginBg from './LoginBg/index.vue';
|
||||
import PwdLogin from './PwdLogin/index.vue';
|
||||
import CodeLogin from './CodeLogin/index.vue';
|
||||
import Register from './Register/index.vue';
|
||||
import ResetPwd from './ResetPwd/index.vue';
|
||||
import BindWechat from './BindWechat/index.vue';
|
||||
|
||||
export { LoginBg };
|
||||
export { LoginBg, PwdLogin, CodeLogin, Register, ResetPwd, BindWechat };
|
||||
|
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<div class="relative flex-center wh-full" :style="{ backgroundColor: bgColor }">
|
||||
<n-card :bordered="false" size="large" class="z-20 !w-auto rounded-20px shadow-sm">
|
||||
<dark-mode-switch
|
||||
:dark="theme.darkMode"
|
||||
class="absolute left-48px top-24px z-3 text-20px"
|
||||
@update:dark="setDarkMode"
|
||||
/>
|
||||
<n-card :bordered="false" size="large" class="z-4 !w-auto rounded-20px shadow-sm">
|
||||
<div class="w-360px">
|
||||
<header class="flex-y-center justify-between">
|
||||
<div class="w-70px h-70px rounded-35px overflow-hidden">
|
||||
@ -9,30 +14,70 @@
|
||||
<n-gradient-text type="primary" :size="28">{{ title }}</n-gradient-text>
|
||||
</header>
|
||||
<main class="pt-24px">
|
||||
<h3 class="text-18px text-primary font-medium">登录</h3>
|
||||
<h3 class="text-18px text-primary font-medium">{{ activeModule.label }}</h3>
|
||||
<div class="pt-24px">
|
||||
<transition>
|
||||
<component :is="activeModule.component" />
|
||||
</transition>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</n-card>
|
||||
<login-bg :theme-color="theme.themeColor" />
|
||||
<login-bg :theme-color="bgThemeColor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import type { Component } from 'vue';
|
||||
import { NCard, NGradientText } from 'naive-ui';
|
||||
import { SystemLogo } from '@/components';
|
||||
import { EnumLoginModule } from '@/enum';
|
||||
import { SystemLogo, DarkModeSwitch } from '@/components';
|
||||
import { useThemeStore } from '@/store';
|
||||
import { useAppInfo } from '@/composables';
|
||||
import { mixColor } from '@/utils';
|
||||
import { LoginBg } from './components';
|
||||
import { getColorPalette, mixColor } from '@/utils';
|
||||
import type { LoginModuleKey } from '@/interface';
|
||||
import { LoginBg, PwdLogin, CodeLogin, Register, ResetPwd, BindWechat } from './components';
|
||||
|
||||
interface Props {
|
||||
/** 登录模块分类 */
|
||||
module: LoginModuleKey;
|
||||
}
|
||||
|
||||
interface LoginModule {
|
||||
key: LoginModuleKey;
|
||||
label: EnumLoginModule;
|
||||
component: Component;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const theme = useThemeStore();
|
||||
const { setDarkMode } = useThemeStore();
|
||||
const { title } = useAppInfo();
|
||||
|
||||
const modules: LoginModule[] = [
|
||||
{ key: 'pwd-login', label: EnumLoginModule['pwd-login'], component: PwdLogin },
|
||||
{ key: 'code-login', label: EnumLoginModule['code-login'], component: CodeLogin },
|
||||
{ key: 'register', label: EnumLoginModule.register, component: Register },
|
||||
{ key: 'reset-pwd', label: EnumLoginModule['reset-pwd'], component: ResetPwd },
|
||||
{ key: 'bind-wechat', label: EnumLoginModule['bind-wechat'], component: BindWechat }
|
||||
];
|
||||
|
||||
const activeModule = computed(() => {
|
||||
const active: LoginModule = { ...modules[0] };
|
||||
const findItem = modules.find(item => item.key === props.module);
|
||||
if (findItem) {
|
||||
Object.assign(active, findItem);
|
||||
}
|
||||
return active;
|
||||
});
|
||||
|
||||
const bgThemeColor = computed(() => (theme.darkMode ? getColorPalette(theme.themeColor, 7) : theme.themeColor));
|
||||
|
||||
const bgColor = computed(() => {
|
||||
const COLOR_WHITE = '#ffffff';
|
||||
const darkMode = false;
|
||||
const ratio = darkMode ? 0.6 : 0.2;
|
||||
const ratio = theme.darkMode ? 0.5 : 0.2;
|
||||
return mixColor(COLOR_WHITE, theme.themeColor, ratio);
|
||||
});
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user