feat(hooks): 重构下载方法,支持流式下载

This commit is contained in:
xlsea
2025-06-26 14:14:02 +08:00
parent fec0563ef7
commit 650673e2db
3 changed files with 192 additions and 132 deletions

View File

@ -57,6 +57,7 @@
"@sa/materials": "workspace:*", "@sa/materials": "workspace:*",
"@sa/tinymce": "workspace:*", "@sa/tinymce": "workspace:*",
"@sa/utils": "workspace:*", "@sa/utils": "workspace:*",
"@types/streamsaver": "^2.0.5",
"@vueuse/core": "13.4.0", "@vueuse/core": "13.4.0",
"clipboard": "2.0.11", "clipboard": "2.0.11",
"dayjs": "1.11.13", "dayjs": "1.11.13",
@ -69,6 +70,7 @@
"naive-ui": "2.42.0", "naive-ui": "2.42.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"pinia": "3.0.3", "pinia": "3.0.3",
"streamsaver": "^2.0.6",
"tailwind-merge": "3.3.1", "tailwind-merge": "3.3.1",
"vue": "3.5.17", "vue": "3.5.17",
"vue-advanced-cropper": "^2.8.9", "vue-advanced-cropper": "^2.8.9",
@ -85,7 +87,7 @@
"@types/node": "24.0.4", "@types/node": "24.0.4",
"@types/nprogress": "0.2.3", "@types/nprogress": "0.2.3",
"@unocss/eslint-config": "66.2.3", "@unocss/eslint-config": "66.2.3",
"@unocss/preset-icons": "66.3.0", "@unocss/preset-icons": "66.2.3",
"@unocss/preset-uno": "66.2.3", "@unocss/preset-uno": "66.2.3",
"@unocss/transformer-directives": "66.2.3", "@unocss/transformer-directives": "66.2.3",
"@unocss/transformer-variant-group": "66.2.3", "@unocss/transformer-variant-group": "66.2.3",

124
pnpm-lock.yaml generated
View File

