diff --git a/.gitignore b/.gitignore index 872102ee..1f0bea9a 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,5 @@ stats.html *.sw? /src/typings/components.d.ts -/src/typings/router-page.d.ts package-lock.json yarn.lock diff --git a/index.html b/index.html index be0f0d68..6b249216 100644 --- a/index.html +++ b/index.html @@ -3,25 +3,12 @@ - <%= appName %>
-
- -
-
-
-
-
-
-
-
-
<%= appTitle %>
-
- +
diff --git a/package.json b/package.json index d6fc2810..88ba694a 100644 --- a/package.json +++ b/package.json @@ -81,11 +81,11 @@ "vue-router": "^4.1.6", "vuedraggable": "^4.1.0", "wangeditor": "^4.7.15", - "xgplayer": "^2.32.1" + "xgplayer": "^2.32.2" }, "devDependencies": { "@amap/amap-jsapi-types": "^0.0.10", - "@iconify/json": "^2.1.136", + "@iconify/json": "^2.1.139", "@iconify/vue": "^4.0.0", "@soybeanjs/router-page": "1.0.3", "@types/bmapgl": "^0.0.5", @@ -107,7 +107,7 @@ "esno": "^0.16.3", "husky": "^8.0.2", "mockjs": "^1.1.0", - "npm-check-updates": "^16.3.25", + "npm-check-updates": "^16.4.1", "rimraf": "^3.0.2", "rollup-plugin-visualizer": "^5.8.3", "sass": "^1.56.1", @@ -117,7 +117,7 @@ "unplugin-vue-components": "0.22.9", "unplugin-vue-macros": "^0.16.3", "utility-types": "^3.10.0", - "vite": "^3.2.3", + "vite": "^3.2.4", "vite-plugin-compression": "^0.5.1", "vite-plugin-html": "^3.2.0", "vite-plugin-mock": "^2.9.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d477609e..3955ac05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ specifiers: '@antv/data-set': ^0.11.8 '@antv/g2': ^4.2.8 '@better-scroll/core': ^2.5.0 - '@iconify/json': ^2.1.136 + '@iconify/json': ^2.1.139 '@iconify/vue': ^4.0.0 '@soybeanjs/router-page': 1.0.3 '@soybeanjs/vue-admin-layout': ^1.1.1 @@ -44,7 +44,7 @@ specifiers: lodash-es: ^4.17.21 mockjs: ^1.1.0 naive-ui: 2.33.5 - npm-check-updates: ^16.3.25 + npm-check-updates: ^16.4.1 pinia: ^2.0.23 print-js: ^1.6.0 qs: ^6.11.0 @@ -60,7 +60,7 @@ specifiers: unplugin-vue-macros: ^0.16.3 utility-types: ^3.10.0 vditor: ^3.8.18 - vite: ^3.2.3 + vite: ^3.2.4 vite-plugin-compression: ^0.5.1 vite-plugin-html: ^3.2.0 vite-plugin-mock: ^2.9.6 @@ -73,7 +73,7 @@ specifiers: vue-tsc: ^1.0.9 vuedraggable: ^4.1.0 wangeditor: ^4.7.15 - xgplayer: ^2.32.1 + xgplayer: ^2.32.2 zx: ^7.1.1 dependencies: @@ -103,11 +103,11 @@ dependencies: vue-router: 4.1.6_vue@3.2.45 vuedraggable: 4.1.0_vue@3.2.45 wangeditor: 4.7.15 - xgplayer: 2.32.1 + xgplayer: 2.32.2 devDependencies: '@amap/amap-jsapi-types': 0.0.10 - '@iconify/json': 2.1.136 + '@iconify/json': 2.1.139 '@iconify/vue': 4.0.0_vue@3.2.45 '@soybeanjs/router-page': 1.0.3 '@types/bmapgl': 0.0.5 @@ -116,9 +116,9 @@ devDependencies: '@types/qs': 6.9.7 '@types/ua-parser-js': 0.7.36 '@unocss/preset-uno': 0.46.5 - '@unocss/vite': 0.46.5_rollup@2.79.1+vite@3.2.3 - '@vitejs/plugin-vue': 3.2.0_vite@3.2.3+vue@3.2.45 - '@vitejs/plugin-vue-jsx': 2.1.1_vite@3.2.3+vue@3.2.45 + '@unocss/vite': 0.46.5_rollup@2.79.1+vite@3.2.4 + '@vitejs/plugin-vue': 3.2.0_vite@3.2.4+vue@3.2.45 + '@vitejs/plugin-vue-jsx': 2.1.1_vite@3.2.4+vue@3.2.45 commitlint: 17.2.0 conventional-changelog: 3.1.25 cross-env: 7.0.3 @@ -129,7 +129,7 @@ devDependencies: esno: 0.16.3 husky: 8.0.2 mockjs: 1.1.0_3y7clh66jsbznbjsqlxuh6722u - npm-check-updates: 16.3.25 + npm-check-updates: 16.4.1 rimraf: 3.0.2 rollup-plugin-visualizer: 5.8.3_rollup@2.79.1 sass: 1.56.1 @@ -137,15 +137,15 @@ devDependencies: typescript: 4.8.4 unplugin-icons: 0.14.13 unplugin-vue-components: 0.22.9_rollup@2.79.1+vue@3.2.45 - unplugin-vue-macros: 0.16.3_mtjmd4d7yri6vok5vdb7foxsoq + unplugin-vue-macros: 0.16.3_wngx4xzvqgttz6r2laqlxyas2u utility-types: 3.10.0 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i - vite-plugin-compression: 0.5.1_vite@3.2.3 - vite-plugin-html: 3.2.0_vite@3.2.3 - vite-plugin-mock: 2.9.6_qj5sox3st75utfpfnxdchh4ucq - vite-plugin-progress: 0.0.6_vite@3.2.3 - vite-plugin-pwa: 0.13.3_jklrv2undatkozcsn24zow6xuu - vite-plugin-svg-icons: 2.0.1_vite@3.2.3 + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i + vite-plugin-compression: 0.5.1_vite@3.2.4 + vite-plugin-html: 3.2.0_vite@3.2.4 + vite-plugin-mock: 2.9.6_55m5mhr4n72hhmialh5t5h2xye + vite-plugin-progress: 0.0.6_vite@3.2.4 + vite-plugin-pwa: 0.13.3_ncfuj3sngaz4xbo7yyj2tfhvju + vite-plugin-svg-icons: 2.0.1_vite@3.2.4 vue-tsc: 1.0.9_typescript@4.8.4 zx: 7.1.1 @@ -1637,11 +1637,11 @@ packages: '@types/node': 14.18.33 chalk: 4.1.2 cosmiconfig: 7.1.0 - cosmiconfig-typescript-loader: 4.2.0_zhrz2lclwdmp54iaqottwiuipu + cosmiconfig-typescript-loader: 4.2.0_qoh33be55smklb2oyrgdyddh4a lodash: 4.17.21 resolve-from: 5.0.0 ts-node: 10.9.1_cbe7ovvae6zqfnmtgctpgpys54 - typescript: 4.8.4 + typescript: 4.9.3 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -1833,8 +1833,8 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@iconify/json/2.1.136: - resolution: {integrity: sha512-tO5hV+yXn87+OCQqiVzis6i4YQiRX4044ZjubP6GmbeclE6tsypK+by/tXjbm90GTX0jhsOJ6YLzWl3szivywg==} + /@iconify/json/2.1.139: + resolution: {integrity: sha512-H/DQ/yVgdUk4x4hU696fy0mZOkvLQaR6REQU/okFLgaiIFOS+EWw6GV5JDSKbbkh0YVaxUrAUaqB8XTSFVrFeA==} dependencies: '@iconify/types': 2.0.0 pathe: 0.3.9 @@ -2569,7 +2569,7 @@ packages: css-tree: 2.2.1 dev: true - /@unocss/vite/0.46.5_rollup@2.79.1+vite@3.2.3: + /@unocss/vite/0.46.5_rollup@2.79.1+vite@3.2.4: resolution: {integrity: sha512-/auNcS1L3PjwAA3U/i9scJf2Zx3kkgCdKiXyfetjws4ddAnVE+LrDmIKbbdSUiWFoq9W2QOPpOPpV2xips2gmg==} peerDependencies: vite: ^2.9.0 || ^3.0.0-0 @@ -2582,12 +2582,12 @@ packages: '@unocss/scope': 0.46.5 '@unocss/transformer-directives': 0.46.5 magic-string: 0.26.7 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i transitivePeerDependencies: - rollup dev: true - /@vitejs/plugin-vue-jsx/2.1.1_vite@3.2.3+vue@3.2.45: + /@vitejs/plugin-vue-jsx/2.1.1_vite@3.2.4+vue@3.2.45: resolution: {integrity: sha512-JgDhxstQlwnHBvZ1BSnU5mbmyQ14/t5JhREc6YH5kWyu2QdAAOsLF6xgHoIWarj8tddaiwFrNzLbWJPudpXKYA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2597,20 +2597,20 @@ packages: '@babel/core': 7.20.2 '@babel/plugin-transform-typescript': 7.20.2_@babel+core@7.20.2 '@vue/babel-plugin-jsx': 1.1.1_@babel+core@7.20.2 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i vue: 3.2.45 transitivePeerDependencies: - supports-color dev: true - /@vitejs/plugin-vue/3.2.0_vite@3.2.3+vue@3.2.45: + /@vitejs/plugin-vue/3.2.0_vite@3.2.4+vue@3.2.45: resolution: {integrity: sha512-E0tnaL4fr+qkdCNxJ+Xd0yM31UwMkQje76fsDVBBUCoGOUPexu2VDUYHL8P4CwV+zMvWw6nlRw19OnRKmYAJpw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^3.0.0 vue: ^3.2.25 dependencies: - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i vue: 3.2.45 dev: true @@ -2742,16 +2742,16 @@ packages: unplugin: 0.10.2 dev: true - /@vue-macros/named-template/0.0.5_pwzry6ifamiyy66hle7uchcfiy: + /@vue-macros/named-template/0.0.5_2aqiuug577r2uhg7pi2e2y3u2a: resolution: {integrity: sha512-bZRUljNyvOOqeE9dyqXvKPQCLUCcPt1EkThmXqSbxagV29ohyviF8+CCs/8OdmNygLTBIChjP8DexQ3nUIFzUg==} engines: {node: '>=14.19.0'} dependencies: '@rollup/pluginutils': 4.2.1 - '@vitejs/plugin-vue': 3.2.0_vite@3.2.3+vue@3.2.45 + '@vitejs/plugin-vue': 3.2.0_vite@3.2.4+vue@3.2.45 '@vue-macros/common': 0.13.3 '@vue/compiler-dom': 3.2.45 unplugin: 0.10.2 - unplugin-combine: 0.2.8_rollup@2.79.1+vite@3.2.3 + unplugin-combine: 0.2.8_rollup@2.79.1+vite@3.2.4 transitivePeerDependencies: - esbuild - rollup @@ -2760,14 +2760,14 @@ packages: - webpack dev: true - /@vue-macros/setup-component/0.12.7_rollup@2.79.1+vite@3.2.3: + /@vue-macros/setup-component/0.12.7_rollup@2.79.1+vite@3.2.4: resolution: {integrity: sha512-L0WkJgw0QDwZh4tOjjKIDR0DMIybiOunsaxVqkJjicTb2YaiRUSLq4Wadl8Ttrsd0IEfI51CSlg7Sx0/dKLrlQ==} engines: {node: '>=14.19.0'} dependencies: '@rollup/pluginutils': 4.2.1 '@vue-macros/common': 0.13.3 unplugin: 0.10.2 - unplugin-combine: 0.2.8_rollup@2.79.1+vite@3.2.3 + unplugin-combine: 0.2.8_rollup@2.79.1+vite@3.2.4 transitivePeerDependencies: - esbuild - rollup @@ -4006,7 +4006,7 @@ packages: vary: 1.1.2 dev: true - /cosmiconfig-typescript-loader/4.2.0_zhrz2lclwdmp54iaqottwiuipu: + /cosmiconfig-typescript-loader/4.2.0_qoh33be55smklb2oyrgdyddh4a: resolution: {integrity: sha512-NkANeMnaHrlaSSlpKGyvn2R4rqUDeE/9E5YHx+b4nwo0R8dZyAqcih8/gxpCZvqWP9Vf6xuLpMSzSgdVEIM78g==} engines: {node: '>=12', npm: '>=6'} peerDependencies: @@ -4018,7 +4018,7 @@ packages: '@types/node': 14.18.33 cosmiconfig: 7.1.0 ts-node: 10.9.1_cbe7ovvae6zqfnmtgctpgpys54 - typescript: 4.8.4 + typescript: 4.9.3 dev: true /cosmiconfig/7.1.0: @@ -7820,8 +7820,8 @@ packages: npm-normalize-package-bin: 3.0.0 dev: true - /npm-check-updates/16.3.25: - resolution: {integrity: sha512-zrjx6P7LGHYS5e3TNuSqkWQc9m1KLjJIxFERGANN+xEY826NQYG08RwucUD9nRxIlRE9PsGCcMsJJTYJu1DHbA==} + /npm-check-updates/16.4.1: + resolution: {integrity: sha512-g0Uf1kCw0p5boutvu5E4htsjYEDuFT9LxYHYFLldAzWs5012jVikEH1Wdae68xedu4twF4EVbKcs83+G2nGnQg==} engines: {node: '>=14.14'} hasBin: true dependencies: @@ -10396,6 +10396,12 @@ packages: engines: {node: '>=4.2.0'} hasBin: true + /typescript/4.9.3: + resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + /ua-parser-js/1.0.32: resolution: {integrity: sha512-dXVsz3M4j+5tTiovFVyVqssXBu5HM47//YSOeZ9fQkdDKkfzv2v3PP1jmH6FUyPW+yCSn7aBVK1fGGKNhowdDA==} dev: false @@ -10595,7 +10601,7 @@ packages: engines: {node: '>= 0.8'} dev: true - /unplugin-combine/0.2.8_rollup@2.79.1+vite@3.2.3: + /unplugin-combine/0.2.8_rollup@2.79.1+vite@3.2.4: resolution: {integrity: sha512-Z38AC/TEjXbVyZ5HjVqo+lADj0/dcfwWC0Z4y0LNhybJzJQwmcMxm+ZsqHY3faauj4YigmlRMdptR5JEW9RuLg==} engines: {node: '>=14.19.0'} peerDependencies: @@ -10616,7 +10622,7 @@ packages: '@antfu/utils': 0.6.3 rollup: 2.79.1 unplugin: 0.10.2 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i dev: true /unplugin-icons/0.14.13: @@ -10683,7 +10689,7 @@ packages: unplugin: 0.10.2 dev: true - /unplugin-vue-macros/0.16.3_mtjmd4d7yri6vok5vdb7foxsoq: + /unplugin-vue-macros/0.16.3_wngx4xzvqgttz6r2laqlxyas2u: resolution: {integrity: sha512-ADdDS5EjHRZ2esEHSNBw7CS7QLWpqvNJIW0H5EqKgSvtQ+2Hnb8IeRVT0f4mR+wyQvl/ZrlpTs1GvZdsh8eSlw==} engines: {node: '>=14.19.0'} peerDependencies: @@ -10696,12 +10702,12 @@ packages: '@vue-macros/define-render': 0.13.8_vue@3.2.45 '@vue-macros/define-slots': 0.0.5_vue@3.2.45 '@vue-macros/hoist-static': 0.12.7 - '@vue-macros/named-template': 0.0.5_pwzry6ifamiyy66hle7uchcfiy - '@vue-macros/setup-component': 0.12.7_rollup@2.79.1+vite@3.2.3 + '@vue-macros/named-template': 0.0.5_2aqiuug577r2uhg7pi2e2y3u2a + '@vue-macros/setup-component': 0.12.7_rollup@2.79.1+vite@3.2.4 '@vue-macros/setup-sfc': 0.12.7 '@vue-macros/short-emits': 0.12.8 local-pkg: 0.4.2 - unplugin-combine: 0.2.8_rollup@2.79.1+vite@3.2.3 + unplugin-combine: 0.2.8_rollup@2.79.1+vite@3.2.4 unplugin-vue-define-options: 0.12.7 vue: 3.2.45 transitivePeerDependencies: @@ -10862,7 +10868,7 @@ packages: vfile-message: 2.0.4 dev: true - /vite-plugin-compression/0.5.1_vite@3.2.3: + /vite-plugin-compression/0.5.1_vite@3.2.4: resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} peerDependencies: vite: '>=2.0.0' @@ -10870,12 +10876,12 @@ packages: chalk: 4.1.2 debug: 4.3.4 fs-extra: 10.1.0 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i transitivePeerDependencies: - supports-color dev: true - /vite-plugin-html/3.2.0_vite@3.2.3: + /vite-plugin-html/3.2.0_vite@3.2.4: resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==} peerDependencies: vite: '>=2.0.0' @@ -10892,10 +10898,10 @@ packages: html-minifier-terser: 6.1.0 node-html-parser: 5.4.2 pathe: 0.2.0 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i dev: true - /vite-plugin-mock/2.9.6_qj5sox3st75utfpfnxdchh4ucq: + /vite-plugin-mock/2.9.6_55m5mhr4n72hhmialh5t5h2xye: resolution: {integrity: sha512-/Rm59oPppe/ncbkSrUuAxIQihlI2YcBmnbR4ST1RA2VzM1C0tEQc1KlbQvnUGhXECAGTaQN2JyasiwXP6EtKgg==} engines: {node: '>=12.0.0'} peerDependencies: @@ -10912,13 +10918,13 @@ packages: fast-glob: 3.2.12 mockjs: 1.1.0_3y7clh66jsbznbjsqlxuh6722u path-to-regexp: 6.2.1 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i transitivePeerDependencies: - rollup - supports-color dev: true - /vite-plugin-progress/0.0.6_vite@3.2.3: + /vite-plugin-progress/0.0.6_vite@3.2.4: resolution: {integrity: sha512-pIK2TVEY4XFGrz10CQDdEufBBCDaV0geRHfXV3abGTBr+OF9O0Zmd3ZDrHJXDv4Rl3qAQP4BTCuPYQ3XqstmqA==} engines: {node: '>=14', pnpm: '>=7.0.0'} peerDependencies: @@ -10927,10 +10933,10 @@ packages: picocolors: 1.0.0 progress: 2.0.3 rd: 2.0.1 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i dev: true - /vite-plugin-pwa/0.13.3_jklrv2undatkozcsn24zow6xuu: + /vite-plugin-pwa/0.13.3_ncfuj3sngaz4xbo7yyj2tfhvju: resolution: {integrity: sha512-cjWXpZ7slAY14OKz7M8XdgTIi9wjf6OD6NkhiMAc+ogxnbUrecUwLdRtfGPCPsN2ftut5gaN1jTghb11p6IQAA==} peerDependencies: vite: ^3.1.0 @@ -10942,14 +10948,14 @@ packages: fast-glob: 3.2.12 pretty-bytes: 6.0.0 rollup: 2.79.1 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i workbox-build: 6.5.4 workbox-window: 6.5.4 transitivePeerDependencies: - supports-color dev: true - /vite-plugin-svg-icons/2.0.1_vite@3.2.3: + /vite-plugin-svg-icons/2.0.1_vite@3.2.4: resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==} peerDependencies: vite: '>=2.0.0' @@ -10962,13 +10968,13 @@ packages: pathe: 0.2.0 svg-baker: 1.7.0 svgo: 2.8.0 - vite: 3.2.3_ajklay5k626t46b6fyghkbup3i + vite: 3.2.4_ajklay5k626t46b6fyghkbup3i transitivePeerDependencies: - supports-color dev: true - /vite/3.2.3_ajklay5k626t46b6fyghkbup3i: - resolution: {integrity: sha512-h8jl1TZ76eGs3o2dIBSsvXDLb1m/Ec1iej8ZMdz+PsaFUsftZeWe2CZOI3qogEsMNaywc17gu0q6cQDzh/weCQ==} + /vite/3.2.4_ajklay5k626t46b6fyghkbup3i: + resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -11427,8 +11433,8 @@ packages: generate-source-map: 0.0.5 dev: false - /xgplayer/2.32.1: - resolution: {integrity: sha512-jUs6108INqnzEn3DTGre6pHW3KroM2w0VKuJNEvOIkoD2oUB+MW5ZZ0PsIwijX/oQRpmvq422CUgo4uqXVidEQ==} + /xgplayer/2.32.2: + resolution: {integrity: sha512-VWK8Hp5K3Fs5YoHadpyCw2zwuiOimRjkPo2PSJZPYKj59VNnL9oLruZp6cy86LHoAgWELRIQj6Nmw5SkQNByWQ==} hasBin: true dependencies: chalk: 2.4.2 diff --git a/public/resource/loading.css b/public/resource/loading.css deleted file mode 100644 index 4f2a1bdb..00000000 --- a/public/resource/loading.css +++ /dev/null @@ -1,91 +0,0 @@ -.loading-container { - position: fixed; - left: 0; - top: 0; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; -} - -.loading-svg { - width: 128px; - height: 128px; - color: var(--primary-color); -} - -.loading-spin__container { - width: 56px; - height: 56px; - margin: 36px 0; -} - -.loading-spin { - position: relative; - height: 100%; - animation: loadingSpin 1s linear infinite; -} - -.left-0 { - left: 0; -} -.right-0 { - right: 0; -} -.top-0 { - top: 0; -} -.bottom-0 { - bottom: 0; -} - -.loading-spin-item { - position: absolute; - height: 16px; - width: 16px; - background-color: var(--primary-color); - border-radius: 8px; - -webkit-animation: loadingPulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; - animation: loadingPulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; -} - -@keyframes loadingSpin { - from { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - to { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -@keyframes loadingPulse { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: .5; - } -} - -.loading-delay-500 { - -webkit-animation-delay: 500ms; - animation-delay: 500ms; -} -.loading-delay-1000 { - -webkit-animation-delay: 1000ms; - animation-delay: 1000ms; -} -.loading-delay-1500 { - -webkit-animation-delay: 1500ms; - animation-delay: 1500ms; -} - -.loading-title { - font-size: 28px; - font-weight: 500; - color: #646464; -} diff --git a/public/resource/loading.js b/public/resource/loading.js deleted file mode 100644 index f9aa943d..00000000 --- a/public/resource/loading.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * 初始化加载效果的svg格式logo - * @param {string} id - 元素id - */ -function initSvgLogo(id) { - const svgStr = ` - - - - - - `; - const appEl = document.querySelector(id); - const div = document.createElement('div'); - div.innerHTML = svgStr; - if (appEl) { - appEl.appendChild(div); - } -} - -function addThemeColorCssVars() { - const key = '__THEME_COLOR__'; - const defaultColor = '#1890ff'; - const themeColor = window.localStorage.getItem(key) || defaultColor; - const cssVars = `--primary-color: ${themeColor}`; - document.documentElement.style.cssText = cssVars; -} - -addThemeColorCssVars(); - -initSvgLogo('#loadingLogo'); diff --git a/src/components/common/AppLoading.vue b/src/components/common/AppLoading.vue new file mode 100644 index 00000000..1d2bab3b --- /dev/null +++ b/src/components/common/AppLoading.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/src/enum/common.ts b/src/enum/common.ts index 598ee9c9..9ed5a063 100644 --- a/src/enum/common.ts +++ b/src/enum/common.ts @@ -5,22 +5,6 @@ export enum EnumContentType { formData = 'multipart/form-data' } -/** 缓存的key */ -export enum EnumStorageKey { - /** 主题颜色 */ - 'theme-color' = '__THEME_COLOR__', - /** 用户token */ - 'token' = '__TOKEN__', - /** 用户刷新token */ - 'refresh-token' = '__REFRESH_TOKEN__', - /** 用户信息 */ - 'user-info' = '__USER_INFO__', - /** 主题配置 */ - 'theme-settings' = '__THEME_SETTINGS__', - /** 多页签路由信息 */ - 'multi-tab-routes' = '__MULTI_TAB_ROUTES__' -} - /** 数据类型 */ export enum EnumDataType { number = '[object Number]', diff --git a/src/main.ts b/src/main.ts index 6a81dfb8..61517e21 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,6 @@ import { createApp } from 'vue'; import App from './App.vue'; +import AppLoading from './components/common/AppLoading.vue'; import { setupDirectives } from './directives'; import { setupRouter } from './router'; import { setupAssets } from './plugins'; @@ -10,6 +11,11 @@ async function setupApp() { // import assets: js、css setupAssets(); + // app loading + const appLoading = createApp(AppLoading); + + appLoading.mount('#appLoading'); + const app = createApp(App); // store plugin: pinia diff --git a/src/router/guard/dynamic.ts b/src/router/guard/dynamic.ts index e57ad2fe..7c238ff6 100644 --- a/src/router/guard/dynamic.ts +++ b/src/router/guard/dynamic.ts @@ -1,7 +1,7 @@ import type { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'; import { routeName } from '@/router'; import { useRouteStore } from '@/store'; -import { getToken } from '@/utils'; +import { localStg } from '@/utils'; /** * 动态路由 @@ -12,7 +12,7 @@ export async function createDynamicRouteGuard( next: NavigationGuardNext ) { const route = useRouteStore(); - const isLogin = Boolean(getToken()); + const isLogin = Boolean(localStg.get('token')); // 初始化权限路由 if (!route.isInitAuthRoute) { diff --git a/src/router/guard/permission.ts b/src/router/guard/permission.ts index e50f3fd9..bc50d597 100644 --- a/src/router/guard/permission.ts +++ b/src/router/guard/permission.ts @@ -1,7 +1,7 @@ import type { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'; import { routeName } from '@/router'; import { useAuthStore } from '@/store'; -import { exeStrategyActions, getToken } from '@/utils'; +import { exeStrategyActions, localStg } from '@/utils'; import { createDynamicRouteGuard } from './dynamic'; /** 处理路由页面的权限 */ @@ -22,7 +22,7 @@ export async function createPermissionGuard( } const auth = useAuthStore(); - const isLogin = Boolean(getToken()); + const isLogin = Boolean(localStg.get('token')); const permissions = to.meta.permissions || []; const needLogin = Boolean(to.meta?.requiresAuth) || Boolean(permissions.length); const hasPermission = !permissions.length || permissions.includes(auth.userInfo.userRole); diff --git a/src/service/request/helpers.ts b/src/service/request/helpers.ts index 356ce06c..49d4fe3c 100644 --- a/src/service/request/helpers.ts +++ b/src/service/request/helpers.ts @@ -1,6 +1,6 @@ import type { AxiosRequestConfig } from 'axios'; import { useAuthStore } from '@/store'; -import { getRefreshToken, setRefreshToken, setToken } from '@/utils'; +import { localStg } from '@/utils'; import { fetchUpdateToken } from '../api'; /** @@ -9,11 +9,12 @@ import { fetchUpdateToken } from '../api'; */ export async function handleRefreshToken(axiosConfig: AxiosRequestConfig) { const { resetAuthStore } = useAuthStore(); - const refreshToken = getRefreshToken(); + const refreshToken = localStg.get('refreshToken') || ''; const { data } = await fetchUpdateToken(refreshToken); if (data) { - setToken(data.token); - setRefreshToken(data.refreshToken); + localStg.set('token', data.token); + localStg.set('refreshToken', data.refreshToken); + const config = { ...axiosConfig }; if (config.headers) { config.headers.Authorization = data.token; diff --git a/src/service/request/instance.ts b/src/service/request/instance.ts index e0b4a3ba..c4180c9f 100644 --- a/src/service/request/instance.ts +++ b/src/service/request/instance.ts @@ -2,7 +2,7 @@ import axios from 'axios'; import type { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios'; import { REFRESH_TOKEN_CODE } from '@/config'; import { - getToken, + localStg, handleAxiosError, handleBackendError, handleResponseError, @@ -49,7 +49,7 @@ export default class CustomAxiosInstance { const contentType = handleConfig.headers['Content-Type'] as string; handleConfig.data = await transformRequestData(handleConfig.data, contentType); // 设置token - handleConfig.headers.Authorization = getToken(); + handleConfig.headers.Authorization = localStg.get('token') || ''; } return handleConfig; }, diff --git a/src/store/modules/auth/helpers.ts b/src/store/modules/auth/helpers.ts new file mode 100644 index 00000000..513b5570 --- /dev/null +++ b/src/store/modules/auth/helpers.ts @@ -0,0 +1,25 @@ +import { localStg } from '@/utils'; + +/** 获取token */ +export function getToken() { + return localStg.get('token') || ''; +} + +/** 获取用户信息 */ +export function getUserInfo() { + const emptyInfo: Auth.UserInfo = { + userId: '', + userName: '', + userRole: 'user' + }; + const userInfo: Auth.UserInfo = localStg.get('userInfo') || emptyInfo; + + return userInfo; +} + +/** 去除用户相关缓存 */ +export function clearAuthStorage() { + localStg.remove('token'); + localStg.remove('refreshToken'); + localStg.remove('userInfo'); +} diff --git a/src/store/modules/auth/index.ts b/src/store/modules/auth/index.ts index 6b6f6e17..73464f56 100644 --- a/src/store/modules/auth/index.ts +++ b/src/store/modules/auth/index.ts @@ -3,9 +3,10 @@ import { defineStore } from 'pinia'; import { router } from '@/router'; import { fetchLogin, fetchUserInfo } from '@/service'; import { useRouterPush } from '@/composables'; -import { clearAuthStorage, getToken, getUserInfo, setRefreshToken, setToken, setUserInfo } from '@/utils'; +import { localStg } from '@/utils'; import { useTabStore } from '../tab'; import { useRouteStore } from '../route'; +import { getToken, getUserInfo, clearAuthStorage } from './helpers'; interface AuthState { /** 用户信息 */ @@ -81,14 +82,14 @@ export const useAuthStore = defineStore('auth-store', { // 先把token存储到缓存中(后面接口的请求头需要token) const { token, refreshToken } = backendToken; - setToken(token); - setRefreshToken(refreshToken); + localStg.set('token', token); + localStg.set('refreshToken', refreshToken); // 获取用户信息 const { data } = await fetchUserInfo(); if (data) { // 成功后把用户信息存储到缓存中 - setUserInfo(data); + localStg.set('userInfo', data); // 更新状态 this.userInfo = data; diff --git a/src/store/modules/route/index.ts b/src/store/modules/route/index.ts index ca3bc9f6..8151164d 100644 --- a/src/store/modules/route/index.ts +++ b/src/store/modules/route/index.ts @@ -2,10 +2,10 @@ import { defineStore } from 'pinia'; import { ROOT_ROUTE, constantRoutes, router, routes as staticRoutes } from '@/router'; import { fetchUserRoutes } from '@/service'; import { + localStg, filterAuthRoutesByUserPermission, getCacheRoutes, getConstantRouteNames, - getUserInfo, transformAuthRouteToVueRoutes, transformAuthRouteToVueRoute, transformAuthRouteToMenu, @@ -106,7 +106,12 @@ export const useRouteStore = defineStore('route-store', { }, /** 初始化动态路由 */ async initDynamicRoute() { - const { userId } = getUserInfo(); + const { userId } = localStg.get('userInfo') || {}; + + if (!userId) { + throw new Error('userId 不能为空!'); + } + const { data } = await fetchUserRoutes(userId); if (data) { this.routeHomeName = data.home; @@ -123,9 +128,6 @@ export const useRouteStore = defineStore('route-store', { /** 初始化权限路由 */ async initAuthRoute() { const { initHomeTab } = useTabStore(); - const { userId } = getUserInfo(); - - if (!userId) return; const isDynamicRoute = this.authRouteMode === 'dynamic'; if (isDynamicRoute) { diff --git a/src/store/modules/tab/helpers.ts b/src/store/modules/tab/helpers.ts index 019f3580..d5833625 100644 --- a/src/store/modules/tab/helpers.ts +++ b/src/store/modules/tab/helpers.ts @@ -1,6 +1,5 @@ import type { RouteLocationNormalizedLoaded, RouteRecordNormalized } from 'vue-router'; -import { EnumStorageKey } from '@/enum'; -import { getLocal, setLocal } from '@/utils'; +import { localStg } from '@/utils'; /** * 根据vue路由获取tab路由 @@ -58,15 +57,10 @@ function hasFullPath( return Boolean((route as RouteLocationNormalizedLoaded).fullPath); } -/** 缓存多页签数据 */ -export function setTabRoutes(data: App.GlobalTabRoute[]) { - setLocal(EnumStorageKey['multi-tab-routes'], data); -} - /** 获取缓存的多页签数据 */ export function getTabRoutes() { const routes: App.GlobalTabRoute[] = []; - const data = getLocal(EnumStorageKey['multi-tab-routes']); + const data = localStg.get('multiTabRoutes'); if (data) { const defaultTabRoutes = data.map(item => ({ ...item, @@ -82,5 +76,5 @@ export function getTabRoutes() { /** 清空多页签数据 */ export function clearTabRoutes() { - setTabRoutes([]); + localStg.set('multiTabRoutes', []); } diff --git a/src/store/modules/tab/index.ts b/src/store/modules/tab/index.ts index 5f153b4d..ed3df8f5 100644 --- a/src/store/modules/tab/index.ts +++ b/src/store/modules/tab/index.ts @@ -1,6 +1,7 @@ import type { RouteLocationNormalizedLoaded, Router } from 'vue-router'; import { defineStore } from 'pinia'; import { useRouterPush } from '@/composables'; +import { localStg } from '@/utils'; import { useThemeStore } from '../theme'; import { clearTabRoutes, @@ -8,8 +9,7 @@ import { getIndexInTabRoutesByRouteName, getTabRouteByVueRoute, getTabRoutes, - isInTabRoutes, - setTabRoutes + isInTabRoutes } from './helpers'; interface TabState { @@ -52,7 +52,7 @@ export const useTabStore = defineStore('tab-store', { }, /** 缓存页签路由数据 */ cacheTabRoutes() { - setTabRoutes(this.tabs); + localStg.set('multiTabRoutes', this.tabs); }, /** * 设置当前路由对应的页签为激活状态 diff --git a/src/store/modules/theme/helpers.ts b/src/store/modules/theme/helpers.ts index 1d07b02d..4007440c 100644 --- a/src/store/modules/theme/helpers.ts +++ b/src/store/modules/theme/helpers.ts @@ -1,19 +1,18 @@ import type { GlobalThemeOverrides } from 'naive-ui'; import { cloneDeep } from 'lodash-es'; import { themeSetting } from '@/settings'; -import { EnumStorageKey } from '@/enum'; -import { addColorAlpha, getColorPalette, getLocal, getThemeColor, removeLocal, setLocal } from '@/utils'; +import { localStg, addColorAlpha, getColorPalette } from '@/utils'; /** 初始化主题配置 */ export function initThemeSettings() { const isProd = import.meta.env.PROD; // 生产环境才缓存主题配置,本地开发实时调整配置更改配置的json - const storageSettings = getThemeSettings(); + const storageSettings = localStg.get('themeSettings'); if (isProd && storageSettings) { return storageSettings; } - const themeColor = getThemeColor() || themeSetting.themeColor; + const themeColor = localStg.get('themeColor') || themeSetting.themeColor; const info = themeSetting.isCustomizeInfoColor ? themeSetting.otherColor.info : getColorPalette(themeColor, 7); const otherColor = { ...themeSetting.otherColor, info }; const setting = cloneDeep({ ...themeSetting, themeColor, otherColor }); @@ -78,18 +77,3 @@ export function getNaiveThemeOverrides(colors: Record): Globa } }; } - -/** 获取缓存中的主题配置 */ -function getThemeSettings() { - return getLocal(EnumStorageKey['theme-settings']); -} - -/** 获取缓存中的主题配置 */ -export function setThemeSettings(settings: Theme.Setting) { - return setLocal(EnumStorageKey['theme-settings'], settings); -} - -/** 清除缓存配置 */ -export function clearThemeSettings() { - removeLocal(EnumStorageKey['theme-settings']); -} diff --git a/src/store/modules/theme/index.ts b/src/store/modules/theme/index.ts index 7c13f8d5..c693790f 100644 --- a/src/store/modules/theme/index.ts +++ b/src/store/modules/theme/index.ts @@ -1,6 +1,7 @@ import { defineStore } from 'pinia'; import { darkTheme } from 'naive-ui'; -import { clearThemeSettings, getNaiveThemeOverrides, initThemeSettings, setThemeSettings } from './helpers'; +import { localStg } from '@/utils'; +import { getNaiveThemeOverrides, initThemeSettings } from './helpers'; type ThemeState = Theme.Setting; @@ -24,14 +25,14 @@ export const useThemeStore = defineStore('theme-store', { actions: { /** 重置theme状态 */ resetThemeStore() { - clearThemeSettings(); + localStg.remove('themeSettings'); this.$reset(); }, /** 缓存主题配置 */ cacheThemeSettings() { const isProd = import.meta.env.PROD; if (isProd) { - setThemeSettings(this.$state); + localStg.set('themeSettings', this.$state); } }, /** 设置暗黑模式 */ diff --git a/src/store/subscribe/theme.ts b/src/store/subscribe/theme.ts index 92b22c8d..89cb821c 100644 --- a/src/store/subscribe/theme.ts +++ b/src/store/subscribe/theme.ts @@ -3,7 +3,7 @@ import { useOsTheme } from 'naive-ui'; import type { GlobalThemeOverrides } from 'naive-ui'; import { useElementSize } from '@vueuse/core'; import { kebabCase } from 'lodash-es'; -import { setThemeColor } from '@/utils'; +import { localStg } from '@/utils'; import { useThemeStore } from '../modules'; /** 订阅theme store */ @@ -17,7 +17,7 @@ export default function subscribeThemeStore() { const stopThemeColor = watch( () => theme.themeColor, newValue => { - setThemeColor(newValue); + localStg.set('themeColor', newValue); }, { immediate: true } ); diff --git a/src/typings/router-page.d.ts b/src/typings/router-page.d.ts new file mode 100644 index 00000000..3f4dd3a1 --- /dev/null +++ b/src/typings/router-page.d.ts @@ -0,0 +1,67 @@ +declare namespace RouterPage { + /** 根路由 */ + type RootRouteKey = 'root'; + + /** 未找到路由(捕获无效路径的路由) */ + type NotFoundRouteKey = 'not-found'; + + /** 页面路由 */ + type RouteKey = + | '403' + | '404' + | '500' + | 'about' + | 'auth-demo' + | 'auth-demo_permission' + | 'auth-demo_super' + | 'component' + | 'component_button' + | 'component_card' + | 'component_table' + | 'constant-page' + | 'dashboard' + | 'dashboard_analysis' + | 'dashboard_workbench' + | 'document' + | 'document_naive' + | 'document_project' + | 'document_project-link' + | 'document_vite' + | 'document_vue' + | 'exception' + | 'exception_403' + | 'exception_404' + | 'exception_500' + | 'function' + | 'function_tab' + | 'function_tab-detail' + | 'function_tab-multi-detail' + | 'login' + | 'management' + | 'management_auth' + | 'management_role' + | 'management_route' + | 'management_user' + | 'multi-menu' + | 'multi-menu_first' + | 'multi-menu_first_second' + | 'multi-menu_first_second-new' + | 'multi-menu_first_second-new_third' + | 'not-found' + | 'plugin' + | 'plugin_charts' + | 'plugin_charts_antv' + | 'plugin_charts_echarts' + | 'plugin_copy' + | 'plugin_editor' + | 'plugin_editor_markdown' + | 'plugin_editor_quill' + | 'plugin_icon' + | 'plugin_map' + | 'plugin_print' + | 'plugin_swiper' + | 'plugin_video'; + + /** 最后一级路由(该级路有对应的vue文件) */ + type LastDegreeRouteKey = Extract +} diff --git a/src/typings/storage.d.ts b/src/typings/storage.d.ts new file mode 100644 index 00000000..892a7167 --- /dev/null +++ b/src/typings/storage.d.ts @@ -0,0 +1,22 @@ +declare namespace StorageInterface { + /** localStorage的存储数据的类型 */ + interface Session { + demoKey: string; + } + + /** localStorage的存储数据的类型 */ + interface Local { + /** 主题颜色 */ + themeColor: string; + /** 用户token */ + token: string; + /** 用户刷新token */ + refreshToken: string; + /** 用户信息 */ + userInfo: Auth.UserInfo; + /** 主题配置 */ + themeSettings: Theme.Setting; + /** 多页签路由信息 */ + multiTabRoutes: App.GlobalTabRoute[]; + } +} diff --git a/src/utils/auth/index.ts b/src/utils/auth/index.ts deleted file mode 100644 index e5abc856..00000000 --- a/src/utils/auth/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './user'; diff --git a/src/utils/auth/user.ts b/src/utils/auth/user.ts deleted file mode 100644 index 2be035b6..00000000 --- a/src/utils/auth/user.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { EnumStorageKey } from '@/enum'; -import { getLocal, removeLocal, setLocal } from '../storage'; - -/** 设置token */ -export function setToken(token: string) { - setLocal(EnumStorageKey.token, token); -} - -/** 获取token */ -export function getToken() { - return getLocal(EnumStorageKey.token) || ''; -} - -/** 去除token */ -export function removeToken() { - removeLocal(EnumStorageKey.token); -} - -/** 获取refresh token */ -export function getRefreshToken() { - return getLocal(EnumStorageKey['refresh-token']) || ''; -} - -/** 设置refresh token */ -export function setRefreshToken(token: string) { - setLocal(EnumStorageKey['refresh-token'], token); -} - -/** 去除refresh token */ -export function removeRefreshToken() { - removeLocal(EnumStorageKey['refresh-token']); -} - -/** 获取用户信息 */ -export function getUserInfo() { - const emptyInfo: Auth.UserInfo = { - userId: '', - userName: '', - userRole: 'user' - }; - const userInfo: Auth.UserInfo = getLocal(EnumStorageKey['user-info']) || emptyInfo; - return userInfo; -} - -/** 设置用户信息 */ -export function setUserInfo(userInfo: Auth.UserInfo) { - setLocal(EnumStorageKey['user-info'], userInfo); -} - -/** 去除用户信息 */ -export function removeUserInfo() { - removeLocal(EnumStorageKey['user-info']); -} - -/** 去除用户相关缓存 */ -export function clearAuthStorage() { - removeToken(); - removeRefreshToken(); - removeUserInfo(); -} diff --git a/src/utils/common/index.ts b/src/utils/common/index.ts index 6bf9554d..cc92dea5 100644 --- a/src/utils/common/index.ts +++ b/src/utils/common/index.ts @@ -1,6 +1,4 @@ export * from './typeof'; export * from './color'; export * from './number'; -export * from './object'; export * from './pattern'; -export * from './theme'; diff --git a/src/utils/common/object.ts b/src/utils/common/object.ts deleted file mode 100644 index 450b6f6f..00000000 --- a/src/utils/common/object.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** 设置对象数据 */ -export function objectAssign>(target: T, source: Partial) { - Object.assign(target, source); -} diff --git a/src/utils/common/theme.ts b/src/utils/common/theme.ts deleted file mode 100644 index fe1bd20c..00000000 --- a/src/utils/common/theme.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { EnumStorageKey } from '@/enum'; - -/** - * 缓存主题颜色 - * @param color - */ -export function setThemeColor(color: string) { - window.localStorage.setItem(EnumStorageKey['theme-color'], color); -} - -/** - * 获取缓存的主题颜色 - */ -export function getThemeColor() { - return window.localStorage.getItem(EnumStorageKey['theme-color']); -} diff --git a/src/utils/index.ts b/src/utils/index.ts index cc3d8ff7..b75f46d6 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +1,5 @@ export * from './common'; export * from './storage'; export * from './service'; -export * from './auth'; export * from './router'; export * from './form'; diff --git a/src/utils/storage/local.ts b/src/utils/storage/local.ts index 0c2c82d4..114f39f7 100644 --- a/src/utils/storage/local.ts +++ b/src/utils/storage/local.ts @@ -1,45 +1,57 @@ import { decrypto, encrypto } from '../crypto'; - -interface StorageData { - value: unknown; +interface StorageData { + value: T; expire: number | null; } -/** 默认缓存期限为7天 */ -const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7; +function createLocalStorage() { + /** 默认缓存期限为7天 */ + const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7; -export function setLocal(key: string, value: unknown, expire: number | null = DEFAULT_CACHE_TIME) { - const storageData: StorageData = { value, expire: expire !== null ? new Date().getTime() + expire * 1000 : null }; - const json = encrypto(storageData); - window.localStorage.setItem(key, json); -} + function set(key: K, value: T[K], expire: number | null = DEFAULT_CACHE_TIME) { + const storageData: StorageData = { + value, + expire: expire !== null ? new Date().getTime() + expire * 1000 : null + }; + const json = encrypto(storageData); + window.localStorage.setItem(key as string, json); + } -export function getLocal(key: string) { - const json = window.localStorage.getItem(key); - if (json) { - let storageData: StorageData | null = null; - try { - storageData = decrypto(json); - } catch { - // 防止解析失败 - } - if (storageData) { - const { value, expire } = storageData; - // 在有效期内直接返回 - if (expire === null || expire >= Date.now()) { - return value as T; + function get(key: K) { + const json = window.localStorage.getItem(key as string); + if (json) { + let storageData: StorageData | null = null; + try { + storageData = decrypto(json); + } catch { + // 防止解析失败 } + if (storageData) { + const { value, expire } = storageData; + // 在有效期内直接返回 + if (expire === null || expire >= Date.now()) { + return value as T[K]; + } + } + remove(key); + return null; } - removeLocal(key); return null; } - return null; + + function remove(key: keyof T) { + window.localStorage.removeItem(key as string); + } + function clear() { + window.localStorage.clear(); + } + + return { + set, + get, + remove, + clear + }; } -export function removeLocal(key: string) { - window.localStorage.removeItem(key); -} - -export function clearLocal() { - window.localStorage.clear(); -} +export const localStg = createLocalStorage(); diff --git a/src/utils/storage/session.ts b/src/utils/storage/session.ts index 64c29b9f..b6efe9b9 100644 --- a/src/utils/storage/session.ts +++ b/src/utils/storage/session.ts @@ -25,3 +25,37 @@ export function removeSession(key: string) { export function clearSession() { window.sessionStorage.clear(); } + +function createSessionStorage() { + function set(key: K, value: T[K]) { + const json = encrypto(value); + sessionStorage.setItem(key as string, json); + } + function get(key: K) { + const json = sessionStorage.getItem(key as string); + let data: T[K] | null = null; + if (json) { + try { + data = decrypto(json); + } catch { + // 防止解析失败 + } + } + return data; + } + function remove(key: keyof T) { + window.sessionStorage.removeItem(key as string); + } + function clear() { + window.sessionStorage.clear(); + } + + return { + set, + get, + remove, + clear + }; +} + +export const sessionStg = createSessionStorage();