diff --git a/.env b/.env new file mode 100644 index 0000000..d13f88a --- /dev/null +++ b/.env @@ -0,0 +1,8 @@ +# 网站标题 +VITE_GLOB_APP_TITLE = 青鸟语言大模型-同聪 + +# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符 +VITE_GLOB_APP_SHORT_NAME = 同聪 + +# token key +VITE_GLOB_APP_TOKEN_KEY = "hulk-Auth" \ No newline at end of file diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..199e83f --- /dev/null +++ b/.env.development @@ -0,0 +1,10 @@ +# 本地开发环境 + +# 公共地址 +VITE_GLOB_BASE_URL = "http://localhost:48080" + +# 本地MQTT地址 +VITE_GLOB_MQTT_URL = "http://localhost:48080" + +# 接口授权标识 +VITE_GLOB_APP_AUTHORIZATION = "ZmFsY29uOmZhbGNvbl9zZWNyZXQ=" \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..e85c639 --- /dev/null +++ b/.env.production @@ -0,0 +1,10 @@ +# 正式环境 + +# 公共地址 +VITE_GLOB_BASE_URL = "http://223.99.228.207:19872" + +# 本地MQTT地址 +VITE_GLOB_MQTT_URL = "http://localhost:48080" + +# 接口授权标识 +VITE_GLOB_APP_AUTHORIZATION = "ZmFsY29uOmZhbGNvbl9zZWNyZXQ=" \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index b18bc31..884e5f1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,7 +14,7 @@ "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[scss]": { - "editor.defaultFormatter": "dbaeumer.vscode-eslint" + "editor.defaultFormatter": "sibiraj-s.vscode-scss-formatter" }, "[typescript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" @@ -22,7 +22,7 @@ // 关闭自动添加文件头部注释 "fileheader.configObj": { - "autoAdd": false, // 默认开启 + "autoAdd": false // 默认开启 }, // 自动修复 diff --git a/eslint.config.js b/eslint.config.js index 4d1f23a..50cdef1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -5,5 +5,8 @@ export default antfu( { // unocss: true, formatters: true, + rules: { + 'vue/html-self-closing': 'off', + }, }, ) diff --git a/index.html b/index.html index dde16aa..9a6ce0d 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Vite + Vue + TS + %VITE_GLOB_APP_TITLE%
diff --git a/package.json b/package.json index 6a97091..d15b365 100644 --- a/package.json +++ b/package.json @@ -3,28 +3,45 @@ "type": "module", "version": "0.0.0", "private": true, + "engines": { + "node": ">=20.0.0", + "pnpm": ">=8.14.0" + }, "scripts": { - "dev": "vite", + "dev": "vite --host --mode development", + "dev:prod": "vite --host --mode production", "build": "vue-tsc && vite build", "preview": "vite preview", "lint": "eslint .", "lint:fix": "eslint . --fix" }, "dependencies": { + "@ant-design/icons-vue": "^7.0.1", "@vueuse/core": "^10.7.2", "ant-design-vue": "^4.1.0", + "axios": "^1.6.5", + "crypto-js": "^4.2.0", + "lodash-es": "^4.17.21", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "qs": "^6.11.2", "vue": "^3.3.11", "vue-router": "^4.2.5" }, "devDependencies": { "@antfu/eslint-config": "^2.6.2", + "@types/crypto-js": "^4.2.1", + "@types/lodash-es": "^4.17.12", "@types/node": "^20.11.0", + "@types/qs": "^6.9.11", "@vitejs/plugin-vue": "^4.5.2", "eslint": "^8.56.0", "eslint-plugin-format": "^0.1.0", + "sass": "^1.69.7", "typescript": "^5.2.2", "unocss": "^0.58.3", "vite": "^5.0.8", + "vite-plugin-svg-icons": "^2.0.1", "vue-tsc": "^1.8.25" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35eb17f..66cd466 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,12 +5,33 @@ settings: excludeLinksFromLockfile: false dependencies: + '@ant-design/icons-vue': + specifier: ^7.0.1 + version: 7.0.1(vue@3.4.13) '@vueuse/core': specifier: ^10.7.2 version: 10.7.2(vue@3.4.13) ant-design-vue: - specifier: ~4.1.0 + specifier: ^4.1.0 version: 4.1.0(vue@3.4.13) + axios: + specifier: ^1.6.5 + version: 1.6.5 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + pinia: + specifier: ^2.1.7 + version: 2.1.7(typescript@5.3.3)(vue@3.4.13) + pinia-plugin-persistedstate: + specifier: ^3.2.1 + version: 3.2.1(pinia@2.1.7) + qs: + specifier: ^6.11.2 + version: 6.11.2 vue: specifier: ^3.3.11 version: 3.4.13(typescript@5.3.3) @@ -22,9 +43,18 @@ devDependencies: '@antfu/eslint-config': specifier: ^2.6.2 version: 2.6.2(@vue/compiler-sfc@3.4.13)(eslint-plugin-format@0.1.0)(eslint@8.56.0)(typescript@5.3.3) + '@types/crypto-js': + specifier: ^4.2.1 + version: 4.2.1 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 '@types/node': specifier: ^20.11.0 version: 20.11.0 + '@types/qs': + specifier: ^6.9.11 + version: 6.9.11 '@vitejs/plugin-vue': specifier: ^4.5.2 version: 4.6.2(vite@5.0.11)(vue@3.4.13) @@ -34,6 +64,9 @@ devDependencies: eslint-plugin-format: specifier: ^0.1.0 version: 0.1.0(eslint@8.56.0) + sass: + specifier: ^1.69.7 + version: 1.69.7 typescript: specifier: ^5.2.2 version: 5.3.3 @@ -42,7 +75,10 @@ devDependencies: version: 0.58.3(postcss@8.4.33)(vite@5.0.11) vite: specifier: ^5.0.8 - version: 5.0.11(@types/node@20.11.0) + version: 5.0.11(@types/node@20.11.0)(sass@1.69.7) + vite-plugin-svg-icons: + specifier: ^2.0.1 + version: 2.0.1(vite@5.0.11) vue-tsc: specifier: ^1.8.25 version: 1.8.27(typescript@5.3.3) @@ -1074,6 +1110,15 @@ packages: - typescript dev: true + /@trysound/sax@0.2.0: + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + dev: true + + /@types/crypto-js@4.2.1: + resolution: {integrity: sha512-FSPGd9+OcSok3RsM0UZ/9fcvMOXJ1ENE/ZbLfOPlBWj7BgXtEAM8VYfTtT760GiLbQIMoVozwVuisjvsVwqYWw==} + dev: true + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true @@ -1082,6 +1127,16 @@ packages: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} dev: true + /@types/lodash-es@4.17.12: + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + dependencies: + '@types/lodash': 4.14.202 + dev: true + + /@types/lodash@4.14.202: + resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} + dev: true + /@types/mdast@3.0.15: resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} dependencies: @@ -1098,10 +1153,20 @@ packages: resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} dev: true + /@types/qs@6.9.11: + resolution: {integrity: sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==} + dev: true + /@types/semver@7.5.6: resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} dev: true + /@types/svgo@2.6.4: + resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} + dependencies: + '@types/node': 20.11.0 + dev: true + /@types/unist@2.0.10: resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} dev: true @@ -1257,7 +1322,7 @@ packages: '@unocss/core': 0.58.3 '@unocss/reset': 0.58.3 '@unocss/vite': 0.58.3(vite@5.0.11) - vite: 5.0.11(@types/node@20.11.0) + vite: 5.0.11(@types/node@20.11.0)(sass@1.69.7) transitivePeerDependencies: - rollup dev: true @@ -1455,7 +1520,7 @@ packages: chokidar: 3.5.3 fast-glob: 3.3.2 magic-string: 0.30.5 - vite: 5.0.11(@types/node@20.11.0) + vite: 5.0.11(@types/node@20.11.0)(sass@1.69.7) transitivePeerDependencies: - rollup dev: true @@ -1467,7 +1532,7 @@ packages: vite: ^4.0.0 || ^5.0.0 vue: ^3.2.25 dependencies: - vite: 5.0.11(@types/node@20.11.0) + vite: 5.0.11(@types/node@20.11.0)(sass@1.69.7) vue: 3.4.13(typescript@5.3.3) dev: true @@ -1626,11 +1691,21 @@ packages: uri-js: 4.4.1 dev: true + /ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + dev: true + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} dev: true + /ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + dev: true + /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -1693,6 +1768,21 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true + /arr-diff@4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-union@3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + dev: true + /array-tree-filter@2.1.0: resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} dev: false @@ -1702,19 +1792,70 @@ packages: engines: {node: '>=8'} dev: true + /array-unique@0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + dev: true + + /assign-symbols@1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + dev: true + /async-validator@4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} dev: false + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + dev: true + + /axios@1.6.5: + resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==} + dependencies: + follow-redirects: 1.15.5 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /base@0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.1 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + dev: true + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: true + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} dev: true + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: true + /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true @@ -1732,6 +1873,24 @@ packages: balanced-match: 1.0.2 dev: true + /braces@2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: 4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} @@ -1766,6 +1925,29 @@ packages: engines: {node: '>=8'} dev: true + /cache-base@1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.1 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + dev: true + + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.2.0 + dev: false + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -1775,6 +1957,17 @@ packages: resolution: {integrity: sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==} dev: true + /chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + dev: true + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1824,6 +2017,16 @@ packages: engines: {node: '>=8'} dev: true + /class-utils@0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + dev: true + /clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} @@ -1840,6 +2043,19 @@ packages: wrap-ansi: 7.0.0 dev: true + /clone@2.1.2: + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} + dev: true + + /collection-visit@1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + dev: true + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1865,11 +2081,27 @@ packages: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} dev: true + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + dev: true + /comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} dev: true + /component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + dev: true + /compute-scroll-into-view@1.0.20: resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} dev: false @@ -1891,6 +2123,11 @@ packages: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true + /copy-descriptor@0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + dev: true + /core-js-compat@3.35.0: resolution: {integrity: sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==} dependencies: @@ -1902,6 +2139,14 @@ packages: requiresBuild: true dev: false + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: true + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1911,6 +2156,28 @@ packages: which: 2.0.2 dev: true + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + dev: false + + /css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + dev: true + + /css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + dev: true + /css-tree@2.3.1: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -1919,12 +2186,24 @@ packages: source-map-js: 1.0.2 dev: true + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + dev: true + /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true dev: true + /csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + dependencies: + css-tree: 1.1.3 + dev: true + /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1936,6 +2215,17 @@ packages: resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} dev: true + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -1959,14 +2249,55 @@ packages: ms: 2.1.2 dev: true + /decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + dev: true + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: false + + /define-property@0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 0.1.7 + dev: true + + /define-property@1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.3 + dev: true + + /define-property@2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.3 + isobject: 3.0.1 + dev: true + /defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} dev: true + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + /destr@2.0.2: resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} dev: true @@ -1993,6 +2324,57 @@ packages: resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==} dev: false + /dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + dev: true + + /dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + dev: true + + /domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + dev: true + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: true + + /domhandler@2.4.2: + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} + dependencies: + domelementtype: 1.3.1 + dev: true + + /domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + dev: true + + /domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + dev: true + /duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} dev: true @@ -2005,6 +2387,19 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true + /emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: true + + /entities@1.1.2: + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} + dev: true + + /entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + dev: true + /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -2527,6 +2922,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: true + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -2557,6 +2957,52 @@ packages: strip-final-newline: 3.0.0 dev: true + /expand-brackets@2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + + /extend-shallow@3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + dev: true + + /extglob@2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2597,6 +3043,16 @@ packages: flat-cache: 3.2.0 dev: true + /fill-range@4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + dev: true + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -2633,6 +3089,46 @@ packages: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true + /follow-redirects@1.15.5: + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /fragment-cache@0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + dependencies: + map-cache: 0.2.2 + dev: true + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -2647,7 +3143,6 @@ packages: /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} @@ -2659,6 +3154,15 @@ packages: engines: {node: 6.* || 8.* || >= 10.*} dev: true + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: false + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -2675,6 +3179,11 @@ packages: resolve-pkg-maps: 1.0.0 dev: true + /get-value@2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -2724,6 +3233,16 @@ packages: slash: 3.0.0 dev: true + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + dev: false + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true @@ -2735,6 +3254,18 @@ packages: duplexer: 0.1.2 dev: true + /has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + dev: true + /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -2745,22 +3276,79 @@ packages: engines: {node: '>=8'} dev: true - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + dev: false + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} + dev: false + + /has-value@0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} dependencies: - function-bind: 1.1.2 + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 dev: true - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true + /has-value@1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + dev: true + + /has-values@0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + dev: true + + /has-values@1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true dev: true /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true + /htmlparser2@3.10.1: + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} + dependencies: + domelementtype: 1.3.1 + domhandler: 2.4.2 + domutils: 1.7.0 + entities: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -2776,6 +3364,16 @@ packages: engines: {node: '>= 4'} dev: true + /image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dev: true + + /immutable@4.3.4: + resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + dev: true + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -2805,6 +3403,13 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true + /is-accessor-descriptor@1.0.1: + resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} + engines: {node: '>= 0.10'} + dependencies: + hasown: 2.0.0 + dev: true + /is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} dev: true @@ -2827,6 +3432,10 @@ packages: binary-extensions: 2.2.0 dev: true + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: true + /is-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} @@ -2840,10 +3449,45 @@ packages: hasown: 2.0.0 dev: true + /is-data-descriptor@1.0.1: + resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} + engines: {node: '>= 0.4'} + dependencies: + hasown: 2.0.0 + dev: true + /is-decimal@1.0.4: resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} dev: true + /is-descriptor@0.1.7: + resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} + engines: {node: '>= 0.4'} + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + dev: true + + /is-descriptor@1.0.3: + resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} + engines: {node: '>= 0.4'} + dependencies: + is-accessor-descriptor: 1.0.1 + is-data-descriptor: 1.0.1 + dev: true + + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: true + + /is-extendable@1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + dev: true + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2865,6 +3509,13 @@ packages: resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} dev: true + /is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -2875,6 +3526,18 @@ packages: engines: {node: '>=8'} dev: true + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + /is-plain-object@3.0.1: resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} engines: {node: '>=0.10.0'} @@ -2890,15 +3553,40 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true + /isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + dev: true + + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: true + /jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true dev: true + /js-base64@2.6.4: + resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2947,6 +3635,13 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + /json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -2967,12 +3662,44 @@ packages: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: json-buffer: 3.0.1 dev: true + /kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of@5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + /kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -2994,6 +3721,15 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true + /loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + dev: true + /local-pkg@0.4.3: resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} engines: {node: '>=14'} @@ -3058,6 +3794,18 @@ packages: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 + /map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-visit@1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + dependencies: + object-visit: 1.0.1 + dev: true + /mdast-util-from-markdown@0.8.5: resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} dependencies: @@ -3074,10 +3822,21 @@ packages: resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} dev: true + /mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + dev: true + /mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} dev: true + /merge-options@1.0.1: + resolution: {integrity: sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==} + engines: {node: '>=4'} + dependencies: + is-plain-obj: 1.1.0 + dev: true + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -3096,6 +3855,27 @@ packages: - supports-color dev: true + /micromatch@3.1.0: + resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 1.0.0 + extend-shallow: 2.0.1 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 5.1.0 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -3104,6 +3884,18 @@ packages: picomatch: 2.3.1 dev: true + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -3132,6 +3924,18 @@ packages: brace-expansion: 2.0.1 dev: true + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /mixin-deep@1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + dev: true + /mlly@1.5.0: resolution: {integrity: sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==} dependencies: @@ -3146,6 +3950,10 @@ packages: engines: {node: '>=10'} dev: true + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -3163,6 +3971,25 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /nanomatch@1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + fragment-cache: 0.2.1 + is-windows: 1.0.2 + kind-of: 6.0.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + /nanopop@2.3.0: resolution: {integrity: sha512-fzN+T2K7/Ah25XU02MJkPZ5q4Tj5FpjmIYq4rvoHX4yb16HzFdCO6JxFFn5Y/oBhQ8no8fUZavnyIv9/+xkBBw==} dev: false @@ -3217,6 +4044,38 @@ packages: boolbase: 1.0.0 dev: true + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-copy@0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + dev: true + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: false + + /object-visit@1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + /ofetch@1.3.3: resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==} dependencies: @@ -3323,6 +4182,11 @@ packages: lines-and-columns: 1.2.4 dev: true + /pascalcase@0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + dev: true + /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: true @@ -3356,6 +4220,10 @@ packages: engines: {node: '>=8'} dev: true + /pathe@0.2.0: + resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + dev: true + /pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} dev: true @@ -3372,6 +4240,32 @@ packages: engines: {node: '>=8.6'} dev: true + /pinia-plugin-persistedstate@3.2.1(pinia@2.1.7): + resolution: {integrity: sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==} + peerDependencies: + pinia: ^2.0.0 + dependencies: + pinia: 2.1.7(typescript@5.3.3)(vue@3.4.13) + dev: false + + /pinia@2.1.7(typescript@5.3.3)(vue@3.4.13): + resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==} + peerDependencies: + '@vue/composition-api': ^1.4.0 + typescript: '>=4.4.4' + vue: ^2.6.14 || ^3.3.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + typescript: + optional: true + dependencies: + '@vue/devtools-api': 6.5.1 + typescript: 5.3.3 + vue: 3.4.13(typescript@5.3.3) + vue-demi: 0.14.6(vue@3.4.13) + dev: false + /pkg-types@1.0.3: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} dependencies: @@ -3385,6 +4279,19 @@ packages: engines: {node: '>=4'} dev: true + /posix-character-classes@0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + dev: true + + /postcss-prefix-selector@1.16.0(postcss@5.2.18): + resolution: {integrity: sha512-rdVMIi7Q4B0XbXqNUEI+Z4E+pueiu/CS5E6vRCQommzdQ/sgsS4dK42U7GX8oJR+TJOtT+Qv3GkNo6iijUMp3Q==} + peerDependencies: + postcss: '>4 <9' + dependencies: + postcss: 5.2.18 + dev: true + /postcss-selector-parser@6.0.15: resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} engines: {node: '>=4'} @@ -3393,6 +4300,16 @@ packages: util-deprecate: 1.0.2 dev: true + /postcss@5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} + engines: {node: '>=0.12'} + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: 3.2.3 + dev: true + /postcss@8.4.33: resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} engines: {node: ^10 || ^12 || >=14} @@ -3401,6 +4318,41 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /posthtml-parser@0.2.1: + resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==} + dependencies: + htmlparser2: 3.10.1 + isobject: 2.1.0 + dev: true + + /posthtml-rename-id@1.0.12: + resolution: {integrity: sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /posthtml-render@1.4.0: + resolution: {integrity: sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==} + engines: {node: '>=10'} + dev: true + + /posthtml-svg-mode@1.0.3: + resolution: {integrity: sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==} + dependencies: + merge-options: 1.0.1 + posthtml: 0.9.2 + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + dev: true + + /posthtml@0.9.2: + resolution: {integrity: sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==} + engines: {node: '>=0.10.0'} + dependencies: + posthtml-parser: 0.2.1 + posthtml-render: 1.4.0 + dev: true + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -3427,11 +4379,30 @@ packages: sisteransi: 1.0.5 dev: true + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} dev: true + /qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /query-string@4.3.4: + resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} + engines: {node: '>=0.10.0'} + dependencies: + object-assign: 4.1.1 + strict-uri-encode: 1.1.0 + dev: true + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true @@ -3455,6 +4426,15 @@ packages: type-fest: 0.6.0 dev: true + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -3466,6 +4446,14 @@ packages: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} dev: false + /regex-not@1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + dev: true + /regexp-tree@0.1.27: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true @@ -3478,6 +4466,16 @@ packages: jsesc: 0.5.0 dev: true + /repeat-element@1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + dev: true + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -3496,6 +4494,11 @@ packages: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} dev: true + /resolve-url@0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + dev: true + /resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -3505,6 +4508,11 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /ret@0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + dev: true + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -3546,6 +4554,26 @@ packages: queue-microtask: 1.2.3 dev: true + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safe-regex@1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + dependencies: + ret: 0.1.15 + dev: true + + /sass@1.69.7: + resolution: {integrity: sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.3.4 + source-map-js: 1.0.2 + dev: true + /scroll-into-view-if-needed@2.2.31: resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} dependencies: @@ -3570,6 +4598,27 @@ packages: lru-cache: 6.0.0 dev: true + /set-function-length@1.2.0: + resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: false + + /set-value@2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + dev: true + /shallow-equal@1.2.1: resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} dev: false @@ -3586,6 +4635,14 @@ packages: engines: {node: '>=8'} dev: true + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + dev: false + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true @@ -3613,10 +4670,68 @@ packages: engines: {node: '>=8'} dev: true + /snapdragon-node@2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + dev: true + + /snapdragon-util@3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /snapdragon@0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + /source-map-resolve@0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + dev: true + + /source-map-url@0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + dev: true + + /source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + /spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} dependencies: @@ -3646,6 +4761,31 @@ packages: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} dev: true + /split-string@3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + dev: true + + /stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + dev: true + + /static-extend@0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + dev: true + + /strict-uri-encode@1.1.0: + resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} + engines: {node: '>=0.10.0'} + dev: true + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -3655,6 +4795,19 @@ packages: strip-ansi: 6.0.1 dev: true + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -3688,6 +4841,18 @@ packages: resolution: {integrity: sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==} dev: false + /supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + dev: true + + /supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + dependencies: + has-flag: 1.0.0 + dev: true + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -3707,6 +4872,40 @@ packages: engines: {node: '>= 0.4'} dev: true + /svg-baker@1.7.0: + resolution: {integrity: sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==} + dependencies: + bluebird: 3.7.2 + clone: 2.1.2 + he: 1.2.0 + image-size: 0.5.5 + loader-utils: 1.4.2 + merge-options: 1.0.1 + micromatch: 3.1.0 + postcss: 5.2.18 + postcss-prefix-selector: 1.16.0(postcss@5.2.18) + posthtml-rename-id: 1.0.12 + posthtml-svg-mode: 1.0.3 + query-string: 4.3.4 + traverse: 0.6.8 + transitivePeerDependencies: + - supports-color + dev: true + + /svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.0.0 + stable: 0.1.8 + dev: true + /synckit@0.8.8: resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} engines: {node: ^14.18.0 || >=16.0.0} @@ -3728,6 +4927,21 @@ packages: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} + /to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /to-regex-range@2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + dev: true + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3735,6 +4949,16 @@ packages: is-number: 7.0.0 dev: true + /to-regex@3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + dev: true + /toml-eslint-parser@0.9.3: resolution: {integrity: sha512-moYoCvkNUAPCxSW9jmHmRElhm4tVJpHL8ItC/+uYD0EpPSFXbck7yREz9tNdJVTSpHVod8+HoipcpbQ0oE6gsw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3747,6 +4971,11 @@ packages: engines: {node: '>=6'} dev: true + /traverse@0.6.8: + resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} + engines: {node: '>= 0.4'} + dev: true + /ts-api-utils@1.0.3(typescript@5.3.3): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} @@ -3804,12 +5033,27 @@ packages: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: true + /union-value@1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + dev: true + /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} dependencies: '@types/unist': 2.0.10 dev: true + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + /unocss@0.58.3(postcss@8.4.33)(vite@5.0.11): resolution: {integrity: sha512-2rnvghfiIDRQ2cOrmN4P7J7xV2p3yBK+bPAt1aoUxCXcszkLczAnQzh9c7IZ+p70kSVstK45cJTYV6TMzOLF7Q==} engines: {node: '>=14'} @@ -3842,13 +5086,21 @@ packages: '@unocss/transformer-directives': 0.58.3 '@unocss/transformer-variant-group': 0.58.3 '@unocss/vite': 0.58.3(vite@5.0.11) - vite: 5.0.11(@types/node@20.11.0) + vite: 5.0.11(@types/node@20.11.0)(sass@1.69.7) transitivePeerDependencies: - postcss - rollup - supports-color dev: true + /unset-value@1.0.0: + resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} + engines: {node: '>=0.10.0'} + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + dev: true + /update-browserslist-db@1.0.13(browserslist@4.22.2): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true @@ -3866,6 +5118,16 @@ packages: punycode: 2.3.1 dev: true + /urix@0.1.0: + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} + deprecated: Please see https://github.com/lydell/urix#deprecated + dev: true + + /use@3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + dev: true + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true @@ -3877,7 +5139,30 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vite@5.0.11(@types/node@20.11.0): + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: true + + /vite-plugin-svg-icons@2.0.1(vite@5.0.11): + resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==} + peerDependencies: + vite: '>=2.0.0' + dependencies: + '@types/svgo': 2.6.4 + cors: 2.8.5 + debug: 4.3.4 + etag: 1.8.1 + fs-extra: 10.1.0 + pathe: 0.2.0 + svg-baker: 1.7.0 + svgo: 2.8.0 + vite: 5.0.11(@types/node@20.11.0)(sass@1.69.7) + transitivePeerDependencies: + - supports-color + dev: true + + /vite@5.0.11(@types/node@20.11.0)(sass@1.69.7): resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -3909,6 +5194,7 @@ packages: esbuild: 0.19.11 postcss: 8.4.33 rollup: 4.9.5 + sass: 1.69.7 optionalDependencies: fsevents: 2.3.3 dev: true diff --git a/src/App.vue b/src/App.vue index d1a7305..ee14bb1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,48 +1,30 @@ diff --git a/src/api/base/login.ts b/src/api/base/login.ts new file mode 100644 index 0000000..946d61b --- /dev/null +++ b/src/api/base/login.ts @@ -0,0 +1,23 @@ +import { defHttp } from '@/utils/axios/index' + +export interface TokenParams { + user_type: string + grant_type: string + invite_code: string + phone: string + phoneCode: string + type: string +} +export async function token(params: TokenParams) { + return defHttp.post({ + url: `/hulk-auth/oauth/token?grant_type=${params.grant_type}&user_type=${params.user_type}&invite_code=${params.invite_code}&phone=${params.phone}&phoneCode=${params.phoneCode}&type=${params.type}`, + }, { + isTransformResponse: false, + }) +} + +export async function sendCode(phone: string) { + return defHttp.post({ + url: `/open-chat/unauth/sendSms?phone=${phone}`, + }) +} diff --git a/src/api/base/user.ts b/src/api/base/user.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/assets/images/bg_menu.png b/src/assets/images/bg_menu.png new file mode 100644 index 0000000..3a788fa Binary files /dev/null and b/src/assets/images/bg_menu.png differ diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 0000000..68c89df Binary files /dev/null and b/src/assets/images/logo.png differ diff --git a/src/assets/svg/404.svg b/src/assets/svg/404.svg new file mode 100644 index 0000000..6df5019 --- /dev/null +++ b/src/assets/svg/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/jue_se.svg b/src/assets/svg/jue_se.svg new file mode 100644 index 0000000..38d14f1 --- /dev/null +++ b/src/assets/svg/jue_se.svg @@ -0,0 +1,11 @@ + + + jiaoseguanli-2 + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/qu_dao.svg b/src/assets/svg/qu_dao.svg new file mode 100644 index 0000000..52c2f4a --- /dev/null +++ b/src/assets/svg/qu_dao.svg @@ -0,0 +1,12 @@ + + + 形状 2 + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/ren_wu.svg b/src/assets/svg/ren_wu.svg new file mode 100644 index 0000000..dc70342 --- /dev/null +++ b/src/assets/svg/ren_wu.svg @@ -0,0 +1,15 @@ + + + cheliang__02-02-01qiandaojilu + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/vue.svg b/src/assets/svg/vue.svg new file mode 100644 index 0000000..770e9d3 --- /dev/null +++ b/src/assets/svg/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svg/wei_xin.svg b/src/assets/svg/wei_xin.svg new file mode 100644 index 0000000..7d348cf --- /dev/null +++ b/src/assets/svg/wei_xin.svg @@ -0,0 +1,18 @@ + + + 24gf-bubblesDots5备份 2 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/wen_sheng_tu.svg b/src/assets/svg/wen_sheng_tu.svg new file mode 100644 index 0000000..fdef16b --- /dev/null +++ b/src/assets/svg/wen_sheng_tu.svg @@ -0,0 +1,13 @@ + + + wenshengtu + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/wo_de.svg b/src/assets/svg/wo_de.svg new file mode 100644 index 0000000..55be82f --- /dev/null +++ b/src/assets/svg/wo_de.svg @@ -0,0 +1,14 @@ + + + 编组 + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svg/xiao_cheng_xu.svg b/src/assets/svg/xiao_cheng_xu.svg new file mode 100644 index 0000000..249cc5e --- /dev/null +++ b/src/assets/svg/xiao_cheng_xu.svg @@ -0,0 +1,22 @@ + + + 编组 7备份 2 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/AppContainerBox/index.ts b/src/components/AppContainerBox/index.ts new file mode 100644 index 0000000..e94f7df --- /dev/null +++ b/src/components/AppContainerBox/index.ts @@ -0,0 +1,3 @@ +import AppContainerBox from './index.vue' + +export { AppContainerBox } diff --git a/src/components/AppContainerBox/index.vue b/src/components/AppContainerBox/index.vue new file mode 100644 index 0000000..87adb37 --- /dev/null +++ b/src/components/AppContainerBox/index.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/components/AppContentBox/index.ts b/src/components/AppContentBox/index.ts new file mode 100644 index 0000000..04261f7 --- /dev/null +++ b/src/components/AppContentBox/index.ts @@ -0,0 +1,3 @@ +import AppContentBox from './index.vue' + +export { AppContentBox } diff --git a/src/components/AppContentBox/index.vue b/src/components/AppContentBox/index.vue new file mode 100644 index 0000000..43caa74 --- /dev/null +++ b/src/components/AppContentBox/index.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/components/AppSubMenuBox/index.ts b/src/components/AppSubMenuBox/index.ts new file mode 100644 index 0000000..1037c0a --- /dev/null +++ b/src/components/AppSubMenuBox/index.ts @@ -0,0 +1,3 @@ +import AppSubMenuBox from './index.vue' + +export { AppSubMenuBox } diff --git a/src/components/AppSubMenuBox/index.vue b/src/components/AppSubMenuBox/index.vue new file mode 100644 index 0000000..cd28458 --- /dev/null +++ b/src/components/AppSubMenuBox/index.vue @@ -0,0 +1,14 @@ + + + + + diff --git a/src/components/AppSubMenuList/index.d.ts b/src/components/AppSubMenuList/index.d.ts new file mode 100644 index 0000000..26278f0 --- /dev/null +++ b/src/components/AppSubMenuList/index.d.ts @@ -0,0 +1,5 @@ +export interface SubMenuItem { + title: string + content: string + id: string +} diff --git a/src/components/AppSubMenuList/index.ts b/src/components/AppSubMenuList/index.ts new file mode 100644 index 0000000..d06a525 --- /dev/null +++ b/src/components/AppSubMenuList/index.ts @@ -0,0 +1,3 @@ +import AppSubMenuList from './index.vue' + +export { AppSubMenuList } diff --git a/src/components/AppSubMenuList/index.vue b/src/components/AppSubMenuList/index.vue new file mode 100644 index 0000000..0bf8e0f --- /dev/null +++ b/src/components/AppSubMenuList/index.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/src/components/AppSubMenuTitle/index.ts b/src/components/AppSubMenuTitle/index.ts new file mode 100644 index 0000000..431d21b --- /dev/null +++ b/src/components/AppSubMenuTitle/index.ts @@ -0,0 +1,3 @@ +import AppSubMenuTitle from './index.vue' + +export { AppSubMenuTitle } diff --git a/src/components/AppSubMenuTitle/index.vue b/src/components/AppSubMenuTitle/index.vue new file mode 100644 index 0000000..77dbc8d --- /dev/null +++ b/src/components/AppSubMenuTitle/index.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue deleted file mode 100644 index adda173..0000000 --- a/src/components/HelloWorld.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - - - diff --git a/src/components/SvgIcon/index.ts b/src/components/SvgIcon/index.ts new file mode 100644 index 0000000..d14e817 --- /dev/null +++ b/src/components/SvgIcon/index.ts @@ -0,0 +1,3 @@ +import SvgIcon from './index.vue' + +export { SvgIcon } diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..084d064 --- /dev/null +++ b/src/components/SvgIcon/index.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/src/design/index.scss b/src/design/index.scss new file mode 100644 index 0000000..500e4d9 --- /dev/null +++ b/src/design/index.scss @@ -0,0 +1,72 @@ +@import "./mixins/config.scss"; +@import "./mixins/mixins.scss"; +:-webkit-autofill { + transition: background-color 5000s ease-in-out 0s !important; +} + +html { + overflow: hidden; + text-size-adjust: 100%; +} + +html, +body { + width: 100%; + height: 100%; + overflow: visible; + overflow-x: hidden; + color: var(--text-color); + + &.color-weak { + filter: invert(80%); + } + + &.gray-mode { + filter: grayscale(100%); + filter: progid:dximagetransform.microsoft.basicimage(grayscale=1); + } +} + +a:focus, +a:active, +button, +div, +svg, +span { + outline: none; +} + +/** 打包后夜间模式样式有问题 在这里覆盖 */ +html[data-theme="dark"] { + /** 菜单边框 */ + ul li { + border: none; + } + + ul li:hover { + color: inherit !important; + border: none; + box-shadow: none; + } + + /** 日期输入框 */ + .ant-picker-input > input { + border: none; + } + + .ant-picker-input > input:focus { + color: inherit !important; + box-shadow: none; + } +} + +.ant-input-number { + width: 100%; +} + +// 保持 和 windi 一样的全局样式,减少升级带来的影响 +ul { + padding: 0; + margin: 0; + list-style: none; +} diff --git a/src/design/mixins/config.scss b/src/design/mixins/config.scss new file mode 100644 index 0000000..06ee5f3 --- /dev/null +++ b/src/design/mixins/config.scss @@ -0,0 +1,3 @@ +$namespace: "app"; +$menu-width: 80px; +$sub-menu-width: 180px; diff --git a/src/design/mixins/mixins.scss b/src/design/mixins/mixins.scss new file mode 100644 index 0000000..21f92a1 --- /dev/null +++ b/src/design/mixins/mixins.scss @@ -0,0 +1,6 @@ +@mixin app($block) { + $B: $namespace + "-" + $block; + .#{$B} { + @content; + } +} diff --git a/src/design/public.scss b/src/design/public.scss new file mode 100644 index 0000000..3ebdf11 --- /dev/null +++ b/src/design/public.scss @@ -0,0 +1,49 @@ +#app { + width: 100%; + height: 100%; +} + +// ================================= +// ==============scrollbar========== +// ================================= + +::-webkit-scrollbar { + width: 7px; + height: 8px; +} + +// ::-webkit-scrollbar-track { +// background: transparent; +// } + +::-webkit-scrollbar-track { + background-color: rgba($color: #000000, $alpha: 0.5); +} + +::-webkit-scrollbar-thumb { + background: rgba($color: #000000, $alpha: 0.6); + background-color: rgba($color: #9093994d, $alpha: 0.3); + border-radius: 2px; + box-shadow: inset 0 0 6px rgba($color: #000000, $alpha: 0.2); +} + +::-webkit-scrollbar-thumb:hover { + background-color: var(--border-color); +} + +// ================================= +// ==============nprogress========== +// ================================= +#nprogress { + pointer-events: none; + + .bar { + position: fixed; + top: 0; + left: 0; + z-index: 99999; + width: 100%; + height: 2px; + opacity: 0.75; + } +} diff --git a/src/enums/cacheEnum.ts b/src/enums/cacheEnum.ts new file mode 100644 index 0000000..86d7178 --- /dev/null +++ b/src/enums/cacheEnum.ts @@ -0,0 +1,12 @@ +// token key +export const ACCESS_TOKEN_KEY = 'ACCESS_TOKEN' + +// user info key +export const USER_INFO_KEY = 'USER_INFO' + +export const USET_STORE_KEY = 'USER_STORE' + +export enum CatchTypeEnum { + ACCESS_TOKEN_KEY, + USER_INFO_KEY, +} diff --git a/src/enums/commonEnum.ts b/src/enums/commonEnum.ts new file mode 100644 index 0000000..eaff220 --- /dev/null +++ b/src/enums/commonEnum.ts @@ -0,0 +1,14 @@ +export enum UserTypeEnum { + WEB = 'web', + C = 'c', +} + +export enum GrantTypeEnum { + PASSWORD = 'password', + CAPTCHA = 'captcha', + SMS = 'sms', +} + +export enum TypeEnum { + PHONE = 'phone', +} diff --git a/src/enums/httpEnum.ts b/src/enums/httpEnum.ts new file mode 100644 index 0000000..f94bdd3 --- /dev/null +++ b/src/enums/httpEnum.ts @@ -0,0 +1,55 @@ +/** + * @description: request method + */ +export enum RequestEnum { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', +} + +/** + * @description: contentType + */ +export enum ContentTypeEnum { + // json + JSON = 'application/json;charset=UTF-8', + // form-data qs + FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8', + // form-data upload + FORM_DATA = 'multipart/form-data;charset=UTF-8', +} + +export enum ResultEnum { + SUCCESS = 200, + ERROR = -1, + TIMEOUT = 400, + UNAUTHORIZED = 401, + INTERNAL_SERVER_ERROR = 500, + TYPE = 'success', +} + +export enum HttpErrorMsgEnum { + ERROR_TIP = '错误提示', + API_REQUEST_FAILED = '请求出错,请稍候重试', + API_TIMEOUT_MESSAGE = '接口请求超时,请刷新页面重试!', + + NETWORK_EXCEPTION = '网络异常,请稍候重试', + + ERROR_MESSAGE_401 = '用户没有权限(令牌、用户名、密码错误)!', + ERROR_MESSAGE_403 = '用户得到授权,但是访问是被禁止的。!', + ERROR_MESSAGE_404 = '网络请求错误,未找到该资源!', + ERROR_MESSAGE_405 = '网络请求错误,请求方法未允许!', + ERROR_MESSAGE_408 = '请求超时!', + ERROR_MESSAGE_500 = '服务器错误,请联系管理员!', + ERROR_MESSAGE_501 = '网络请求错误,未实现!', + ERROR_MESSAGE_502 = '网络请求错误,网关错误!', + ERROR_MESSAGE_503 = '服务不可用,服务器暂时过载或维护!', + ERROR_MESSAGE_504 = '网络请求错误,网关超时!', + ERROR_MESSAGE_505 = 'http版本不受支持!', +} + +export enum HttpSuccessEnum { + SUCCESS_TIP = '成功提示', + OPERATION_SUCCESS = '操作成功', +} diff --git a/src/enums/menuEnum.ts b/src/enums/menuEnum.ts new file mode 100644 index 0000000..0daccda --- /dev/null +++ b/src/enums/menuEnum.ts @@ -0,0 +1,22 @@ +export enum MenuTypeEnum { + // 会话 + CONVERSATION = 'conversation', + + // 文生图 + TEXT_TO_PICTURE = 'textToPicture', + + // 角色 + ROLE = 'role', + + // 任务 + TASK = 'task', + + // 渠道 + CHANNEL = 'channel', + + // 小程序 + APPLET = 'applet', + + // 我的 + USER = 'user', +} diff --git a/src/enums/pageEnum.ts b/src/enums/pageEnum.ts new file mode 100644 index 0000000..91d5908 --- /dev/null +++ b/src/enums/pageEnum.ts @@ -0,0 +1,11 @@ +/** + * @description: 页面枚举(使用router中name属性) + */ +export enum PageEnum { + // 登录 + BASE_LOGIN = 'Login', + + // 错误 + ERROR_PAGE_NAME_404 = '404', + +} diff --git a/src/hooks/useMessage.tsx b/src/hooks/useMessage.tsx new file mode 100644 index 0000000..546701a --- /dev/null +++ b/src/hooks/useMessage.tsx @@ -0,0 +1,111 @@ +import type { ModalFuncProps } from 'ant-design-vue/lib/modal/Modal' + +import { message as Message, Modal, notification } from 'ant-design-vue' +import { CheckCircleFilled, CloseCircleFilled, InfoCircleFilled } from '@ant-design/icons-vue' + +import type { ConfigProps, NotificationArgsProps } from 'ant-design-vue/lib/notification' +import { isString } from '@/utils/is' + +export interface NotifyApi { + info(config: NotificationArgsProps): void + success(config: NotificationArgsProps): void + error(config: NotificationArgsProps): void + warn(config: NotificationArgsProps): void + warning(config: NotificationArgsProps): void + open(args: NotificationArgsProps): void + close(key: string): void + config(options: ConfigProps): void + destroy(): void +} + +export declare type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' +export declare type IconType = 'success' | 'info' | 'error' | 'warning' +export interface ModalOptionsEx extends Omit { + iconType: 'warning' | 'success' | 'error' | 'info' +} +export type ModalOptionsPartial = Partial & Pick + +function getIcon(iconType: string) { + if (iconType === 'warning') + return + else if (iconType === 'success') + return + else if (iconType === 'info') + return + else + return +} + +function renderContent({ content }: Pick) { + if (isString(content)) + return
${content}
`}> + else + return content +} + +/** + * @description: Create confirmation box + */ +function createConfirm(options: ModalOptionsEx) { + const iconType = options.iconType || 'warning' + Reflect.deleteProperty(options, 'iconType') + const opt: ModalFuncProps = { + centered: true, + icon: getIcon(iconType), + ...options, + content: renderContent(options), + } + return Modal.confirm(opt) +} + +function getBaseOptions() { + return { + okText: '确认', + centered: true, + } +} + +function createModalOptions(options: ModalOptionsPartial, icon: string): ModalOptionsPartial { + return { + ...getBaseOptions(), + ...options, + content: renderContent(options), + icon: getIcon(icon), + } +} + +function createSuccessModal(options: ModalOptionsPartial) { + return Modal.success(createModalOptions(options, 'success')) +} + +function createErrorModal(options: ModalOptionsPartial) { + return Modal.error(createModalOptions(options, 'close')) +} + +function createInfoModal(options: ModalOptionsPartial) { + return Modal.info(createModalOptions(options, 'info')) +} + +function createWarningModal(options: ModalOptionsPartial) { + return Modal.warning(createModalOptions(options, 'warning')) +} + +notification.config({ + placement: 'topRight', + duration: 3, +}) + +/** + * @description: message + */ +export function useMessage() { + return { + createMessage: Message, + notification: notification as NotifyApi, + createConfirm, + createSuccessModal, + createErrorModal, + createInfoModal, + createWarningModal, + } +} diff --git a/src/layout/AppMain/index.vue b/src/layout/AppMain/index.vue new file mode 100644 index 0000000..fdee26b --- /dev/null +++ b/src/layout/AppMain/index.vue @@ -0,0 +1,14 @@ + + + + + diff --git a/src/layout/AppMenu/index.d.ts b/src/layout/AppMenu/index.d.ts new file mode 100644 index 0000000..eb9b25c --- /dev/null +++ b/src/layout/AppMenu/index.d.ts @@ -0,0 +1,8 @@ +import type { MenuTypeEnum } from '@/enums/menuEnum' + +export interface MenuItem { + name: string + icon: string + path: string + key: MenuTypeEnum +} diff --git a/src/layout/AppMenu/index.vue b/src/layout/AppMenu/index.vue new file mode 100644 index 0000000..583babc --- /dev/null +++ b/src/layout/AppMenu/index.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/src/layout/index.vue b/src/layout/index.vue new file mode 100644 index 0000000..dba5755 --- /dev/null +++ b/src/layout/index.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/src/main.ts b/src/main.ts index c28322b..e73cd0c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,17 +2,30 @@ * @Description: * @Author: yeke * @Date: 2024-01-14 15:47:49 - * @LastEditors: yeke - * @LastEditTime: 2024-01-14 21:34:34 + * @LastEditors: lipenghui + * @LastEditTime: 2024-01-16 15:24:25 */ import { createApp } from 'vue' -import './style.css' + +import './design/public.scss' import 'virtual:uno.css' import 'ant-design-vue/dist/reset.css' -import router from './router/index' import App from './App.vue' +import { setupStore } from '@/store' +import { router, setupRouter } from '@/router' +import { setupRouterGuard } from '@/router/guard' + +// svg图标 +import 'virtual:svg-icons-register' const app = createApp(App) +// 挂载状态管理 +setupStore(app) + +// 配置路由 +setupRouter(app) + +// 路由守卫 +setupRouterGuard(router) -app.use(router) app.mount('#app') diff --git a/src/router/guard.ts b/src/router/guard.ts new file mode 100644 index 0000000..78077aa --- /dev/null +++ b/src/router/guard.ts @@ -0,0 +1,35 @@ +import type { Router } from 'vue-router' +import { PageEnum } from '@/enums/pageEnum' +import { useUserStore } from '@/store/moules/userStore/index' + +export function setupRouterGuard(router: Router) { + createRouterGuards(router) +} + +const WHITE_NAME_LIST: string[] = [ + PageEnum.BASE_LOGIN, +] + +function createRouterGuards(router: Router) { + const userStore = useUserStore() + // 前置 + router.beforeEach(async (to, _from, next) => { + const isErrorPage = router.getRoutes().findIndex(item => item.name === to.name) + if (isErrorPage === -1) + next({ name: PageEnum.ERROR_PAGE_NAME_404 }) + + if (userStore.getToken) { + next() + } + else { + if (WHITE_NAME_LIST.includes(to.name as string)) + next() + else + next({ name: PageEnum.BASE_LOGIN }) + } + }) + + // router.afterEach((to, _) => { + // document.title = (to?.meta?.title as string) || document.title + // }) +} diff --git a/src/router/index.ts b/src/router/index.ts index 0291432..30277ca 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,3 +1,4 @@ +import type { App } from 'vue' import type { RouteRecordRaw, } from 'vue-router' @@ -5,21 +6,57 @@ import { createRouter, createWebHistory, } from 'vue-router' +import Layout from '@/layout/index.vue' export const constantRoutes: Array = [ + { + path: '/404', + name: '404', + component: () => import('@/views/error/404.vue'), + meta: { + title: '404', + }, + }, { path: '/login', name: 'Login', - component: () => import('@/views/login.vue'), + component: () => import('@/views/login/index.vue'), + meta: { + title: '登录', + }, + }, + { + name: 'Layout', + path: '/', + component: Layout, + redirect: '/conversation', + children: [ + { + name: 'Conversation', + path: '/conversation', + component: () => import('@/views/conversation/index.vue'), + meta: { + title: '会话', + }, + }, + { + name: 'TextToPicture', + path: '/textToPicture', + component: () => import('@/views/textToPicture/index.vue'), + meta: { + title: '文生图', + }, + }, + ], }, ] -// 1.返回一个 router 实列,为函数,里面有配置项(对象) history -const router = createRouter({ +export const router = createRouter({ history: createWebHistory(), routes: constantRoutes, }) -// 3导出路由 然后去 main.ts 注册 router.ts -export default router +export function setupRouter(app: App) { + app.use(router) +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..5c02824 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,11 @@ +import type { App } from 'vue' +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +const pinia = createPinia() +pinia.use(piniaPluginPersistedstate) +export function setupStore(app: App) { + app.use(pinia) +} + +export { pinia } diff --git a/src/store/moules/userStore/index.d.ts b/src/store/moules/userStore/index.d.ts new file mode 100644 index 0000000..fc7e958 --- /dev/null +++ b/src/store/moules/userStore/index.d.ts @@ -0,0 +1,15 @@ +export interface UserStateType { + token: string | null + userInfo: string | null +} + +export interface UserInfoType { + user_id: string + avatar: string + access_token: string + token_type: string + role_name: string + user_name: string + real_name: string + nick_name: string +} diff --git a/src/store/moules/userStore/index.ts b/src/store/moules/userStore/index.ts new file mode 100644 index 0000000..ba8ecf9 --- /dev/null +++ b/src/store/moules/userStore/index.ts @@ -0,0 +1,73 @@ +/* + * @Description: 主题状态控制 + * @Author: yeke + * @Date: 2023-06-28 11:16:32 + * @LastEditors: lipenghui + * @LastEditTime: 2024-01-17 13:54:13 + */ +import { defineStore } from 'pinia' +import type { UserInfoType, UserStateType } from './index.d' +import { router } from '@/router' +import { PageEnum } from '@/enums/pageEnum' +import { ACCESS_TOKEN_KEY, USER_INFO_KEY } from '@/enums/cacheEnum' +import { token } from '@/api/base/login' +import type { TokenParams } from '@/api/base/login' +import crypto from '@/utils/crypto' + +export const useUserStore = defineStore('useUserStore', { + state: (): UserStateType => { + return { + token: null, + userInfo: null, + } + }, + getters: { + getToken(): string | null { + return this.token ? crypto.decryptAES(this.token, crypto.localKey) : null + }, + getUserInfo(): UserInfoType | null { + return this.userInfo ? JSON.parse(crypto.decryptAES(this.userInfo, crypto.localKey)) : null + }, + }, + actions: { + setToken(token: string) { + this.token = token + }, + + setUserInfo(userInfo: string) { + this.userInfo = userInfo + }, + + async login(params: TokenParams) { + return new Promise((resolve, reject) => { + token(params).then((res) => { + this.setToken(crypto.encryptAES(res.access_token, crypto.localKey)) + this.setUserInfo(crypto.encryptAES(JSON.stringify(res), crypto.localKey)) + resolve(res) + }).catch((err) => { + reject(err) + }) + }) + }, + + /** + * @description: logout + */ + async logout(goLogin = false) { + this.$reset() + localStorage.clear() + // 清空数据 + goLogin && router.push(PageEnum.BASE_LOGIN) + }, + }, + persist: [ + { + paths: ['token'], + key: ACCESS_TOKEN_KEY, + }, + { + paths: ['userInfo'], + key: USER_INFO_KEY, + }, + ], +}) diff --git a/src/style.css b/src/style.css deleted file mode 100644 index bb131d6..0000000 --- a/src/style.css +++ /dev/null @@ -1,79 +0,0 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -.card { - padding: 2em; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/src/utils/axios/Axios.ts b/src/utils/axios/Axios.ts new file mode 100644 index 0000000..d93fe88 --- /dev/null +++ b/src/utils/axios/Axios.ts @@ -0,0 +1,337 @@ +import type { + AxiosError, + AxiosInstance, + AxiosRequestConfig, + AxiosResponse, + InternalAxiosRequestConfig, +} from 'axios' +import axios from 'axios' +import qs from 'qs' +import { cloneDeep } from 'lodash-es' +import type { CreateAxiosOptions } from './axiosTransform' +import { AxiosCanceler } from './axiosCancel' +import { isFunction } from '@/utils/is' +import { downloadByData } from '@/utils/file/download' +import type { RequestOptions, Result, UploadFileParams } from '/#/axios' +import { ContentTypeEnum, RequestEnum } from '@/enums/httpEnum' + +/** + * @description: axios 模块 + */ +export class VAxios { + private axiosInstance: AxiosInstance + private readonly options: CreateAxiosOptions + + constructor(options: CreateAxiosOptions) { + this.options = options + this.axiosInstance = axios.create(options) + this.setupInterceptors() + } + + /** + * @description: 创建 axios 实例 + */ + private createAxios(config: CreateAxiosOptions): void { + this.axiosInstance = axios.create(config) + } + + private getTransform() { + const { transform } = this.options + return transform + } + + getAxios(): AxiosInstance { + return this.axiosInstance + } + + /** + * @description: 重新配置 axios + */ + configAxios(config: CreateAxiosOptions) { + if (!this.axiosInstance) + return + + this.createAxios(config) + } + + /** + * @description: 设置通用标题 + */ + setHeader(headers: any): void { + if (!this.axiosInstance) + return + + Object.assign(this.axiosInstance.defaults.headers, headers) + } + + /** + * @description: Interceptor configuration 拦截器配置 + */ + private setupInterceptors() { + // const transform = this.getTransform(); + const { + axiosInstance, + options: { transform }, + } = this + if (!transform) + return + + const { + requestInterceptors, + requestInterceptorsCatch, + responseInterceptors, + responseInterceptorsCatch, + } = transform + + const axiosCanceler = new AxiosCanceler() + + // 请求拦截器配置处理 + this.axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => { + // If cancel repeat request is turned on, then cancel repeat request is prohibited + const requestOptions + = (config as unknown as any).requestOptions ?? this.options.requestOptions + const ignoreCancelToken = requestOptions?.ignoreCancelToken ?? true + + !ignoreCancelToken && axiosCanceler.addPending(config) + + if (requestInterceptors && isFunction(requestInterceptors)) + config = requestInterceptors(config, this.options) + + return config + }, undefined) + + // 请求拦截器错误捕获 + requestInterceptorsCatch + && isFunction(requestInterceptorsCatch) + && this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch) + + // 响应结果拦截器处理 + this.axiosInstance.interceptors.response.use(async (res: AxiosResponse) => { + if (res.data.code === 401) { + // 如果未认证,说明可能是访问令牌过期了,跳转登录页 + } + res && axiosCanceler.removePending(res.config) + if (responseInterceptors && isFunction(responseInterceptors)) + res = responseInterceptors(res) + + return res + }, undefined) + + // 响应结果拦截器错误捕获 + responseInterceptorsCatch + && isFunction(responseInterceptorsCatch) + && this.axiosInstance.interceptors.response.use(undefined, (error) => { + return responseInterceptorsCatch(axiosInstance, error) + }) + } + + /** + * @description: 文件上传 + */ + uploadFile(config: AxiosRequestConfig, params: UploadFileParams) { + const formData = new window.FormData() + const customFilename = params.name || 'file' + + if (params.filename) + formData.append(customFilename, params.file, params.filename) + + else + formData.append(customFilename, params.file) + + if (params.data) { + Object.keys(params.data).forEach((key) => { + const value = params.data![key] + if (Array.isArray(value)) { + value.forEach((item) => { + formData.append(`${key}[]`, item) + }) + return + } + + formData.append(key, params.data![key]) + }) + } + + return this.axiosInstance.request({ + ...config, + method: 'POST', + data: formData, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + 'ignoreCancelToken': true, + }, + }) + } + + // 支持表单数据 + supportFormData(config: AxiosRequestConfig) { + const headers = config.headers || this.options.headers + const contentType = headers?.['Content-Type'] || headers?.['content-type'] + + if ( + contentType !== ContentTypeEnum.FORM_URLENCODED + || !Reflect.has(config, 'data') + || config.method?.toUpperCase() === RequestEnum.GET + ) + return config + + return { + ...config, + data: qs.stringify(config.data, { arrayFormat: 'brackets' }), + } + } + + get(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'GET' }, options) + } + + post(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'POST' }, options) + } + + put(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'PUT' }, options) + } + + delete(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'DELETE' }, options) + } + + download(config: AxiosRequestConfig, title?: string, options?: RequestOptions): Promise { + let conf: CreateAxiosOptions = cloneDeep({ + ...config, + method: 'GET', + responseType: 'blob', + }) + const transform = this.getTransform() + + const { requestOptions } = this.options + + const opt: RequestOptions = Object.assign({}, requestOptions, options) + + const { beforeRequestHook, requestCatchHook } = transform || {} + + if (beforeRequestHook && isFunction(beforeRequestHook)) + conf = beforeRequestHook(conf, opt) + + conf.requestOptions = opt + + conf = this.supportFormData(conf) + + return new Promise((resolve, reject) => { + this.axiosInstance + .request>(conf) + .then((res: AxiosResponse) => { + resolve(res as unknown as Promise) + // download file + if (typeof res != 'undefined') + downloadByData(res?.data as unknown as BlobPart, title || 'export') + }) + .catch((e: Error | AxiosError) => { + if (requestCatchHook && isFunction(requestCatchHook)) { + reject(requestCatchHook(e, opt)) + return + } + if (axios.isAxiosError(e)) { + // rewrite error message from axios in here + } + reject(e) + }) + }) + } + + export(config: AxiosRequestConfig, title: string, options?: RequestOptions): Promise { + let conf: CreateAxiosOptions = cloneDeep({ + ...config, + method: 'POST', + responseType: 'blob', + }) + const transform = this.getTransform() + + const { requestOptions } = this.options + + const opt: RequestOptions = Object.assign({}, requestOptions, options) + + const { beforeRequestHook, requestCatchHook } = transform || {} + + if (beforeRequestHook && isFunction(beforeRequestHook)) + conf = beforeRequestHook(conf, opt) + + conf.requestOptions = opt + + conf = this.supportFormData(conf) + + return new Promise((resolve, reject) => { + this.axiosInstance + .request>(conf) + .then((res: AxiosResponse) => { + resolve(res as unknown as Promise) + // download file + if (typeof res != 'undefined') + downloadByData(res?.data as unknown as BlobPart, title) + }) + .catch((e: Error | AxiosError) => { + if (requestCatchHook && isFunction(requestCatchHook)) { + reject(requestCatchHook(e, opt)) + return + } + if (axios.isAxiosError(e)) { + // rewrite error message from axios in here + } + reject(e) + }) + }) + } + + request(config: AxiosRequestConfig, options?: RequestOptions): Promise { + let conf: CreateAxiosOptions = cloneDeep(config) + + // cancelToken 如果被深拷贝,会导致最外层无法使用cancel方法来取消请求 + if (config.cancelToken) + conf.cancelToken = config.cancelToken + + if (config.signal) + conf.signal = config.signal + + const transform = this.getTransform() + + const { requestOptions } = this.options + + const opt: RequestOptions = Object.assign({}, requestOptions, options) + const { beforeRequestHook, requestCatchHook, transformResponseHook } = transform || {} + if (beforeRequestHook && isFunction(beforeRequestHook)) + conf = beforeRequestHook(conf, opt) + + conf.requestOptions = opt + + conf = this.supportFormData(conf) + + return new Promise((resolve, reject) => { + this.axiosInstance + .request>(conf) + .then((res: AxiosResponse) => { + if (transformResponseHook && isFunction(transformResponseHook)) { + try { + const ret = transformResponseHook(res, opt) + resolve(ret) + } + catch (err) { + reject(err || new Error('request error!')) + } + return + } + resolve(res as unknown as Promise) + }) + .catch((e: Error | AxiosError) => { + if (requestCatchHook && isFunction(requestCatchHook)) { + reject(requestCatchHook(e, opt)) + return + } + if (axios.isAxiosError(e)) { + // 在此处重写来自 axios 的错误消息 + } + reject(e) + }) + }) + } +} diff --git a/src/utils/axios/axiosCancel.ts b/src/utils/axios/axiosCancel.ts new file mode 100644 index 0000000..e28b2c7 --- /dev/null +++ b/src/utils/axios/axiosCancel.ts @@ -0,0 +1,59 @@ +import type { AxiosRequestConfig } from 'axios' + +// 用于存储每个请求的标识和取消函数 +const pendingMap = new Map() + +function getPendingUrl(config: AxiosRequestConfig): string { + return [config.method, config.url].join('&') +} + +export class AxiosCanceler { + /** + * 添加请求 + * @param config 请求配置 + */ + public addPending(config: AxiosRequestConfig): void { + this.removePending(config) + const url = getPendingUrl(config) + const controller = new AbortController() + config.signal = config.signal || controller.signal + if (!pendingMap.has(url)) { + // 如果当前请求不在等待中,将其添加到等待中 + pendingMap.set(url, controller) + } + } + + /** + * 清除所有等待中的请求 + */ + public removeAllPending(): void { + pendingMap.forEach((abortController) => { + if (abortController) + abortController.abort() + }) + this.reset() + } + + /** + * 移除请求 + * @param config 请求配置 + */ + public removePending(config: AxiosRequestConfig): void { + const url = getPendingUrl(config) + if (pendingMap.has(url)) { + // 如果当前请求在等待中,取消它并将其从等待中移除 + const abortController = pendingMap.get(url) + if (abortController) + abortController.abort(url) + + pendingMap.delete(url) + } + } + + /** + * 重置 + */ + public reset(): void { + pendingMap.clear() + } +} diff --git a/src/utils/axios/axiosRetry.ts b/src/utils/axios/axiosRetry.ts new file mode 100644 index 0000000..e8e6e55 --- /dev/null +++ b/src/utils/axios/axiosRetry.ts @@ -0,0 +1,33 @@ +import type { AxiosError, AxiosInstance } from 'axios' + +/** + * 请求重试机制 + */ + +export class AxiosRetry { + /** + * 重试 + */ + async retry(axiosInstance: AxiosInstance, error: AxiosError) { + // eslint-disable-next-line ts/ban-ts-comment, ts/prefer-ts-expect-error + // @ts-ignore + const { config } = error.response + const { waitTime, count } = config?.requestOptions?.retryRequest ?? {} + config.__retryCount = config.__retryCount || 0 + if (config.__retryCount >= count) + return Promise.reject(error) + + config.__retryCount += 1 + // 请求返回后config的header不正确造成重试请求失败,删除返回headers采用默认headers + delete config.headers + await this.delay(waitTime) + return await axiosInstance(config) + } + + /** + * 延迟 + */ + private delay(waitTime: number) { + return new Promise(resolve => setTimeout(resolve, waitTime)) + } +} diff --git a/src/utils/axios/axiosTransform.ts b/src/utils/axios/axiosTransform.ts new file mode 100644 index 0000000..a433530 --- /dev/null +++ b/src/utils/axios/axiosTransform.ts @@ -0,0 +1,57 @@ +/** + * Data processing class, can be configured according to the project + */ +import type { + AxiosInstance, + AxiosRequestConfig, + AxiosResponse, + InternalAxiosRequestConfig, +} from 'axios' +import type { RequestOptions, Result } from '/#/axios' + +export interface CreateAxiosOptions extends AxiosRequestConfig { + authenticationScheme?: string + tokenScheme?: string + transform?: AxiosTransform + requestOptions?: RequestOptions +} + +export abstract class AxiosTransform { + /** + * @description: 在发送请求之前调用的函数。它可以根据需要修改请求配置 + */ + beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig + + /** + * @description: 处理响应数据 + */ + transformResponseHook?: (res: AxiosResponse, options: RequestOptions) => any + + /** + * @description: 请求失败处理 + */ + requestCatchHook?: (e: Error, options: RequestOptions) => Promise + + /** + * @description: 请求之前的拦截器 + */ + requestInterceptors?: ( + config: InternalAxiosRequestConfig, + options: CreateAxiosOptions, + ) => InternalAxiosRequestConfig + + /** + * @description: 请求之后的拦截器 + */ + responseInterceptors?: (res: AxiosResponse) => AxiosResponse + + /** + * @description: 请求之前的拦截器错误处理 + */ + requestInterceptorsCatch?: (error: Error) => void + + /** + * @description: 请求之后的拦截器错误处理 + */ + responseInterceptorsCatch?: (axiosInstance: AxiosInstance, error: Error) => void +} diff --git a/src/utils/axios/checkStatus.ts b/src/utils/axios/checkStatus.ts new file mode 100644 index 0000000..5b67fdd --- /dev/null +++ b/src/utils/axios/checkStatus.ts @@ -0,0 +1,69 @@ +import type { ErrorMessageMode } from '/#/axios' +import { useMessage } from '@/hooks/useMessage' +import { useUserStore } from '@/store/moules/userStore/index' +import { HttpErrorMsgEnum } from '@/enums/httpEnum' + +const { createMessage, createErrorModal } = useMessage() +const error = createMessage.error! +export function checkStatus( + status: number, + msg: string, + errorMessageMode: ErrorMessageMode = 'message', +): void { + const userStore = useUserStore() + let errMessage = '' + + switch (status) { + case 400: + errMessage = msg || HttpErrorMsgEnum.API_REQUEST_FAILED + break + // 401: Not logged in + // Jump to the login page if not logged in, and carry the path of the current page + // Return to the current page after successful login. This step needs to be operated on the login page. + case 401: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_401 + userStore.logout(true) + + break + case 403: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_403 + break + // 404请求不存在 + case 404: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_404 + break + case 405: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_405 + break + case 408: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_408 + break + case 500: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_500 + break + case 501: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_501 + break + case 502: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_502 + break + case 503: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_503 + break + case 504: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_504 + break + case 505: + errMessage = msg || HttpErrorMsgEnum.ERROR_MESSAGE_505 + break + default: + } + + if (errMessage) { + if (errorMessageMode === 'modal') + createErrorModal({ title: HttpErrorMsgEnum.ERROR_TIP, content: errMessage }) + + else if (errorMessageMode === 'message') + error({ content: errMessage, key: `global_error_message_status_${status}` }) + } +} diff --git a/src/utils/axios/helper.ts b/src/utils/axios/helper.ts new file mode 100644 index 0000000..6fc13b5 --- /dev/null +++ b/src/utils/axios/helper.ts @@ -0,0 +1,47 @@ +import { isObject, isString } from '@/utils/is' + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss' + +export function joinTimestamp( + join: boolean, + restful: T, +): T extends true ? string : object + +export function joinTimestamp(join: boolean, restful = false): string | object { + if (!join) + return restful ? '' : {} + + const now = new Date().getTime() + if (restful) + return `?_t=${now}` + + return { _t: now } +} + +/** + * @description: 请求参数时间格式 + */ +export function formatRequestDate(params: Recordable) { + if (Object.prototype.toString.call(params) !== '[object Object]') + return + + for (const key in params) { + const format = params[key]?.format ?? null + if (format && typeof format === 'function') + params[key] = params[key].format(DATE_TIME_FORMAT) + + if (isString(key)) { + const value = params[key] + if (value) { + try { + params[key] = isString(value) ? value.trim() : value + } + catch (error: any) { + throw new Error(error) + } + } + } + if (isObject(params[key])) + formatRequestDate(params[key]) + } +} diff --git a/src/utils/axios/index.ts b/src/utils/axios/index.ts new file mode 100644 index 0000000..4e7f04b --- /dev/null +++ b/src/utils/axios/index.ts @@ -0,0 +1,313 @@ +// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 +// The axios configuration can be changed according to the project, just change the file, other files can be left unchanged + +import type { AxiosInstance, AxiosResponse } from 'axios' +import { clone } from 'lodash-es' +import axios from 'axios' +import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform' +import { VAxios } from './Axios' +import { checkStatus } from './checkStatus' +import { formatRequestDate, joinTimestamp } from './helper' +import type { RequestOptions, Result } from '/#/axios' +import { AxiosRetry } from './axiosRetry' +import { useMessage } from '@/hooks/useMessage' +import { ContentTypeEnum, HttpErrorMsgEnum, HttpSuccessEnum, RequestEnum, ResultEnum } from '@/enums/httpEnum' +import { isEmpty, isNull, isString, isUndefined } from '@/utils/is' +import { deepMerge, setObjToUrlParams } from '@/utils' +import { useUserStore } from '@/store/moules/userStore/index' + +const { createMessage, createErrorModal, createSuccessModal } = useMessage() + +// 请求白名单,无须token的接口 +const whiteList: string[] = ['/login', '/refresh-token'] + +/** + * @description: 数据处理,方便区分多种处理方式 + */ +const transform: AxiosTransform = { + /** + * @description: 处理响应数据。如果数据不是预期格式,可直接抛出错误 + */ + transformResponseHook: (res: AxiosResponse, options: RequestOptions) => { + const { isTransformResponse, isReturnNativeResponse } = options + // 二进制数据则直接返回 + if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') + return res.data + + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + if (isReturnNativeResponse) + return res + + // 不进行任何处理,直接返回 + // 用于页面代码可能需要直接获取code,data,message这些信息时开启 + if (!isTransformResponse) + return res.data + + // 错误的时候返回 + + const { data } = res + + if (!data) { + // return '[HTTP] Request has no return value'; + throw new Error(HttpErrorMsgEnum.API_REQUEST_FAILED) + } + // 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式 + const { code, data: result, msg } = data + // 这里逻辑可以根据项目进行修改 + const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS + if (hasSuccess) { + let successMsg = msg + + if (isNull(successMsg) || isUndefined(successMsg) || isEmpty(successMsg)) + successMsg = HttpSuccessEnum.OPERATION_SUCCESS + + if (options.successMessageMode === 'modal') + createSuccessModal({ title: HttpSuccessEnum.SUCCESS_TIP, content: successMsg }) + + else if (options.successMessageMode === 'message') + createMessage.success(successMsg) + + return result + } + + // 在此处根据自己项目的实际情况对不同的code执行不同的操作 + // 如果不希望中断当前请求,请return数据,否则直接抛出异常即可 + let timeoutMsg = '' + switch (code) { + case ResultEnum.UNAUTHORIZED: + timeoutMsg = HttpErrorMsgEnum.API_TIMEOUT_MESSAGE + break + default: + if (msg) + timeoutMsg = msg + } + + // errorMessageMode='modal' 的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误 + // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示 + if (options.errorMessageMode === 'modal') + createErrorModal({ title: HttpErrorMsgEnum.ERROR_TIP, content: timeoutMsg }) + + else if (options.errorMessageMode === 'message') + createMessage.error(timeoutMsg) + + throw new Error(timeoutMsg || HttpErrorMsgEnum.API_REQUEST_FAILED) + }, + + // 请求之前处理config + beforeRequestHook: (config, options) => { + const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options + + if (joinPrefix) + config.url = `${config.url}` + + if (apiUrl && isString(apiUrl)) + config.url = `${apiUrl}${config.url}` + + const params = config.params || {} + const data = config.data || false + formatDate && data && !isString(data) && formatRequestDate(data) + + if (config.method?.toUpperCase() === RequestEnum.GET) { + if (!isString(params)) { + // 给 get 请求加上时间戳参数,避免从缓存中拿数据。 + let url = `${config.url}?` + for (const propName of Object.keys(params)) { + const value = params[propName] + + if (value !== void 0 && value !== null && typeof value !== 'undefined') { + if (typeof value === 'object') { + for (const val of Object.keys(value)) { + const paramss = `${propName}[${val}]` + const subPart = `${encodeURIComponent(paramss)}=` + url += `${subPart + encodeURIComponent(value[val])}&` + } + } + else { + url += `${propName}=${encodeURIComponent(value)}&` + } + } + } + url = url.slice(0, -1) + config.params = {} + config.url = url + } + else { + // 兼容restful风格 + config.url = `${config.url + params}${joinTimestamp(joinTime, true)}` + config.params = undefined + } + } + else { + if (!isString(params)) { + formatDate && formatRequestDate(params) + if ( + Reflect.has(config, 'data') + && config.data + && (Object.keys(config.data).length > 0 || config.data instanceof FormData) + ) { + config.data = data + config.params = params + } + else { + // 非GET请求如果没有提供data,则将params视为data + config.data = params + config.params = undefined + } + if (joinParamsToUrl) { + config.url = setObjToUrlParams( + config.url as string, + Object.assign({}, config.params, config.data), + ) + } + } + else { + // 兼容restful风格 + config.url = config.url + params + config.params = undefined + } + } + return config + }, + + /** + * @description: 请求拦截器处理 + */ + requestInterceptors: (config, options) => { + const userStore = useUserStore() + + // 是否需要设置 token + let isToken = (config as Recordable)?.requestOptions?.withToken === false + isToken = whiteList.some((v) => { + if (config.url) { + config.url.includes(v) + return false + } + return true + }) + // 请求之前处理config + const token = userStore.getToken + if (token && !isToken) { + // jwt token + (config as Recordable).headers[import.meta.env.VITE_GLOB_APP_TOKEN_KEY] = options.tokenScheme + ? `${options.tokenScheme} ${token}` + : token + } + + (config as Recordable).headers.Authorization = `${options.authenticationScheme} ${import.meta.env.VITE_GLOB_APP_AUTHORIZATION}` + return config + }, + + /** + * @description: 响应拦截器处理 + */ + responseInterceptors: (res: AxiosResponse) => { + return res + }, + + /** + * @description: 响应错误处理 + */ + responseInterceptorsCatch: (axiosInstance: AxiosInstance, error: any) => { + const { response, code, message, config } = error || {} + const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none' + const msg: string = response?.data?.msg ?? '' + const err: string = error?.toString?.() ?? '' + let errMessage = '' + + if (axios.isCancel(error)) + return Promise.reject(error) + + try { + if (code === 'ECONNABORTED' && message.includes('timeout')) + errMessage = HttpErrorMsgEnum.API_TIMEOUT_MESSAGE + + if (err?.includes('Network Error')) + errMessage = HttpErrorMsgEnum.NETWORK_EXCEPTION + + if (errMessage) { + if (errorMessageMode === 'modal') + createErrorModal({ title: HttpErrorMsgEnum.ERROR_TIP, content: errMessage }) + + else if (errorMessageMode === 'message') + createMessage.error(errMessage) + + return Promise.reject(error) + } + } + catch (error) { + throw new Error(error as unknown as string) + } + + checkStatus(error?.response?.status, msg, errorMessageMode) + + // 添加自动重试机制 保险起见 只针对GET请求 + const retryRequest = new AxiosRetry() + const { isOpenRetry } = config.requestOptions.retryRequest + + config.method?.toUpperCase() === RequestEnum.GET + && isOpenRetry + && retryRequest.retry(axiosInstance, error) + return Promise.reject(error) + }, +} + +function createAxios(opt?: Partial) { + return new VAxios( + // 深度合并 + deepMerge( + { + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes + // authentication schemes,e.g: Bearer + tokenScheme: 'crypto', + authenticationScheme: 'Basic', + timeout: 10 * 1000, + // 基础接口地址 + // baseURL: globSetting.apiUrl, + + headers: { 'Content-Type': ContentTypeEnum.JSON }, + // 如果是form-data格式 + // headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED }, + // 数据处理方式 + transform: clone(transform), + // 配置项,下面的选项都可以在独立的接口请求中覆盖 + requestOptions: { + // 默认将prefix 添加到url + joinPrefix: true, + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + isReturnNativeResponse: false, + // 需要对返回数据进行处理 + isTransformResponse: true, + // post请求的时候添加参数到url + joinParamsToUrl: false, + // 格式化提交参数时间 + formatDate: true, + // 消息提示类型 + errorMessageMode: 'message', + // 接口地址 + apiUrl: import.meta.env.VITE_GLOB_BASE_URL, + // 是否加入时间戳 + joinTime: true, + // 忽略重复请求 + ignoreCancelToken: true, + // 是否携带token + withToken: true, + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 100, + }, + }, + }, + opt || {}, + ), + ) +} +export const defHttp = createAxios() + +// other api url +// export const otherHttp = createAxios({ +// requestOptions: { +// apiUrl: 'xxx', +// urlPrefix: 'xxx', +// }, +// }); diff --git a/src/utils/crypto.ts b/src/utils/crypto.ts new file mode 100644 index 0000000..bf7be98 --- /dev/null +++ b/src/utils/crypto.ts @@ -0,0 +1,48 @@ +import CryptoJS from 'crypto-js' + +export default class crypto { + /** + * token加密key 使用@org.springblade.test.CryptoKeyGenerator获取,需和后端配置保持一致 + * @type {string} + */ + + static cryptoKey: string = 'Zc72Ghs63Z2b8jl7PXnr68r7B69xmRLX' + /** + * 报文加密key 使用@org.springblade.test.CryptoKeyGenerator获取,需和后端配置保持一致 + * @type {string} + */ + static aesKey: string = 'OPGbg7HHRiClg4u9euSPXt5Dtwed9qcG' + + /** + * 本地加密key 使用@org.springblade.test.CryptoKeyGenerator获取,需和后端配置保持一致 + * @type {string} + */ + static localKey: string = 'LaiJiangKeLiuXingMing_LaoTie6666' + + /** + * aes 加密方法,同java:AesUtil.encryptToBase64(text, aesKey); + */ + static encryptAES(data: string, key: string) { + const dataBytes = CryptoJS.enc.Utf8.parse(data) + const keyBytes = CryptoJS.enc.Utf8.parse(key) + const encrypted = CryptoJS.AES.encrypt(dataBytes, keyBytes, { + iv: keyBytes, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }) + return CryptoJS.enc.Base64.stringify(encrypted.ciphertext) + } + + /** + * aes 解密方法,同java:AesUtil.decryptFormBase64ToString(encrypt, aesKey); + */ + static decryptAES(data: string | CryptoJS.lib.CipherParams, key: string) { + const keyBytes = CryptoJS.enc.Utf8.parse(key) + const decrypted = CryptoJS.AES.decrypt(data, keyBytes, { + iv: keyBytes, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }) + return CryptoJS.enc.Utf8.stringify(decrypted) + } +} diff --git a/src/utils/env.ts b/src/utils/env.ts new file mode 100644 index 0000000..d1c8b66 --- /dev/null +++ b/src/utils/env.ts @@ -0,0 +1,3 @@ +export function getEnv() { + return import.meta.env +} diff --git a/src/utils/file/base64Conver.ts b/src/utils/file/base64Conver.ts new file mode 100644 index 0000000..8ed49ad --- /dev/null +++ b/src/utils/file/base64Conver.ts @@ -0,0 +1,42 @@ +/** + * @description: base64 to blob + */ +export function dataURLtoBlob(base64Buf: string): Blob { + const arr = base64Buf.split(',') + const typeItem = arr[0] + const mime = typeItem.match(/:(.*?);/)![1] + const bstr = window.atob(arr[1]) + let n = bstr.length + const u8arr = new Uint8Array(n) + while (n--) + u8arr[n] = bstr.charCodeAt(n) + + return new Blob([u8arr], { type: mime }) +} + +/** + * img url to base64 + * @param url + */ +export function urlToBase64(url: string, mineType?: string): Promise { + return new Promise((resolve, reject) => { + let canvas = document.createElement('CANVAS') as Nullable + const ctx = canvas!.getContext('2d') + + const img = new Image() + img.crossOrigin = '' + img.onload = function () { + if (!canvas || !ctx) + // eslint-disable-next-line prefer-promise-reject-errors + return reject() + + canvas.height = img.height + canvas.width = img.width + ctx.drawImage(img, 0, 0) + const dataURL = canvas.toDataURL(mineType || 'image/png') + canvas = null + resolve(dataURL) + } + img.src = url + }) +} diff --git a/src/utils/file/download.ts b/src/utils/file/download.ts new file mode 100644 index 0000000..0350036 --- /dev/null +++ b/src/utils/file/download.ts @@ -0,0 +1,86 @@ +import { openWindow } from '..' +import { dataURLtoBlob, urlToBase64 } from './base64Conver' + +/** + * Download online pictures + * @param url + * @param filename + * @param mime + * @param bom + */ +export function downloadByOnlineUrl(url: string, filename: string, mime?: string, bom?: BlobPart) { + urlToBase64(url).then((base64) => { + downloadByBase64(base64, filename, mime, bom) + }) +} + +/** + * Download pictures based on base64 + * @param buf + * @param filename + * @param mime + * @param bom + */ +export function downloadByBase64(buf: string, filename: string, mime?: string, bom?: BlobPart) { + const base64Buf = dataURLtoBlob(buf) + downloadByData(base64Buf, filename, mime, bom) +} + +/** + * Download according to the background interface file stream + * @param {*} data + * @param {*} filename + * @param {*} mime + * @param {*} bom + */ +export function downloadByData(data: BlobPart, filename: string, mime?: string, bom?: BlobPart) { + const blobData = typeof bom !== 'undefined' ? [bom, data] : [data] + const blob = new Blob(blobData, { type: mime || 'application/octet-stream' }) + + const blobURL = window.URL.createObjectURL(blob) + const tempLink = document.createElement('a') + tempLink.style.display = 'none' + tempLink.href = blobURL + tempLink.setAttribute('download', filename) + if (typeof tempLink.download === 'undefined') + tempLink.setAttribute('target', '_blank') + + document.body.appendChild(tempLink) + tempLink.click() + document.body.removeChild(tempLink) + window.URL.revokeObjectURL(blobURL) +} + +/** + * Download file according to file address + * @param {*} sUrl + */ +export function downloadByUrl({ url, target = '_blank', fileName }: { url: string, target?: TargetContext, fileName?: string }): boolean { + const isChrome = window.navigator.userAgent.toLowerCase().includes('chrome') + const isSafari = window.navigator.userAgent.toLowerCase().includes('safari') + + if (/(iP)/g.test(window.navigator.userAgent)) { + console.error('Your browser does not support download!') + return false + } + if (isChrome || isSafari) { + const link = document.createElement('a') + link.href = url + link.target = target + + if (link.download !== undefined) + link.download = fileName || url.substring(url.lastIndexOf('/') + 1, url.length) + + if (document.createEvent) { + const e = document.createEvent('MouseEvents') + e.initEvent('click', true, true) + link.dispatchEvent(e) + return true + } + } + if (!url.includes('?')) + url += '?download' + + openWindow(url, { target }) + return true +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..ca17b0e --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,81 @@ +import { intersectionWith, isEqual, mergeWith, unionWith } from 'lodash-es' +import { isArray, isObject } from '@/utils/is' + +/** + * Add the object as a parameter to the URL + * @param baseUrl url + * @param obj + * @returns {string} + * eg: + * let obj = {a: '3', b: '4'} + * setObjToUrlParams('www.baidu.com', obj) + * ==>www.baidu.com?a=3&b=4 + */ +export function setObjToUrlParams(baseUrl: string, obj: any): string { + let parameters = '' + for (const key in obj) + parameters += `${key}=${encodeURIComponent(obj[key])}&` + + parameters = parameters.replace(/&$/, '') + return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters +} + +/** + * Recursively merge two objects. + * 递归合并两个对象。 + * + * @param source The source object to merge from. 要合并的源对象。 + * @param target The target object to merge into. 目标对象,合并后结果存放于此。 + * @param mergeArrays How to merge arrays. Default is "replace". + * 如何合并数组。默认为replace。 + * - "union": Union the arrays. 对数组执行并集操作。 + * - "intersection": Intersect the arrays. 对数组执行交集操作。 + * - "concat": Concatenate the arrays. 连接数组。 + * - "replace": Replace the source array with the target array. 用目标数组替换源数组。 + * @returns The merged object. 合并后的对象。 + */ +export function deepMerge( + source: T, + target: U, + mergeArrays: 'union' | 'intersection' | 'concat' | 'replace' = 'replace', +): T & U { + if (!target) + return source as T & U + + if (!source) + return target as T & U + + return mergeWith({}, source, target, (sourceValue, targetValue) => { + if (isArray(targetValue) && isArray(sourceValue)) { + switch (mergeArrays) { + case 'union': + return unionWith(sourceValue, targetValue, isEqual) + case 'intersection': + return intersectionWith(sourceValue, targetValue, isEqual) + case 'concat': + return sourceValue.concat(targetValue) + case 'replace': + return targetValue + default: + throw new Error(`Unknown merge array strategy: ${mergeArrays as string}`) + } + } + if (isObject(targetValue) && isObject(sourceValue)) + return deepMerge(sourceValue, targetValue, mergeArrays) + + return undefined + }) +} + +export function openWindow( + url: string, + opt?: { target?: TargetContext | string, noopener?: boolean, noreferrer?: boolean }, +) { + const { target = '__blank', noopener = true, noreferrer = true } = opt || {} + const feature: string[] = [] + + noopener && feature.push('noopener=yes') + noreferrer && feature.push('noreferrer=yes') + + window.open(url, target, feature.join(',')) +} diff --git a/src/utils/is.ts b/src/utils/is.ts new file mode 100644 index 0000000..c4c1917 --- /dev/null +++ b/src/utils/is.ts @@ -0,0 +1,66 @@ +export { + isArguments, + isArrayBuffer, + isArrayLike, + isArrayLikeObject, + isBuffer, + isBoolean, + isDate, + isElement, + isEmpty, + isEqual, + isEqualWith, + isError, + isFunction, + isFinite, + isLength, + isMap, + isMatch, + isMatchWith, + isNative, + isNil, + isNumber, + isNull, + isObjectLike, + isPlainObject, + isRegExp, + isSafeInteger, + isSet, + isString, + isSymbol, + isTypedArray, + isUndefined, + isWeakMap, + isWeakSet, +} from 'lodash-es' + +const toString = Object.prototype.toString + +export function is(val: unknown, type: string) { + return toString.call(val) === `[object ${type}]` +} + +export function isDef(val?: T): val is T { + return typeof val !== 'undefined' +} + +export function isObject(val: any): val is Record { + return val !== null && is(val, 'Object') +} + +export function isArray(val: any): val is Array { + return val && Array.isArray(val) +} + +export function isWindow(val: any): val is Window { + return typeof window !== 'undefined' && is(val, 'Window') +} + +export const isServer = typeof window === 'undefined' + +export const isClient = !isServer + +export function isHttpUrl(path: string): boolean { + const reg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/ + return reg.test(path) +} diff --git a/src/views/conversation/index.vue b/src/views/conversation/index.vue new file mode 100644 index 0000000..d8db631 --- /dev/null +++ b/src/views/conversation/index.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/src/views/error/404.vue b/src/views/error/404.vue new file mode 100644 index 0000000..712cfd4 --- /dev/null +++ b/src/views/error/404.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/src/views/login.vue b/src/views/login.vue deleted file mode 100644 index 65c5dc5..0000000 --- a/src/views/login.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - - - diff --git a/src/views/login/index.vue b/src/views/login/index.vue new file mode 100644 index 0000000..36c5fdb --- /dev/null +++ b/src/views/login/index.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/views/textToPicture/index.vue b/src/views/textToPicture/index.vue new file mode 100644 index 0000000..512b931 --- /dev/null +++ b/src/views/textToPicture/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts deleted file mode 100644 index 11f02fe..0000000 --- a/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/tsconfig.json b/tsconfig.json index 0bd78d5..ebe8a0c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,9 +10,11 @@ /* Bundler mode */ "moduleResolution": "bundler", "paths": { - "@/*": ["src/*"] + "@/*": ["src/*"], + "/#/*": ["types/*"] }, "resolveJsonModule": true, + "types": ["vite/client"], "allowImportingTsExtensions": true, "strict": true, @@ -26,6 +28,6 @@ "isolatedModules": true, "skipLibCheck": true }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "types/**/*"], "exclude": ["dist", "node_modules"] } diff --git a/types/axios.d.ts b/types/axios.d.ts new file mode 100644 index 0000000..94846a1 --- /dev/null +++ b/types/axios.d.ts @@ -0,0 +1,54 @@ +export type ErrorMessageMode = 'none' | 'modal' | 'message' | undefined +export type SuccessMessageMode = ErrorMessageMode + +export interface RequestOptions { + // Splicing request parameters to url + joinParamsToUrl?: boolean + // Format request parameter time + formatDate?: boolean + // Whether to process the request result + isTransformResponse?: boolean + // Whether to return native response headers + // For example: use this attribute when you need to get the response headers + isReturnNativeResponse?: boolean + // Whether to join url + joinPrefix?: boolean + // Interface address, use the default apiUrl if you leave it blank + apiUrl?: string + // Error message prompt type + errorMessageMode?: ErrorMessageMode + // Success message prompt type + successMessageMode?: SuccessMessageMode + // Whether to add a timestamp + joinTime?: boolean + ignoreCancelToken?: boolean + // Whether to send token in header + withToken?: boolean + // 请求重试机制 + retryRequest?: RetryRequest +} + +export interface RetryRequest { + isOpenRetry: boolean + count: number + waitTime: number +} + +export interface Result { + code: number + msg: string + data: T +} + +// multipart/form-data: upload file +export interface UploadFileParams { + // Other parameters + data?: Recordable + // File parameter interface field name + name?: string + // file name + file: File | Blob + // file name + filename?: string + [key: string]: any +} diff --git a/types/global.d.ts b/types/global.d.ts new file mode 100644 index 0000000..b184ee3 --- /dev/null +++ b/types/global.d.ts @@ -0,0 +1,98 @@ +import type { ComponentPublicInstance, ComponentRenderProxy, FunctionalComponent, VNode, VNodeChild, PropType as VuePropType } from 'vue' + +declare type Recordable = Record + +declare type Nullable = T | null + +declare global { + const __APP_INFO__: { + pkg: { + name: string + version: string + dependencies: Recordable + devDependencies: Recordable + } + lastBuildTime: string + } + declare interface Window { + _hmt: [string, string][] + } + + interface Document { + mozFullScreenElement?: Element + msFullscreenElement?: Element + webkitFullscreenElement?: Element + } + + // vue + declare type PropType = VuePropType + declare type VueNode = VNodeChild | JSX.Element + + export type Writable = { + -readonly [P in keyof T]: T[P] + } + + declare type Nullable = T | null + declare type NonNullable = T extends null | undefined ? never : T + declare type Recordable = Record + declare interface ReadonlyRecordable { + readonly [key: string]: T + } + declare interface Indexable { + [key: string]: T + } + declare type DeepPartial = { + [P in keyof T]?: DeepPartial + } + declare type TimeoutHandle = ReturnType + declare type IntervalHandle = ReturnType + + declare interface ChangeEvent extends Event { + target: HTMLInputElement + } + + declare interface WheelEvent { + path?: EventTarget[] + } + interface ImportMetaEnv extends ViteEnv { + __: unknown + } + + declare interface ViteEnv { + VITE_PORT: number + VITE_USE_PWA: boolean + VITE_PUBLIC_PATH: string + VITE_PROXY: [string, string][] + VITE_GLOB_APP_TITLE: string + VITE_GLOB_APP_SHORT_NAME: string + VITE_USE_CDN: boolean + VITE_DROP_CONSOLE: boolean + VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none' + VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean + VITE_GENERATE_UI: string + } + + declare function parseInt(s: string | number, radix?: number): number + + declare function parseFloat(string: string | number): number + + namespace JSX { + // tslint:disable no-empty-interface + type Element = VNode + // tslint:disable no-empty-interface + type ElementClass = ComponentRenderProxy + interface ElementAttributesProperty { + $props: any + } + interface IntrinsicElements { + [elem: string]: any + } + interface IntrinsicAttributes { + [elem: string]: any + } + } +} + +declare module 'vue' { + export type JSXComponent = { new (): ComponentPublicInstance } | FunctionalComponent +} diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..a608579 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1 @@ +declare type TargetContext = '_self' | '_blank' diff --git a/types/shims-vue.d.ts b/types/shims-vue.d.ts new file mode 100644 index 0000000..9a74572 --- /dev/null +++ b/types/shims-vue.d.ts @@ -0,0 +1,6 @@ +declare module '*.vue' { + import type { DefineComponent } from 'vue' + + const component: DefineComponent + export default component +} diff --git a/types/vite-env.d.ts b/types/vite-env.d.ts new file mode 100644 index 0000000..4616d11 --- /dev/null +++ b/types/vite-env.d.ts @@ -0,0 +1,12 @@ +/// + +interface ImportMetaEnv { + NODE_ENV: string + + VITE_GLOB_APP_TITLE: string + VITE_GLOB_APP_SHORT_NAME: string + VITE_GLOB_BASE_URL: string + VITE_GLOB_MQTT_URL: string + VITE_GLOB_APP_AUTHORIZATION: string + VITE_GLOB_APP_TOKEN_KEY: string +} diff --git a/types/vue-router.d.ts b/types/vue-router.d.ts new file mode 100644 index 0000000..05629a4 --- /dev/null +++ b/types/vue-router.d.ts @@ -0,0 +1,19 @@ +export {} + +declare module 'vue-router' { + interface RouteMeta extends Record { + orderNo?: number + // 路由title 一般必填 + title: string + // 是否忽略权限,只在权限模式为Role的时候有效 + ignoreAuth?: boolean + // 是否固定标签 + affix?: boolean + // 图标,也是菜单图标 + icon?: string + // img on tab + img?: string + // 内嵌iframe的地址 + frameSrc?: string + } +} diff --git a/vite.config.ts b/vite.config.ts index 5938e5f..8831b8e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,10 +2,19 @@ import { join, resolve } from 'node:path' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import UnoCSS from 'unocss/vite' +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' // https://vitejs.dev/config/ export default defineConfig({ - plugins: [vue(), UnoCSS()], + plugins: [ + vue(), + UnoCSS(), + createSvgIconsPlugin({ + // eslint-disable-next-line node/prefer-global/process + iconDirs: [resolve(process.cwd(), 'src/assets/svg')], + symbolId: 'icon-[name]', + }), + ], server: { host: '0.0.0.0', }, @@ -15,4 +24,13 @@ export default defineConfig({ '@': join(__dirname, 'src'), }, }, + // 全局 css 注册 + css: { + preprocessorOptions: { + scss: { + javascriptEnabled: true, + additionalData: `@import "src/design/index.scss";`, + }, + }, + }, })