@ -32,6 +32,9 @@ importers:
'@sa/utils': '@sa/utils':
specifier: workspace:* specifier: workspace:*
version: link:packages/utils version: link:packages/utils
'@types/streamsaver':
specifier: ^2.0.5
version: 2.0.5
'@vueuse/core': '@vueuse/core':
specifier: 13.4.0 specifier: 13.4.0
version: 13.4.0(vue@3.5.17(typescript@5.8.3)) version: 13.4.0(vue@3.5.17(typescript@5.8.3))
@ -57,7 +60,7 @@ importers:
specifier: 2.2.3 specifier: 2.2.3
version: 2.2.3 version: 2.2.3
monaco-editor: monaco-editor:
specifier: ^0.52.0 specifier: ^0.52.2
version: 0.52.2 version: 0.52.2
naive-ui: naive-ui:
specifier: 2.42.0 specifier: 2.42.0
@ -68,6 +71,9 @@ importers:
pinia: pinia:
specifier: 3.0.3 specifier: 3.0.3
version: 3.0.3(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3)) version: 3.0.3(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3))
streamsaver:
specifier: ^2.0.6
version: 2.0.6
tailwind-merge: tailwind-merge:
specifier: 3.3.1 specifier: 3.3.1
version: 3.3.1 version: 3.3.1
@ -103,8 +109,8 @@ importers:
specifier: 1.6.1 specifier: 1.6.1
version: 1.6.1(@unocss/eslint-config@66.2.3(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-plugin-vue@10.2.0(eslint@9.29.0(jiti@2.4.2))(vue-eslint-parser@10.1.4(eslint@9.29.0(jiti@2.4.2))))(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vue-eslint-parser@10.1.4(eslint@9.29.0(jiti@2.4.2))) version: 1.6.1(@unocss/eslint-config@66.2.3(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-plugin-vue@10.2.0(eslint@9.29.0(jiti@2.4.2))(vue-eslint-parser@10.1.4(eslint@9.29.0(jiti@2.4.2))))(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vue-eslint-parser@10.1.4(eslint@9.29.0(jiti@2.4.2)))
'@types/node': '@types/node':
specifier: 24.0.3 specifier: 24.0.4
version: 24.0.3 version: 24.0.4
'@types/nprogress': '@types/nprogress':
specifier: 0.2.3 specifier: 0.2.3
version: 0.2.3 version: 0.2.3
@ -125,13 +131,13 @@ importers:
version: 66.2.3 version: 66.2.3
'@unocss/vite': '@unocss/vite':
specifier: 66.2.3 specifier: 66.2.3
version: 66.2.3(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3)) version: 66.2.3(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))
'@vitejs/plugin-vue': '@vitejs/plugin-vue':
specifier: 6.0.0 specifier: 6.0.0
version: 6.0.0(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3)) version: 6.0.0(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))
'@vitejs/plugin-vue-jsx': '@vitejs/plugin-vue-jsx':
specifier: 5.0.0 specifier: 5.0.0
version: 5.0.0(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3)) version: 5.0.0(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))
consola: consola:
specifier: 3.4.2 specifier: 3.4.2
version: 3.4.2 version: 3.4.2
@ -164,22 +170,22 @@ importers:
version: 28.7.0(@babel/parser@7.27.5)(vue@3.5.17(typescript@5.8.3)) version: 28.7.0(@babel/parser@7.27.5)(vue@3.5.17(typescript@5.8.3))
vite: vite:
specifier: 7.0.0 specifier: 7.0.0
version: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) version: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
vite-plugin-monaco-editor: vite-plugin-monaco-editor:
specifier: ^1.1.0 specifier: ^1.1.0
version: 1.1.0(monaco-editor@0.52.2) version: 1.1.0(monaco-editor@0.52.2)
vite-plugin-progress: vite-plugin-progress:
specifier: 0.0.7 specifier: 0.0.7
version: 0.0.7(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)) version: 0.0.7(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))
vite-plugin-static-copy: vite-plugin-static-copy:
specifier: ^3.0.0 specifier: ^3.0.2
version: 3.0.2(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)) version: 3.0.2(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))
vite-plugin-svg-icons: vite-plugin-svg-icons:
specifier: 2.0.1 specifier: 2.0.1
version: 2.0.1(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)) version: 2.0.1(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))
vite-plugin-vue-devtools: vite-plugin-vue-devtools:
specifier: 7.7.7 specifier: 7.7.7
version: 7.7.7(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3)) version: 7.7.7(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))
vue-eslint-parser: vue-eslint-parser:
specifier: 10.1.4 specifier: 10.1.4
version: 10.1.4(eslint@9.29.0(jiti@2.4.2)) version: 10.1.4(eslint@9.29.0(jiti@2.4.2))
@ -291,12 +297,12 @@ importers:
packages/tinymce: packages/tinymce:
dependencies: dependencies:
tinymce: tinymce:
specifier: 7.8.0 specifier: 7.9.1
version: 7.8.0 version: 7.9.1
devDependencies: devDependencies:
'@tinymce/tinymce-vue': '@tinymce/tinymce-vue':
specifier: 6.1.0 specifier: 6.2.0
version: 6.1.0(tinymce@7.8.0)(vue@3.5.17(typescript@5.8.3)) version: 6.2.0(tinymce@7.9.1)(vue@3.5.17(typescript@5.8.3))
packages/uno-preset: {} packages/uno-preset: {}
@ -1112,8 +1118,8 @@ packages:
vue-eslint-parser: vue-eslint-parser:
optional: true optional: true
'@tinymce/tinymce-vue@6.1.0': '@tinymce/tinymce-vue@6.2.0':
resolution: {integrity: sha512-7JdaKMOaohuFWpjKwRmaZJbT/eNVUUYHG93R7+lUf7SUN+hSqd2spbuqZcki+tG9kaSAGd2ZmvJIsmzWDNAzpw==} resolution: {integrity: sha512-HiXKB+M3mJnWO6/8kY0HsP255+8zLZw5JMqHKVUvsXvzYyHW+splXXwYDYOkCYqf39R5nBqQaK2l2WL9rz3y5w==}
peerDependencies: peerDependencies:
tinymce: ^7.0.0 || ^6.0.0 || ^5.5.1 tinymce: ^7.0.0 || ^6.0.0 || ^5.5.1
vue: ^3.0.0 vue: ^3.0.0
@ -1158,8 +1164,8 @@ packages:
'@types/node@10.17.60': '@types/node@10.17.60':
resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==}
'@types/node@24.0.3': '@types/node@24.0.4':
resolution: {integrity: sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==} resolution: {integrity: sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==}
'@types/nprogress@0.2.3': '@types/nprogress@0.2.3':
resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==}
@ -1170,6 +1176,9 @@ packages:
'@types/sortablejs@1.15.8': '@types/sortablejs@1.15.8':
resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==} resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==}
'@types/streamsaver@2.0.5':
resolution: {integrity: sha512-93o0zjV8swEhR2YI57h/2ytbJF8bJh7sI9GNB02TLJHdM4fWDxZuChwfWhyD8vt2ub4kw4rsfZ0C0yAUX+3gcg==}
'@types/svgo@2.6.4': '@types/svgo@2.6.4':
resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==}
@ -3745,6 +3754,9 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
streamsaver@2.0.6:
resolution: {integrity: sha512-LK4e7TfCV8HzuM0PKXuVUfKyCB1FtT9L0EGxsFk5Up8njj0bXK8pJM9+Wq2Nya7/jslmCQwRK39LFm55h7NBTw==}
strict-uri-encode@1.1.0: strict-uri-encode@1.1.0:
resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -3851,8 +3863,8 @@ packages:
resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
tinymce@7.8.0: tinymce@7.9.1:
resolution: {integrity: sha512-MUER5MWV9mkOB4expgbWknh/C5ZJvOXQlMVSx4tJxTuYtcUCDB6bMZ34fWNOIc8LvrnXmGHGj0eGQuxjQyRgrA==} resolution: {integrity: sha512-zaOHwmiP1EqTeLRXAvVriDb00JYnfEjWGPdKEuac7MiZJ5aiDMZ4Unc98Gmajn+PBljOmO1GKV6G0KwWn3+k8A==}
to-object-path@0.3.0: to-object-path@0.3.0:
resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==}
@ -4994,11 +5006,11 @@ snapshots:
- '@types/eslint' - '@types/eslint'
- supports-color - supports-color
'@tinymce/tinymce-vue@6.1.0(tinymce@7.8.0)(vue@3.5.17(typescript@5.8.3))': '@tinymce/tinymce-vue@6.2.0(tinymce@7.9.1)(vue@3.5.17(typescript@5.8.3))':
dependencies: dependencies:
vue: 3.5.17(typescript@5.8.3) vue: 3.5.17(typescript@5.8.3)
optionalDependencies: optionalDependencies:
tinymce: 7.8.0 tinymce: 7.9.1
'@trysound/sax@0.2.0': {} '@trysound/sax@0.2.0': {}
@ -5033,7 +5045,7 @@ snapshots:
'@types/node@10.17.60': {} '@types/node@10.17.60': {}
'@types/node@24.0.3': '@types/node@24.0.4':
dependencies: dependencies:
undici-types: 7.8.0 undici-types: 7.8.0
@ -5043,9 +5055,11 @@ snapshots:
'@types/sortablejs@1.15.8': {} '@types/sortablejs@1.15.8': {}
'@types/streamsaver@2.0.5': {}
'@types/svgo@2.6.4': '@types/svgo@2.6.4':
dependencies: dependencies:
'@types/node': 24.0.3 '@types/node': 24.0.4
'@types/unist@3.0.3': {} '@types/unist@3.0.3': {}
@ -5263,7 +5277,7 @@ snapshots:
dependencies: dependencies:
'@unocss/core': 66.2.3 '@unocss/core': 66.2.3
'@unocss/vite@66.2.3(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))': '@unocss/vite@66.2.3(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))':
dependencies: dependencies:
'@ampproject/remapping': 2.3.0 '@ampproject/remapping': 2.3.0
'@unocss/config': 66.2.3 '@unocss/config': 66.2.3
@ -5274,7 +5288,7 @@ snapshots:
pathe: 2.0.3 pathe: 2.0.3
tinyglobby: 0.2.14 tinyglobby: 0.2.14
unplugin-utils: 0.2.4 unplugin-utils: 0.2.4
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies: transitivePeerDependencies:
- vue - vue
@ -5337,21 +5351,21 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.9.2': '@unrs/resolver-binding-win32-x64-msvc@1.9.2':
optional: true optional: true
'@vitejs/plugin-vue-jsx@5.0.0(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))': '@vitejs/plugin-vue-jsx@5.0.0(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))':
dependencies: dependencies:
'@babel/core': 7.27.4 '@babel/core': 7.27.4
'@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.4) '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.4)
'@rolldown/pluginutils': 1.0.0-beta.19 '@rolldown/pluginutils': 1.0.0-beta.19
'@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.4) '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.4)
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
vue: 3.5.17(typescript@5.8.3) vue: 3.5.17(typescript@5.8.3)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@vitejs/plugin-vue@6.0.0(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))': '@vitejs/plugin-vue@6.0.0(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))':
dependencies: dependencies:
'@rolldown/pluginutils': 1.0.0-beta.19 '@rolldown/pluginutils': 1.0.0-beta.19
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
vue: 3.5.17(typescript@5.8.3) vue: 3.5.17(typescript@5.8.3)
'@volar/language-core@2.4.15': '@volar/language-core@2.4.15':
@ -5436,14 +5450,14 @@ snapshots:
dependencies: dependencies:
'@vue/devtools-kit': 7.7.7 '@vue/devtools-kit': 7.7.7
'@vue/devtools-core@7.7.7(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))': '@vue/devtools-core@7.7.7(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))':
dependencies: dependencies:
'@vue/devtools-kit': 7.7.7 '@vue/devtools-kit': 7.7.7
'@vue/devtools-shared': 7.7.7 '@vue/devtools-shared': 7.7.7
mitt: 3.0.1 mitt: 3.0.1
nanoid: 5.1.5 nanoid: 5.1.5
pathe: 2.0.3 pathe: 2.0.3
vite-hot-client: 2.0.4(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)) vite-hot-client: 2.0.4(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))
vue: 3.5.17(typescript@5.8.3) vue: 3.5.17(typescript@5.8.3)
transitivePeerDependencies: transitivePeerDependencies:
- vite - vite
@ -7996,6 +8010,8 @@ snapshots:
es-errors: 1.3.0 es-errors: 1.3.0
internal-slot: 1.1.0 internal-slot: 1.1.0
streamsaver@2.0.6: {}
strict-uri-encode@1.1.0: {} strict-uri-encode@1.1.0: {}
string-width@4.2.3: string-width@4.2.3:
@ -8122,7 +8138,7 @@ snapshots:
fdir: 6.4.6(picomatch@4.0.2) fdir: 6.4.6(picomatch@4.0.2)
picomatch: 4.0.2 picomatch: 4.0.2
tinymce@7.8.0: {} tinymce@7.9.1: {}
to-object-path@0.3.0: to-object-path@0.3.0:
dependencies: dependencies:
@ -8366,11 +8382,11 @@ snapshots:
evtd: 0.2.4 evtd: 0.2.4
vue: 3.5.17(typescript@5.8.3) vue: 3.5.17(typescript@5.8.3)
vite-hot-client@2.0.4(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)): vite-hot-client@2.0.4(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)):
dependencies: dependencies:
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
vite-plugin-inspect@0.8.9(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)): vite-plugin-inspect@0.8.9(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)):
dependencies: dependencies:
'@antfu/utils': 0.7.10 '@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.2.0(rollup@4.44.0) '@rollup/pluginutils': 5.2.0(rollup@4.44.0)
@ -8381,7 +8397,7 @@ snapshots:
perfect-debounce: 1.0.0 perfect-debounce: 1.0.0
picocolors: 1.1.1 picocolors: 1.1.1
sirv: 3.0.1 sirv: 3.0.1
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
- supports-color - supports-color
@ -8390,23 +8406,23 @@ snapshots:
dependencies: dependencies:
monaco-editor: 0.52.2 monaco-editor: 0.52.2
vite-plugin-progress@0.0.7(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)): vite-plugin-progress@0.0.7(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)):
dependencies: dependencies:
picocolors: 1.1.1 picocolors: 1.1.1
progress: 2.0.3 progress: 2.0.3
rd: 2.0.1 rd: 2.0.1
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
vite-plugin-static-copy@3.0.2(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)): vite-plugin-static-copy@3.0.2(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)):
dependencies: dependencies:
chokidar: 3.6.0 chokidar: 3.6.0
fs-extra: 11.3.0 fs-extra: 11.3.0
p-map: 7.0.3 p-map: 7.0.3
picocolors: 1.1.1 picocolors: 1.1.1
tinyglobby: 0.2.14 tinyglobby: 0.2.14
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
vite-plugin-svg-icons@2.0.1(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)): vite-plugin-svg-icons@2.0.1(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)):
dependencies: dependencies:
'@types/svgo': 2.6.4 '@types/svgo': 2.6.4
cors: 2.8.5 cors: 2.8.5
@ -8416,27 +8432,27 @@ snapshots:
pathe: 0.2.0 pathe: 0.2.0
svg-baker: 1.7.0 svg-baker: 1.7.0
svgo: 2.8.0 svgo: 2.8.0
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vite-plugin-vue-devtools@7.7.7(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3)): vite-plugin-vue-devtools@7.7.7(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3)):
dependencies: dependencies:
'@vue/devtools-core': 7.7.7(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3)) '@vue/devtools-core': 7.7.7(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))
'@vue/devtools-kit': 7.7.7 '@vue/devtools-kit': 7.7.7
'@vue/devtools-shared': 7.7.7 '@vue/devtools-shared': 7.7.7
execa: 9.6.0 execa: 9.6.0
sirv: 3.0.1 sirv: 3.0.1
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
vite-plugin-inspect: 0.8.9(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)) vite-plugin-inspect: 0.8.9(rollup@4.44.0)(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))
vite-plugin-vue-inspector: 5.3.2(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)) vite-plugin-vue-inspector: 5.3.2(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0))
transitivePeerDependencies: transitivePeerDependencies:
- '@nuxt/kit' - '@nuxt/kit'
- rollup - rollup
- supports-color - supports-color
- vue - vue
vite-plugin-vue-inspector@5.3.2(vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)): vite-plugin-vue-inspector@5.3.2(vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)):
dependencies: dependencies:
'@babel/core': 7.27.4 '@babel/core': 7.27.4
'@babel/plugin-proposal-decorators': 7.27.1(@babel/core@7.27.4) '@babel/plugin-proposal-decorators': 7.27.1(@babel/core@7.27.4)
@ -8447,11 +8463,11 @@ snapshots:
'@vue/compiler-dom': 3.5.17 '@vue/compiler-dom': 3.5.17
kolorist: 1.8.0 kolorist: 1.8.0
magic-string: 0.30.17 magic-string: 0.30.17
vite: 7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vite@7.0.0(@types/node@24.0.3)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0): vite@7.0.0(@types/node@24.0.4)(jiti@2.4.2)(sass@1.89.2)(tsx@4.20.3)(yaml@2.8.0):
dependencies: dependencies:
esbuild: 0.25.5 esbuild: 0.25.5
fdir: 6.4.6(picomatch@4.0.2) fdir: 6.4.6(picomatch@4.0.2)
@ -8460,7 +8476,7 @@ snapshots:
rollup: 4.44.0 rollup: 4.44.0
tinyglobby: 0.2.14 tinyglobby: 0.2.14
optionalDependencies: optionalDependencies:
'@types/node': 24.0.3 '@types/node': 24.0.4
fsevents: 2.3.3 fsevents: 2.3.3
jiti: 2.4.2 jiti: 2.4.2
sass: 1.89.2 sass: 1.89.2

View File

@ -1,109 +1,151 @@
import StreamSaver from 'streamsaver';
import { errorCodeRecord } from '@/constants/common'; import { errorCodeRecord } from '@/constants/common';
import { localStg } from '@/utils/storage'; import { localStg } from '@/utils/storage';
import { getServiceBaseURL } from '@/utils/service'; import { getServiceBaseURL } from '@/utils/service';
import { transformToURLSearchParams } from '@/utils/common'; import { transformToURLSearchParams } from '@/utils/common';
interface RequestConfig {
method: 'GET' | 'POST';
url: string;
params?: Record<string, any>;
filename?: string;
contentType?: string;
}
export function useDownload() { export function useDownload() {
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y'; const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy); const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
function downloadByData(data: BlobPart, filename: string, type: string = 'application/octet-stream') { /** 获取通用请求头 */
const blobData = [data]; const getCommonHeaders = (contentType = 'application/octet-stream') => ({
const blob = new Blob(blobData, { type }); Authorization: `Bearer ${localStg.get('token')}`,
Clientid: import.meta.env.VITE_APP_CLIENT_ID!,
'Content-Type': contentType
});
/** 通用下载方法 */
function downloadByData(data: BlobPart, filename: string, type = 'application/octet-stream') {
const blob = new Blob([data], { type });
const blobURL = window.URL.createObjectURL(blob); const blobURL = window.URL.createObjectURL(blob);
const tempLink = document.createElement('a');
tempLink.style.display = 'none'; const tempLink = Object.assign(document.createElement('a'), {
tempLink.href = blobURL; style: { display: 'none' },
tempLink.setAttribute('download', filename); href: blobURL,
download: filename
});
if (typeof tempLink.download === 'undefined') { if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank'); tempLink.setAttribute('target', '_blank');
} }
document.body.appendChild(tempLink); document.body.appendChild(tempLink);
tempLink.click(); tempLink.click();
document.body.removeChild(tempLink); document.body.removeChild(tempLink);
window.URL.revokeObjectURL(blobURL); window.URL.revokeObjectURL(blobURL);
} }
function download(url: string, params: Record<string, any>, fileName: string) { /** 流式下载 */
window.$loading?.startLoading('正在下载数据,请稍候...'); async function downloadByStream(
const token = localStg.get('token'); readableStream: ReadableStream<Uint8Array>,
const clientId = import.meta.env.VITE_APP_CLIENT_ID; filename: string,
const now = Date.now(); contentLength?: number
const searchParams = transformToURLSearchParams(params); ): Promise<void> {
window.$loading?.endLoading();
const fileStream = StreamSaver.createWriteStream(filename, { size: contentLength });
fetch(`${baseURL}${url}?t=${now}`, { if (window.WritableStream && readableStream?.pipeTo) {
method: 'post', await readableStream.pipeTo(fileStream);
body: searchParams, window.$message?.success('下载完成');
headers: { return;
Authorization: `Bearer ${token}`, }
Clientid: clientId!,
'Content-Type': 'application/x-www-form-urlencoded' // 降级处理
} const writer = fileStream.getWriter();
}) const reader = readableStream.getReader();
.then(async response => {
if (response.headers.get('Content-Type')?.includes('application/json')) { const pump = async (): Promise<void> => {
const res = await response.json(); const { done, value } = await reader.read();
const code = res.code as CommonType.ErrorCode; if (done) return writer.close();
throw new Error(errorCodeRecord[code] || res.msg || errorCodeRecord.default); await writer.write(value);
} return pump();
return response.blob(); };
})
.then(data => downloadByData(data, fileName, 'application/zip')) await pump();
.catch(err => window.$message?.error(err.message))
.finally(() => window.$loading?.endLoading());
} }
function oss(ossId: CommonType.IdType) { /** 处理响应 */
window.$loading?.startLoading('正在下载数据,请稍候...'); async function handleResponse(response: Response) {
const token = localStg.get('token'); if (response.headers.get('Content-Type')?.includes('application/json')) {
const clientId = import.meta.env.VITE_APP_CLIENT_ID; const res = await response.json();
const url = `/resource/oss/download/${ossId}`; const code = res.code as CommonType.ErrorCode;
const now = Date.now(); throw new Error(errorCodeRecord[code] || res.msg || errorCodeRecord.default);
let fileName = String(`${ossId}-${now}`); }
fetch(`${baseURL}${url}?t=${now}`, {
method: 'get',
headers: {
Authorization: `Bearer ${token}`,
Clientid: clientId!,
'Content-Type': 'application/octet-stream'
}
})
.then(async response => {
fileName = String(response.headers.get('Download-Filename'));
return response.blob();
})
.then(data => downloadByData(data, fileName))
.catch(err => window.$message?.error(err.message))
.finally(() => window.$loading?.endLoading());
} }
function zip(url: string, fileName: string) { /** 核心下载逻辑 */
async function executeDownload(config: RequestConfig): Promise<void> {
const { method, url, params, filename, contentType } = config;
const timestamp = Date.now();
const fullUrl = `${baseURL}${url}${url.includes('?') ? '&' : '?'}t=${timestamp}`;
window.$loading?.startLoading('正在下载数据,请稍候...'); window.$loading?.startLoading('正在下载数据,请稍候...');
const token = localStg.get('token');
const clientId = import.meta.env.VITE_APP_CLIENT_ID; try {
const now = Date.now(); const requestOptions: RequestInit = {
fetch(`${baseURL}${url}${url.includes('?') ? '&' : '?'}t=${now}`, { method,
method: 'get', headers: getCommonHeaders(contentType)
headers: { };
Authorization: `Bearer ${token}`,
Clientid: clientId!, if (method === 'POST' && params) {
'Content-Type': 'application/octet-stream' requestOptions.body = transformToURLSearchParams(params);
requestOptions.headers = {
...requestOptions.headers,
'Content-Type': 'application/x-www-form-urlencoded'
};
} }
})
.then(async response => { const response = await fetch(fullUrl, requestOptions);
if (response.headers.get('Content-Type')?.includes('application/json')) {
const res = await response.json(); await handleResponse(response);
const code = res.code as CommonType.ErrorCode;
throw new Error(errorCodeRecord[code] || res.msg || errorCodeRecord.default); const finalFilename = filename || response.headers.get('Download-Filename') || `download-${timestamp}`;
}
return response.blob(); if (response.body) {
}) const contentLength = Number(response.headers.get('Content-Length'));
.then(data => downloadByData(data, fileName, 'application/zip')) await downloadByStream(response.body, finalFilename, contentLength);
.catch(err => window.$message?.error(err.message)) return;
.finally(() => window.$loading?.endLoading()); }
const responseContentType = response.headers.get('Content-Type');
const mainType = responseContentType?.split(';')[0]?.trim() || 'application/octet-stream';
downloadByData(await response.blob(), finalFilename, mainType);
} catch (error: any) {
window.$message?.error(error.message);
} finally {
window.$loading?.endLoading();
}
} }
/** 公共下载接口 */
const download = (url: string, params: Record<string, any>, filename: string) =>
executeDownload({ method: 'POST', url, params, filename });
/** OSS文件下载 */
const oss = (ossId: CommonType.IdType) =>
executeDownload({
method: 'GET',
url: `/resource/oss/download/${ossId}`
});
/** ZIP文件下载 */
const zip = (url: string, filename: string) =>
executeDownload({
method: 'GET',
url,
filename,
contentType: 'application/octet-stream'
});
return { return {
oss, oss,
zip, zip,