giime 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/index.css +59 -58
  2. package/es/api/materialApi/cross/getAdFileExist.d.ts +1 -0
  3. package/es/api/materialApi/cross/getAdFileExist.mjs.map +1 -1
  4. package/es/components/src/base/chart/Chart.vue.d.ts +2 -2
  5. package/es/components/src/base/chart/index.d.ts +2 -2
  6. package/es/components/src/base/empty/Empty.vue.d.ts +1 -1
  7. package/es/components/src/base/empty/index.d.ts +3 -3
  8. package/es/components/src/business/loginDialog/LoginDialog.vue2.mjs +7 -8
  9. package/es/components/src/business/loginDialog/LoginDialog.vue2.mjs.map +1 -1
  10. package/es/components/src/business/uploadMaterial/UploadMaterial.vue.d.ts +4 -4
  11. package/es/components/src/business/uploadMaterial/index.d.ts +4 -4
  12. package/es/components/src/business/uploadMaterial/uploadMaterial.d.ts +2 -5
  13. package/es/components/src/business/uploadMaterial/uploadMaterial.mjs.map +1 -1
  14. package/es/components/src/composite/fileComponent/FileComponent.vue.d.ts +1 -1
  15. package/es/components/src/composite/fileComponent/index.d.ts +1 -1
  16. package/es/components/src/composite/importDialog/ImportDialog.vue.d.ts +9 -2
  17. package/es/components/src/composite/importDialog/ImportDialog.vue2.mjs +5 -4
  18. package/es/components/src/composite/importDialog/ImportDialog.vue2.mjs.map +1 -1
  19. package/es/components/src/composite/importDialog/index.d.ts +193 -49
  20. package/es/components/src/composite/previewFile/PreviewFile.vue.d.ts +1 -1
  21. package/es/components/src/composite/previewFile/index.d.ts +1 -1
  22. package/es/components/src/composite/uploadFile/UploadFile.vue.d.ts +5 -5
  23. package/es/components/src/composite/uploadFile/UploadFile.vue.mjs +1 -1
  24. package/es/components/src/composite/uploadFile/UploadFile.vue2.mjs +156 -145
  25. package/es/components/src/composite/uploadFile/UploadFile.vue2.mjs.map +1 -1
  26. package/es/components/src/composite/uploadFile/index.d.ts +12 -12
  27. package/es/giime/index.mjs +2 -1
  28. package/es/giime/index.mjs.map +1 -1
  29. package/es/giime/version.d.ts +1 -1
  30. package/es/giime/version.mjs +1 -1
  31. package/es/giime/version.mjs.map +1 -1
  32. package/es/hooks/base/usePasteFile/index.d.ts +89 -0
  33. package/es/hooks/base/usePasteFile/index.mjs +109 -0
  34. package/es/hooks/base/usePasteFile/index.mjs.map +1 -0
  35. package/es/hooks/store/useOrgUserList/index.d.ts +3 -3
  36. package/es/hooks/store/useOrgUserList/index.mjs +3 -3
  37. package/es/hooks/store/useOrgUserList/index.mjs.map +1 -1
  38. package/es/index.css +59 -58
  39. package/es/utils/index.d.ts +1 -0
  40. package/es/utils/index.mjs +2 -1
  41. package/es/utils/index.mjs.map +1 -1
  42. package/es/utils/src/alioss/aliossPutHook.d.ts +116 -41
  43. package/es/utils/src/alioss/aliossPutHook.mjs +165 -97
  44. package/es/utils/src/alioss/aliossPutHook.mjs.map +1 -1
  45. package/es/utils/src/file.d.ts +7 -0
  46. package/es/utils/src/file.mjs +39 -1
  47. package/es/utils/src/file.mjs.map +1 -1
  48. package/es/utils/src/pasteFile/index.d.ts +33 -0
  49. package/es/utils/src/pasteFile/index.mjs +142 -0
  50. package/es/utils/src/pasteFile/index.mjs.map +1 -0
  51. package/lib/api/materialApi/cross/getAdFileExist.d.ts +1 -0
  52. package/lib/api/materialApi/cross/getAdFileExist.js.map +1 -1
  53. package/lib/components/src/base/chart/Chart.vue.d.ts +2 -2
  54. package/lib/components/src/base/chart/index.d.ts +2 -2
  55. package/lib/components/src/base/empty/Empty.vue.d.ts +1 -1
  56. package/lib/components/src/base/empty/index.d.ts +3 -3
  57. package/lib/components/src/business/loginDialog/LoginDialog.vue2.js +7 -8
  58. package/lib/components/src/business/loginDialog/LoginDialog.vue2.js.map +1 -1
  59. package/lib/components/src/business/uploadMaterial/UploadMaterial.vue.d.ts +4 -4
  60. package/lib/components/src/business/uploadMaterial/index.d.ts +4 -4
  61. package/lib/components/src/business/uploadMaterial/uploadMaterial.d.ts +2 -5
  62. package/lib/components/src/business/uploadMaterial/uploadMaterial.js.map +1 -1
  63. package/lib/components/src/composite/fileComponent/FileComponent.vue.d.ts +1 -1
  64. package/lib/components/src/composite/fileComponent/index.d.ts +1 -1
  65. package/lib/components/src/composite/importDialog/ImportDialog.vue.d.ts +9 -2
  66. package/lib/components/src/composite/importDialog/ImportDialog.vue2.js +4 -3
  67. package/lib/components/src/composite/importDialog/ImportDialog.vue2.js.map +1 -1
  68. package/lib/components/src/composite/importDialog/index.d.ts +193 -49
  69. package/lib/components/src/composite/previewFile/PreviewFile.vue.d.ts +1 -1
  70. package/lib/components/src/composite/previewFile/index.d.ts +1 -1
  71. package/lib/components/src/composite/uploadFile/UploadFile.vue.d.ts +5 -5
  72. package/lib/components/src/composite/uploadFile/UploadFile.vue.js +1 -1
  73. package/lib/components/src/composite/uploadFile/UploadFile.vue2.js +160 -149
  74. package/lib/components/src/composite/uploadFile/UploadFile.vue2.js.map +1 -1
  75. package/lib/components/src/composite/uploadFile/index.d.ts +12 -12
  76. package/lib/giime/index.js +334 -328
  77. package/lib/giime/index.js.map +1 -1
  78. package/lib/giime/version.d.ts +1 -1
  79. package/lib/giime/version.js +1 -1
  80. package/lib/giime/version.js.map +1 -1
  81. package/lib/hooks/base/usePasteFile/index.d.ts +89 -0
  82. package/lib/hooks/base/usePasteFile/index.js +111 -0
  83. package/lib/hooks/base/usePasteFile/index.js.map +1 -0
  84. package/lib/hooks/store/useOrgUserList/index.d.ts +3 -3
  85. package/lib/hooks/store/useOrgUserList/index.js +3 -3
  86. package/lib/hooks/store/useOrgUserList/index.js.map +1 -1
  87. package/lib/index.css +59 -58
  88. package/lib/utils/index.d.ts +1 -0
  89. package/lib/utils/index.js +6 -0
  90. package/lib/utils/index.js.map +1 -1
  91. package/lib/utils/src/alioss/aliossPutHook.d.ts +116 -41
  92. package/lib/utils/src/alioss/aliossPutHook.js +165 -97
  93. package/lib/utils/src/alioss/aliossPutHook.js.map +1 -1
  94. package/lib/utils/src/file.d.ts +7 -0
  95. package/lib/utils/src/file.js +40 -0
  96. package/lib/utils/src/file.js.map +1 -1
  97. package/lib/utils/src/pasteFile/index.d.ts +33 -0
  98. package/lib/utils/src/pasteFile/index.js +146 -0
  99. package/lib/utils/src/pasteFile/index.js.map +1 -0
  100. package/package.json +1 -1
@@ -1,36 +1,59 @@
1
1
  /// <reference types="@vueuse/shared" />
2
- import { type PostSaveFileResourcesData } from '../../../api/materialApi';
3
- export type PostSaveFileResponse = PostSaveFileResourcesData;
2
+ /**
3
+ * 阿里云OSS上传错误类型
4
+ */
5
+ export declare class AliOssError extends Error {
6
+ code: string;
7
+ originalError?: unknown;
8
+ constructor(message: string, code: string, originalError?: unknown);
9
+ }
10
+ /**
11
+ * 上传到阿里云OSS的文件类型
12
+ */
4
13
  export type UploadAliOssFile = File & {
5
14
  uid: number;
6
15
  };
7
- /** 上传文件到阿里云 */
8
- export type AliOssParams = {
16
+ /**
17
+ * 上传进度回调函数类型
18
+ */
19
+ export type ProgressCallback = (progress: {
20
+ percent: number;
21
+ loaded: number;
22
+ total: number;
23
+ }) => void;
24
+ /**
25
+ * 上传文件到阿里云参数类型
26
+ */
27
+ export interface AliOssParams {
9
28
  /** 资源文件 */
10
29
  file: UploadAliOssFile;
11
- /** 文件名 */
30
+ /** 文件名(可选,默认使用原始文件名) */
12
31
  fileName?: string;
13
- /** 文件存储路径 */
32
+ /** 文件存储路径(可选,默认为'material') */
14
33
  folder?: string;
15
- /** 文件存储位置 */
34
+ /** 文件存储位置(可选,默认为'default') */
16
35
  seat?: string;
17
- /** 并行上传数量 */
36
+ /** 并行上传数量(可选,根据文件大小自动计算) */
18
37
  parallel?: number;
19
- /** 并行分片大小 */
38
+ /** 并行分片大小(可选,根据文件大小自动计算) */
20
39
  partSize?: number;
21
- /** 阿里上传配置 */
22
- options?: {
23
- [key: string]: any;
24
- };
25
- /** 阿里服务器 Bucket 名称 */
40
+ /** 阿里上传配置(可选) */
41
+ options?: Record<string, any>;
42
+ /** 阿里服务器 Bucket 名称(可选,默认为'giikin-material') */
26
43
  bucket?: string;
27
- /** cdn */
44
+ /** CDN域名(可选,默认为'https://sucai.giikin.cn/') */
28
45
  cdn?: string;
29
- /** 文件是否保存入库 */
46
+ /** 文件是否保存入库(可选,默认为false) */
30
47
  saveStore?: boolean;
31
- };
32
- /** 返回数据 */
33
- export type AliOssResponse = {
48
+ /** 上传进度回调(可选) */
49
+ onProgress?: ProgressCallback;
50
+ /** 取消上传的信号(可选) */
51
+ abortSignal?: AbortSignal;
52
+ }
53
+ /**
54
+ * 阿里云OSS上传响应类型
55
+ */
56
+ export interface AliOssResponse {
34
57
  /** 文件地址 */
35
58
  url: string;
36
59
  /** 文件名 */
@@ -41,39 +64,91 @@ export type AliOssResponse = {
41
64
  lastModified: number;
42
65
  /** 文件md5 */
43
66
  md5: string;
44
- /** 文件大小 */
67
+ /** 文件大小(字节) */
45
68
  size: number;
46
- /** 文件后缀 */
69
+ /** 文件后缀(不含点) */
47
70
  type: string;
48
71
  /** 文件库是否存在 */
49
72
  isExist: boolean;
50
- };
51
- export declare const ts_md5_file: (file: File) => Promise<string>;
52
- /** 文件分片 */
73
+ /** 文件库中文件ID */
74
+ existId?: number;
75
+ }
76
+ /**
77
+ * 文件检查参数类型
78
+ */
79
+ interface FileExistParams {
80
+ md5Code: string;
81
+ ext: string;
82
+ name: string;
83
+ size: number;
84
+ uid: number;
85
+ lastModified: number;
86
+ }
87
+ /**
88
+ * 根据文件大小计算并行上传参数
89
+ * @param size 文件大小(MB)
90
+ * @returns 并行上传参数配置
91
+ */
53
92
  export declare const getParallelPartSize: (size: number) => {
54
93
  parallel: number;
55
94
  partSize: number;
56
95
  };
57
- /** 上传 Hook */
96
+ /**
97
+ * 阿里云OSS上传Hook
98
+ */
58
99
  export declare const useAliossHookStore: import("pinia").StoreDefinition<"aliossHook", import("pinia")._UnwrapAll<Pick<{
59
100
  aliossResult: import("@vueuse/shared").EventHookOn<AliOssResponse>;
60
- aliossError: import("@vueuse/shared").EventHookOn<any>;
61
- saveFileResult: import("@vueuse/shared").EventHookOn<PostSaveFileResourcesData>;
62
- saveFileError: import("@vueuse/shared").EventHookOn<any>;
63
- uploadFile: ({ file, fileName, folder, seat, parallel, partSize, options, bucket, cdn, saveStore }: AliOssParams) => Promise<unknown>;
64
- postSaveFile: ({ url, md5_code, file_size }: PostSaveFileResourcesData) => Promise<unknown>;
101
+ aliossError: import("@vueuse/shared").EventHookOn<Error | AliOssError>;
102
+ aliossProgress: import("@vueuse/shared").EventHookOn<{
103
+ file: UploadAliOssFile;
104
+ progress: {
105
+ percent: number;
106
+ loaded: number;
107
+ total: number;
108
+ };
109
+ }>;
110
+ saveFileResult: import("@vueuse/shared").EventHookOn<AliOssResponse>;
111
+ saveFileError: import("@vueuse/shared").EventHookOn<Error>;
112
+ uploadFile: (params: AliOssParams) => Promise<AliOssResponse>;
113
+ saveFileToStore: (params: AliOssResponse) => Promise<AliOssResponse>;
114
+ cancelUpload: (uid: number) => boolean;
115
+ cancelAllUploads: () => void;
116
+ checkFileExists: (params: FileExistParams) => Promise<AliOssResponse | false>;
65
117
  }, never>>, Pick<{
66
118
  aliossResult: import("@vueuse/shared").EventHookOn<AliOssResponse>;
67
- aliossError: import("@vueuse/shared").EventHookOn<any>;
68
- saveFileResult: import("@vueuse/shared").EventHookOn<PostSaveFileResourcesData>;
69
- saveFileError: import("@vueuse/shared").EventHookOn<any>;
70
- uploadFile: ({ file, fileName, folder, seat, parallel, partSize, options, bucket, cdn, saveStore }: AliOssParams) => Promise<unknown>;
71
- postSaveFile: ({ url, md5_code, file_size }: PostSaveFileResourcesData) => Promise<unknown>;
119
+ aliossError: import("@vueuse/shared").EventHookOn<Error | AliOssError>;
120
+ aliossProgress: import("@vueuse/shared").EventHookOn<{
121
+ file: UploadAliOssFile;
122
+ progress: {
123
+ percent: number;
124
+ loaded: number;
125
+ total: number;
126
+ };
127
+ }>;
128
+ saveFileResult: import("@vueuse/shared").EventHookOn<AliOssResponse>;
129
+ saveFileError: import("@vueuse/shared").EventHookOn<Error>;
130
+ uploadFile: (params: AliOssParams) => Promise<AliOssResponse>;
131
+ saveFileToStore: (params: AliOssResponse) => Promise<AliOssResponse>;
132
+ cancelUpload: (uid: number) => boolean;
133
+ cancelAllUploads: () => void;
134
+ checkFileExists: (params: FileExistParams) => Promise<AliOssResponse | false>;
72
135
  }, never>, Pick<{
73
136
  aliossResult: import("@vueuse/shared").EventHookOn<AliOssResponse>;
74
- aliossError: import("@vueuse/shared").EventHookOn<any>;
75
- saveFileResult: import("@vueuse/shared").EventHookOn<PostSaveFileResourcesData>;
76
- saveFileError: import("@vueuse/shared").EventHookOn<any>;
77
- uploadFile: ({ file, fileName, folder, seat, parallel, partSize, options, bucket, cdn, saveStore }: AliOssParams) => Promise<unknown>;
78
- postSaveFile: ({ url, md5_code, file_size }: PostSaveFileResourcesData) => Promise<unknown>;
79
- }, "aliossResult" | "aliossError" | "saveFileResult" | "saveFileError" | "uploadFile" | "postSaveFile">>;
137
+ aliossError: import("@vueuse/shared").EventHookOn<Error | AliOssError>;
138
+ aliossProgress: import("@vueuse/shared").EventHookOn<{
139
+ file: UploadAliOssFile;
140
+ progress: {
141
+ percent: number;
142
+ loaded: number;
143
+ total: number;
144
+ };
145
+ }>;
146
+ saveFileResult: import("@vueuse/shared").EventHookOn<AliOssResponse>;
147
+ saveFileError: import("@vueuse/shared").EventHookOn<Error>;
148
+ uploadFile: (params: AliOssParams) => Promise<AliOssResponse>;
149
+ saveFileToStore: (params: AliOssResponse) => Promise<AliOssResponse>;
150
+ cancelUpload: (uid: number) => boolean;
151
+ cancelAllUploads: () => void;
152
+ checkFileExists: (params: FileExistParams) => Promise<AliOssResponse | false>;
153
+ }, "aliossResult" | "aliossError" | "aliossProgress" | "saveFileResult" | "saveFileError" | "uploadFile" | "saveFileToStore" | "cancelUpload" | "cancelAllUploads" | "checkFileExists">>;
154
+ export {};
@@ -2,74 +2,62 @@
2
2
 
3
3
  var pinia = require('pinia');
4
4
  var core = require('@vueuse/core');
5
- var jsMd5 = require('js-md5');
6
5
  var AliOss = require('ali-oss');
7
6
  require('../../../api/materialApi/index.js');
7
+ var file = require('../file.js');
8
8
  var aliossToken = require('./aliossToken.js');
9
9
  var getAdFileExist = require('../../../api/materialApi/cross/getAdFileExist.js');
10
10
  var postSaveFileResources = require('../../../api/materialApi/cross/postSaveFileResources.js');
11
11
 
12
- const ts_md5_file = (file) => {
13
- return new Promise((resolve) => {
14
- const reader = new FileReader();
15
- reader.onload = async function(e) {
16
- const binary = e.target.result;
17
- resolve(jsMd5.md5(binary));
18
- };
19
- reader.readAsArrayBuffer(file);
20
- });
21
- };
12
+ class AliOssError extends Error {
13
+ constructor(message, code, originalError) {
14
+ super(message);
15
+ this.code = code;
16
+ this.originalError = originalError;
17
+ this.name = "AliOssError";
18
+ }
19
+ }
22
20
  const getParallelPartSize = (size) => {
23
21
  const thresholds = [
24
- {
25
- max: 5,
26
- parallel: 1,
27
- multiplier: 5
28
- },
29
- {
30
- max: 10,
31
- parallel: 2,
32
- multiplier: 4
33
- },
34
- {
35
- max: 30,
36
- parallel: 4,
37
- multiplier: 5
38
- },
39
- {
40
- max: 50,
41
- parallel: 6,
42
- multiplier: 6
43
- },
44
- {
45
- max: Number.POSITIVE_INFINITY,
46
- parallel: 8,
47
- multiplier: 8
48
- }
22
+ { max: 5, parallel: 1, multiplier: 5 },
23
+ // 小于5MB: 单线程,5MB分片
24
+ { max: 10, parallel: 2, multiplier: 4 },
25
+ // 5-10MB: 2线程,4MB分片
26
+ { max: 30, parallel: 4, multiplier: 5 },
27
+ // 10-30MB: 4线程,5MB分片
28
+ { max: 50, parallel: 6, multiplier: 6 },
29
+ // 30-50MB: 6线程,6MB分片
30
+ { max: Number.POSITIVE_INFINITY, parallel: 8, multiplier: 8 }
31
+ // >50MB: 8线程,8MB分片
49
32
  ];
50
33
  const { parallel, multiplier } = thresholds.find(({ max }) => size <= max) || thresholds[thresholds.length - 1];
51
34
  return {
52
35
  parallel,
53
36
  partSize: multiplier * 1024 * 1024
37
+ // 转换为字节
54
38
  };
55
39
  };
40
+ const getFileExtension = (filename) => {
41
+ const match = filename.match(/\.(\w+)$/i);
42
+ return match ? match[0] : "";
43
+ };
44
+ const getFileBaseName = (filename) => {
45
+ const ext = getFileExtension(filename);
46
+ return ext ? filename.slice(0, filename.length - ext.length) : filename;
47
+ };
56
48
  const useAliossHookStore = pinia.defineStore("aliossHook", () => {
57
49
  const aliossResult = core.createEventHook();
58
50
  const aliossError = core.createEventHook();
51
+ const aliossProgress = core.createEventHook();
59
52
  const saveFileResult = core.createEventHook();
60
53
  const saveFileError = core.createEventHook();
61
- const getFileExist = async ({
62
- md5Code,
63
- ext,
64
- name,
65
- size,
66
- uid,
67
- lastModified
68
- }) => {
69
- return new Promise(async (resolve) => {
54
+ const uploadTasks = /* @__PURE__ */ new Map();
55
+ const checkFileExists = async (params) => {
56
+ const { md5Code, ext, name, size, uid, lastModified } = params;
57
+ try {
70
58
  const { data } = await getAdFileExist.getAdFileExist({ md5Code, ext });
71
59
  if (data.code !== 0 || data.data.count === 0) {
72
- return resolve(false);
60
+ return false;
73
61
  }
74
62
  const result = {
75
63
  name,
@@ -79,106 +67,186 @@ const useAliossHookStore = pinia.defineStore("aliossHook", () => {
79
67
  url: data.data.url,
80
68
  md5: md5Code,
81
69
  type: ext,
82
- isExist: true
70
+ isExist: true,
71
+ existId: data.data.id ?? data.data.count
83
72
  };
84
- resolve(result);
85
73
  aliossResult.trigger(result);
86
- });
74
+ return result;
75
+ } catch (error) {
76
+ const err = new AliOssError(`\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u5B58\u5728\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`, "CHECK_FILE_EXIST_ERROR", error);
77
+ aliossError.trigger(err);
78
+ throw err;
79
+ }
87
80
  };
88
- const uploadFile = async ({ file, fileName, folder, seat, parallel, partSize, options, bucket, cdn, saveStore }) => {
89
- let { name, uid, lastModified, size } = file;
90
- const ext = name.match(/\.(\w+)$/)?.[0] || "";
91
- name = (fileName || name).slice(0, name.lastIndexOf("."));
92
- const md5Code = await ts_md5_file(file);
93
- const FileName = name + ext;
94
- const type = ext.replaceAll(".", "");
81
+ const uploadFile = async (params) => {
82
+ const {
83
+ file: file$1,
84
+ fileName,
85
+ folder = "material",
86
+ seat = "default",
87
+ parallel,
88
+ partSize,
89
+ options = {},
90
+ bucket = "giikin-material",
91
+ cdn = "https://sucai.giikin.cn/",
92
+ saveStore = false,
93
+ onProgress,
94
+ abortSignal
95
+ } = params;
96
+ const { name: originalName, uid, lastModified, size } = file$1;
97
+ const ext = getFileExtension(originalName);
98
+ const baseName = getFileBaseName(fileName || originalName);
99
+ const finalFileName = baseName + ext;
100
+ const fileType = ext.replace(".", "");
95
101
  try {
96
- let result = await getFileExist({ md5Code, ext: type, name: FileName, size, uid, lastModified });
97
- if (result)
98
- return result;
99
- const timestr = Date.now();
100
- const path = `${folder ?? "material"}/${seat ?? "default"}/file-${timestr}-${md5Code}${ext}`;
101
- const P = getParallelPartSize(size);
102
- options = {
103
- ...P,
104
- ...{ parallel, partSize },
105
- ContentDisposition: `attachment;filename=${encodeURIComponent(name)}${ext};filename*=${encodeURIComponent(name)}${ext}`,
102
+ const md5Code = await file.fileMd5(file$1);
103
+ const existingFile = await checkFileExists({
104
+ md5Code,
105
+ ext: fileType,
106
+ name: finalFileName,
107
+ size,
108
+ uid,
109
+ lastModified
110
+ });
111
+ if (existingFile) {
112
+ return existingFile;
113
+ }
114
+ if (abortSignal?.aborted) {
115
+ throw new AliOssError("\u4E0A\u4F20\u5DF2\u53D6\u6D88", "UPLOAD_ABORTED");
116
+ }
117
+ const timestamp = Date.now();
118
+ const path = `${folder}/${seat}/file-${timestamp}-${md5Code}${ext}`;
119
+ const sizeInMB = size / (1024 * 1024);
120
+ const uploadParams = getParallelPartSize(sizeInMB);
121
+ const uploadOptions = {
122
+ ...uploadParams,
123
+ ...parallel !== void 0 ? { parallel } : {},
124
+ ...partSize !== void 0 ? { partSize } : {},
125
+ ContentDisposition: `attachment;filename=${encodeURIComponent(baseName)}${ext};filename*=${encodeURIComponent(baseName)}${ext}`,
106
126
  ...options
107
127
  };
108
- const bucketName = bucket || "giikin-material";
109
128
  const { AccessKeyId, AccessKeySecret, SecurityToken } = await aliossToken.default().getAliossTokenAsync({
110
- config_id: bucketName
129
+ config_id: bucket
111
130
  });
112
131
  const client = new AliOss({
113
- // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
114
132
  region: "oss-cn-shenzhen",
115
- // 从STS服务获取的临时访问密钥(AccessKey ID、AccessKey Secret、StsToken)。
116
133
  accessKeyId: AccessKeyId,
117
134
  accessKeySecret: AccessKeySecret,
118
135
  stsToken: SecurityToken,
119
- // 刷新临时访问凭证的时间间隔,单位为毫秒。
120
136
  refreshSTSTokenInterval: 3e5,
121
- // 填写Bucket名称。
122
- bucket: bucketName
137
+ bucket
123
138
  });
124
- const upload = options.parallel === 1 ? "put" : "multipartUpload";
125
- const { res } = await client[upload](path, file, options);
126
- if (res.status !== 200) {
127
- aliossError.trigger(res);
128
- return res;
139
+ const uploadMethod = uploadOptions.parallel === 1 ? "put" : "multipartUpload";
140
+ const progressCallback = onProgress ? (p) => {
141
+ onProgress(p);
142
+ aliossProgress.trigger({ file: file$1, progress: p });
143
+ } : void 0;
144
+ if (uploadMethod === "multipartUpload") {
145
+ try {
146
+ const uploadOptions2 = { ...uploadOptions };
147
+ if (progressCallback) {
148
+ uploadOptions2.progress = progressCallback;
149
+ }
150
+ const uploadPromise = client.multipartUpload(path, file$1, uploadOptions2);
151
+ const cancelFn = () => {
152
+ console.warn("\u5C1D\u8BD5\u53D6\u6D88\u4E0A\u4F20\uFF0C\u4F46ali-oss SDK\u53EF\u80FD\u4E0D\u652F\u6301\u53D6\u6D88\u64CD\u4F5C");
153
+ };
154
+ uploadTasks.set(uid, { cancel: cancelFn });
155
+ if (abortSignal) {
156
+ abortSignal.addEventListener("abort", () => {
157
+ cancelFn();
158
+ });
159
+ }
160
+ const result2 = await uploadPromise;
161
+ uploadTasks.delete(uid);
162
+ if (!result2 || !result2.res || result2.res.status !== 200) {
163
+ throw new AliOssError(`\u4E0A\u4F20\u5931\u8D25: ${result2?.res ? `HTTP\u72B6\u6001\u7801 ${result2.res.status}` : "\u672A\u77E5\u9519\u8BEF"}`, "UPLOAD_FAILED", result2);
164
+ }
165
+ } catch (err) {
166
+ uploadTasks.delete(uid);
167
+ throw err;
168
+ }
169
+ } else {
170
+ const result2 = await client.put(path, file$1, uploadOptions);
171
+ if (!result2 || !result2.res || result2.res.status !== 200) {
172
+ throw new AliOssError(`\u4E0A\u4F20\u5931\u8D25: ${result2?.res ? `HTTP\u72B6\u6001\u7801 ${result2.res.status}` : "\u672A\u77E5\u9519\u8BEF"}`, "UPLOAD_FAILED", result2);
173
+ }
129
174
  }
130
- cdn = cdn ?? "https://sucai.giikin.cn/";
131
175
  const resultUrl = cdn + path;
132
- result = {
176
+ const result = {
133
177
  url: resultUrl,
134
- name: name + ext,
178
+ name: finalFileName,
135
179
  md5: md5Code,
136
- type: ext.replaceAll(".", ""),
180
+ type: fileType,
137
181
  uid,
138
182
  lastModified,
139
183
  size,
140
184
  isExist: false
141
185
  };
142
186
  if (saveStore) {
143
- postSaveFile({ url: resultUrl, md5_code: md5Code, file_size: size });
187
+ saveFileToStore(result).catch((error) => {
188
+ console.error("\u4FDD\u5B58\u6587\u4EF6\u5230\u7D20\u6750\u5E93\u5931\u8D25:", error);
189
+ });
144
190
  }
145
191
  aliossResult.trigger(result);
146
192
  return result;
147
193
  } catch (error) {
148
- aliossError.trigger(error);
149
- return error;
194
+ uploadTasks.delete(uid);
195
+ const err = error instanceof AliOssError ? error : new AliOssError(`\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`, "UPLOAD_ERROR", error);
196
+ aliossError.trigger(err);
197
+ throw err;
150
198
  }
151
199
  };
152
- const postSaveFile = async ({ url, md5_code, file_size }) => {
200
+ const saveFileToStore = async (params) => {
153
201
  try {
202
+ const { url, md5: md5_code, size: file_size } = params;
154
203
  const { data } = await postSaveFileResources.postSaveFileResources({ fileData: { url, md5_code, file_size } });
155
204
  if (data?.code !== 0) {
156
- saveFileError.trigger(data);
157
- return data;
205
+ const errorMsg = data?.comment || data?.data?.message || "\u672A\u77E5\u9519\u8BEF";
206
+ const error = new Error(`\u4FDD\u5B58\u6587\u4EF6\u5230\u7D20\u6750\u5E93\u5931\u8D25: ${errorMsg}`);
207
+ saveFileError.trigger(error);
208
+ throw error;
158
209
  }
159
- const result = {
160
- url,
161
- md5_code,
162
- file_size
163
- };
210
+ const result = { ...params, existId: data.data.id ?? data.comment };
164
211
  saveFileResult.trigger(result);
165
212
  return result;
166
213
  } catch (error) {
167
- saveFileError.trigger(error);
168
- return error;
214
+ const err = error instanceof Error ? error : new Error(`\u4FDD\u5B58\u6587\u4EF6\u5230\u7D20\u6750\u5E93\u5931\u8D25: ${String(error)}`);
215
+ saveFileError.trigger(err);
216
+ throw err;
217
+ }
218
+ };
219
+ const cancelUpload = (uid) => {
220
+ const task = uploadTasks.get(uid);
221
+ if (task) {
222
+ task.cancel();
223
+ uploadTasks.delete(uid);
224
+ return true;
169
225
  }
226
+ return false;
227
+ };
228
+ const cancelAllUploads = () => {
229
+ uploadTasks.forEach((task) => task.cancel());
230
+ uploadTasks.clear();
170
231
  };
171
232
  return {
233
+ // 事件监听器
172
234
  aliossResult: aliossResult.on,
173
235
  aliossError: aliossError.on,
236
+ aliossProgress: aliossProgress.on,
174
237
  saveFileResult: saveFileResult.on,
175
238
  saveFileError: saveFileError.on,
239
+ // 主要方法
176
240
  uploadFile,
177
- postSaveFile
241
+ saveFileToStore,
242
+ cancelUpload,
243
+ cancelAllUploads,
244
+ // 辅助方法
245
+ checkFileExists
178
246
  };
179
247
  });
180
248
 
249
+ exports.AliOssError = AliOssError;
181
250
  exports.getParallelPartSize = getParallelPartSize;
182
- exports.ts_md5_file = ts_md5_file;
183
251
  exports.useAliossHookStore = useAliossHookStore;
184
252
  //# sourceMappingURL=aliossPutHook.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"aliossPutHook.js","sources":["../../../../../../packages/utils/src/alioss/aliossPutHook.ts"],"sourcesContent":["import { defineStore } from 'pinia';\r\nimport { createEventHook } from '@vueuse/core';\r\nimport { md5 } from 'js-md5';\r\nimport AliOss from 'ali-oss';\r\nimport { type PostSaveFileResourcesData, getAdFileExist, postSaveFileResources } from '@giime/api/materialApi';\r\nimport useAliossTokenStore from './aliossToken';\r\n\r\nexport type PostSaveFileResponse = PostSaveFileResourcesData;\r\nexport type UploadAliOssFile = File & { uid: number };\r\n\r\n/** 上传文件到阿里云 */\r\nexport type AliOssParams = {\r\n /** 资源文件 */\r\n file: UploadAliOssFile;\r\n /** 文件名 */\r\n fileName?: string;\r\n /** 文件存储路径 */\r\n folder?: string;\r\n /** 文件存储位置 */\r\n seat?: string;\r\n /** 并行上传数量 */\r\n parallel?: number;\r\n /** 并行分片大小 */\r\n partSize?: number;\r\n /** 阿里上传配置 */\r\n options?: { [key: string]: any };\r\n /** 阿里服务器 Bucket 名称 */\r\n bucket?: string;\r\n /** cdn */\r\n cdn?: string;\r\n /** 文件是否保存入库 */\r\n saveStore?: boolean;\r\n};\r\n\r\n/** 返回数据 */\r\nexport type AliOssResponse = {\r\n /** 文件地址 */\r\n url: string;\r\n /** 文件名 */\r\n name: string;\r\n /** 文件唯一标识 */\r\n uid: number;\r\n /** 文件最后修改时间 */\r\n lastModified: number;\r\n /** 文件md5 */\r\n md5: string;\r\n /** 文件大小 */\r\n size: number;\r\n /** 文件后缀 */\r\n type: string;\r\n /** 文件库是否存在 */\r\n isExist: boolean;\r\n};\r\n\r\nexport const ts_md5_file = (file: File) => {\r\n return new Promise<string>(resolve => {\r\n const reader = new FileReader();\r\n reader.onload = async function (e) {\r\n const binary = (e.target as any).result;\r\n resolve(md5(binary));\r\n };\r\n reader.readAsArrayBuffer(file);\r\n });\r\n};\r\n\r\n/** 文件分片 */\r\nexport const getParallelPartSize = (size: number) => {\r\n const thresholds = [\r\n {\r\n max: 5,\r\n parallel: 1,\r\n multiplier: 5,\r\n },\r\n {\r\n max: 10,\r\n parallel: 2,\r\n multiplier: 4,\r\n },\r\n {\r\n max: 30,\r\n parallel: 4,\r\n multiplier: 5,\r\n },\r\n {\r\n max: 50,\r\n parallel: 6,\r\n multiplier: 6,\r\n },\r\n {\r\n max: Number.POSITIVE_INFINITY,\r\n parallel: 8,\r\n multiplier: 8,\r\n },\r\n ];\r\n const { parallel, multiplier } = thresholds.find(({ max }) => size <= max) || thresholds[thresholds.length - 1];\r\n\r\n return {\r\n parallel,\r\n partSize: multiplier * 1024 * 1024,\r\n };\r\n};\r\n\r\n/** 上传 Hook */\r\nexport const useAliossHookStore = defineStore('aliossHook', () => {\r\n const aliossResult = createEventHook<AliOssResponse>();\r\n const aliossError = createEventHook<any>();\r\n const saveFileResult = createEventHook<PostSaveFileResponse>();\r\n const saveFileError = createEventHook<any>();\r\n\r\n /** 检测广告素材是否已存在 */\r\n const getFileExist = async ({\r\n md5Code,\r\n ext,\r\n name,\r\n size,\r\n uid,\r\n lastModified,\r\n }: {\r\n md5Code: string;\r\n ext: string;\r\n name: string;\r\n size: number;\r\n uid: number;\r\n lastModified: number;\r\n }) => {\r\n // eslint-disable-next-line no-async-promise-executor\r\n return new Promise<AliOssResponse | false>(async resolve => {\r\n const { data } = await getAdFileExist({ md5Code, ext });\r\n if (data.code !== 0 || data.data.count === 0) {\r\n return resolve(false);\r\n }\r\n const result = {\r\n name,\r\n uid,\r\n lastModified,\r\n size,\r\n url: data.data.url,\r\n md5: md5Code,\r\n type: ext,\r\n isExist: true,\r\n };\r\n resolve(result);\r\n aliossResult.trigger(result);\r\n });\r\n };\r\n\r\n /** 上传文件 */\r\n const uploadFile = async ({ file, fileName, folder, seat, parallel, partSize, options, bucket, cdn, saveStore }: AliOssParams) => {\r\n let { name, uid, lastModified, size } = file;\r\n const ext = name.match(/\\.(\\w+)$/)?.[0] || '';\r\n name = (fileName || name).slice(0, name.lastIndexOf('.'));\r\n const md5Code = await ts_md5_file(file);\r\n const FileName = name + ext;\r\n const type = ext.replaceAll('.', '');\r\n\r\n try {\r\n let result = await getFileExist({ md5Code, ext: type, name: FileName, size, uid, lastModified });\r\n if (result) return result;\r\n\r\n // 文件存储路径\r\n const timestr = Date.now();\r\n const path = `${folder ?? 'material'}/${seat ?? 'default'}/file-${timestr}-${md5Code}${ext}`;\r\n\r\n const P = getParallelPartSize(size);\r\n options = {\r\n ...P,\r\n ...{ parallel, partSize },\r\n ContentDisposition: `attachment;filename=${encodeURIComponent(name)}${ext};filename*=${encodeURIComponent(name)}${ext}`,\r\n ...options,\r\n };\r\n\r\n // 阿里云临时上传权限\r\n // 使用组件 props 的默认值\r\n const bucketName = bucket || 'giikin-material';\r\n const { AccessKeyId, AccessKeySecret, SecurityToken } = await useAliossTokenStore().getAliossTokenAsync({\r\n config_id: bucketName,\r\n });\r\n\r\n const client = new AliOss({\r\n // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。\r\n region: 'oss-cn-shenzhen',\r\n // 从STS服务获取的临时访问密钥(AccessKey ID、AccessKey Secret、StsToken)。\r\n accessKeyId: AccessKeyId,\r\n accessKeySecret: AccessKeySecret,\r\n stsToken: SecurityToken,\r\n // 刷新临时访问凭证的时间间隔,单位为毫秒。\r\n refreshSTSTokenInterval: 300000,\r\n // 填写Bucket名称。\r\n bucket: bucketName,\r\n });\r\n\r\n const upload = options.parallel === 1 ? 'put' : 'multipartUpload';\r\n const { res } = await client[upload](path, file, options);\r\n if (res.status !== 200) {\r\n aliossError.trigger(res);\r\n return res;\r\n }\r\n cdn = cdn ?? 'https://sucai.giikin.cn/';\r\n const resultUrl = cdn + path;\r\n result = {\r\n url: resultUrl,\r\n name: name + ext,\r\n md5: md5Code,\r\n type: ext.replaceAll('.', ''),\r\n uid,\r\n lastModified,\r\n size,\r\n isExist: false,\r\n };\r\n if (saveStore) {\r\n postSaveFile({ url: resultUrl, md5_code: md5Code, file_size: size });\r\n }\r\n aliossResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n aliossError.trigger(error);\r\n return error;\r\n }\r\n };\r\n\r\n /** 文件入库 */\r\n const postSaveFile = async ({ url, md5_code, file_size }: PostSaveFileResourcesData) => {\r\n try {\r\n const { data } = await postSaveFileResources({ fileData: { url, md5_code, file_size } });\r\n if (data?.code !== 0) {\r\n saveFileError.trigger(data);\r\n return data;\r\n }\r\n const result = {\r\n url,\r\n md5_code,\r\n file_size,\r\n };\r\n saveFileResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n saveFileError.trigger(error);\r\n return error;\r\n }\r\n };\r\n return {\r\n aliossResult: aliossResult.on,\r\n aliossError: aliossError.on,\r\n saveFileResult: saveFileResult.on,\r\n saveFileError: saveFileError.on,\r\n uploadFile,\r\n postSaveFile,\r\n };\r\n});\r\n"],"names":["md5","defineStore","createEventHook","getAdFileExist","useAliossTokenStore","postSaveFileResources"],"mappings":"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"}
1
+ {"version":3,"file":"aliossPutHook.js","sources":["../../../../../../packages/utils/src/alioss/aliossPutHook.ts"],"sourcesContent":["import { defineStore } from 'pinia';\r\nimport { createEventHook } from '@vueuse/core';\r\nimport AliOss from 'ali-oss';\r\nimport { getAdFileExist, postSaveFileResources } from '@giime/api/materialApi';\r\nimport { fileMd5 } from '../file';\r\nimport useAliossTokenStore from './aliossToken';\r\n\r\n/**\r\n * 阿里云OSS上传错误类型\r\n */\r\nexport class AliOssError extends Error {\r\n constructor(\r\n message: string,\r\n public code: string,\r\n public originalError?: unknown,\r\n ) {\r\n super(message);\r\n this.name = 'AliOssError';\r\n }\r\n}\r\n/**\r\n * 上传到阿里云OSS的文件类型\r\n */\r\nexport type UploadAliOssFile = File & { uid: number };\r\n\r\n/**\r\n * 上传进度回调函数类型\r\n */\r\nexport type ProgressCallback = (progress: { percent: number; loaded: number; total: number }) => void;\r\n\r\n/**\r\n * 上传文件到阿里云参数类型\r\n */\r\nexport interface AliOssParams {\r\n /** 资源文件 */\r\n file: UploadAliOssFile;\r\n /** 文件名(可选,默认使用原始文件名) */\r\n fileName?: string;\r\n /** 文件存储路径(可选,默认为'material') */\r\n folder?: string;\r\n /** 文件存储位置(可选,默认为'default') */\r\n seat?: string;\r\n /** 并行上传数量(可选,根据文件大小自动计算) */\r\n parallel?: number;\r\n /** 并行分片大小(可选,根据文件大小自动计算) */\r\n partSize?: number;\r\n /** 阿里上传配置(可选) */\r\n options?: Record<string, any>;\r\n /** 阿里服务器 Bucket 名称(可选,默认为'giikin-material') */\r\n bucket?: string;\r\n /** CDN域名(可选,默认为'https://sucai.giikin.cn/') */\r\n cdn?: string;\r\n /** 文件是否保存入库(可选,默认为false) */\r\n saveStore?: boolean;\r\n /** 上传进度回调(可选) */\r\n onProgress?: ProgressCallback;\r\n /** 取消上传的信号(可选) */\r\n abortSignal?: AbortSignal;\r\n}\r\n\r\n/**\r\n * 阿里云OSS上传响应类型\r\n */\r\nexport interface AliOssResponse {\r\n /** 文件地址 */\r\n url: string;\r\n /** 文件名 */\r\n name: string;\r\n /** 文件唯一标识 */\r\n uid: number;\r\n /** 文件最后修改时间 */\r\n lastModified: number;\r\n /** 文件md5 */\r\n md5: string;\r\n /** 文件大小(字节) */\r\n size: number;\r\n /** 文件后缀(不含点) */\r\n type: string;\r\n /** 文件库是否存在 */\r\n isExist: boolean;\r\n /** 文件库中文件ID */\r\n existId?: number;\r\n}\r\n\r\n/**\r\n * 文件检查参数类型\r\n */\r\ninterface FileExistParams {\r\n md5Code: string;\r\n ext: string;\r\n name: string;\r\n size: number;\r\n uid: number;\r\n lastModified: number;\r\n}\r\n\r\n/**\r\n * 根据文件大小计算并行上传参数\r\n * @param size 文件大小(MB)\r\n * @returns 并行上传参数配置\r\n */\r\nexport const getParallelPartSize = (size: number) => {\r\n // 文件大小阈值(MB)及对应的并行配置\r\n const thresholds = [\r\n { max: 5, parallel: 1, multiplier: 5 }, // 小于5MB: 单线程,5MB分片\r\n { max: 10, parallel: 2, multiplier: 4 }, // 5-10MB: 2线程,4MB分片\r\n { max: 30, parallel: 4, multiplier: 5 }, // 10-30MB: 4线程,5MB分片\r\n { max: 50, parallel: 6, multiplier: 6 }, // 30-50MB: 6线程,6MB分片\r\n { max: Number.POSITIVE_INFINITY, parallel: 8, multiplier: 8 }, // >50MB: 8线程,8MB分片\r\n ];\r\n\r\n // 查找适合当前文件大小的配置\r\n const { parallel, multiplier } = thresholds.find(({ max }) => size <= max) || thresholds[thresholds.length - 1];\r\n\r\n return {\r\n parallel,\r\n partSize: multiplier * 1024 * 1024, // 转换为字节\r\n };\r\n};\r\n\r\n/**\r\n * 从文件名中提取扩展名\r\n * @param filename 文件名\r\n * @returns 扩展名(包含点)\r\n */\r\nconst getFileExtension = (filename: string): string => {\r\n const match = filename.match(/\\.(\\w+)$/i);\r\n return match ? match[0] : '';\r\n};\r\n\r\n/**\r\n * 从文件名中提取基本名称(不含扩展名)\r\n * @param filename 文件名\r\n * @returns 基本名称\r\n */\r\nconst getFileBaseName = (filename: string): string => {\r\n const ext = getFileExtension(filename);\r\n return ext ? filename.slice(0, filename.length - ext.length) : filename;\r\n};\r\n\r\n/**\r\n * 阿里云OSS上传Hook\r\n */\r\nexport const useAliossHookStore = defineStore('aliossHook', () => {\r\n // 创建事件钩子\r\n const aliossResult = createEventHook<AliOssResponse>();\r\n const aliossError = createEventHook<AliOssError | Error>();\r\n const aliossProgress = createEventHook<{ file: UploadAliOssFile; progress: { percent: number; loaded: number; total: number } }>();\r\n const saveFileResult = createEventHook<AliOssResponse>();\r\n const saveFileError = createEventHook<Error>();\r\n\r\n // 存储当前上传任务,用于取消\r\n const uploadTasks = new Map<number, { cancel: () => void }>();\r\n\r\n /**\r\n * 检测文件是否已存在于素材库\r\n * @param params 文件检查参数\r\n * @returns 如果文件存在,返回文件信息;否则返回false\r\n */\r\n const checkFileExists = async (params: FileExistParams): Promise<AliOssResponse | false> => {\r\n const { md5Code, ext, name, size, uid, lastModified } = params;\r\n\r\n try {\r\n const { data } = await getAdFileExist({ md5Code, ext });\r\n\r\n // 文件不存在\r\n if (data.code !== 0 || data.data.count === 0) {\r\n return false;\r\n }\r\n\r\n // 文件已存在,构建响应\r\n const result: AliOssResponse = {\r\n name,\r\n uid,\r\n lastModified,\r\n size,\r\n url: data.data.url,\r\n md5: md5Code,\r\n type: ext,\r\n isExist: true,\r\n existId: data.data.id ?? data.data.count,\r\n };\r\n\r\n // 触发结果事件\r\n aliossResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n // 处理错误\r\n const err = new AliOssError(`检查文件是否存在失败: ${error instanceof Error ? error.message : String(error)}`, 'CHECK_FILE_EXIST_ERROR', error);\r\n aliossError.trigger(err);\r\n throw err;\r\n }\r\n };\r\n\r\n /**\r\n * 上传文件到阿里云OSS\r\n * @param params 上传参数\r\n * @returns 上传结果\r\n */\r\n const uploadFile = async (params: AliOssParams): Promise<AliOssResponse> => {\r\n const {\r\n file,\r\n fileName,\r\n folder = 'material',\r\n seat = 'default',\r\n parallel,\r\n partSize,\r\n options = {},\r\n bucket = 'giikin-material',\r\n cdn = 'https://sucai.giikin.cn/',\r\n saveStore = false,\r\n onProgress,\r\n abortSignal,\r\n } = params;\r\n\r\n const { name: originalName, uid, lastModified, size } = file;\r\n\r\n // 提取文件扩展名和基本名称\r\n const ext = getFileExtension(originalName);\r\n const baseName = getFileBaseName(fileName || originalName);\r\n const finalFileName = baseName + ext;\r\n const fileType = ext.replace('.', '');\r\n\r\n try {\r\n // 计算文件MD5\r\n const md5Code = await fileMd5(file);\r\n\r\n // 检查文件是否已存在\r\n const existingFile = await checkFileExists({\r\n md5Code,\r\n ext: fileType,\r\n name: finalFileName,\r\n size,\r\n uid,\r\n lastModified,\r\n });\r\n\r\n // 如果文件已存在,直接返回\r\n if (existingFile) {\r\n return existingFile;\r\n }\r\n\r\n // 如果提供了取消信号并且已经被触发,则取消上传\r\n if (abortSignal?.aborted) {\r\n throw new AliOssError('上传已取消', 'UPLOAD_ABORTED');\r\n }\r\n\r\n // 生成文件存储路径\r\n const timestamp = Date.now();\r\n const path = `${folder}/${seat}/file-${timestamp}-${md5Code}${ext}`;\r\n\r\n // 根据文件大小计算上传参数\r\n const sizeInMB = size / (1024 * 1024);\r\n const uploadParams = getParallelPartSize(sizeInMB);\r\n\r\n // 合并上传选项\r\n const uploadOptions = {\r\n ...uploadParams,\r\n ...(parallel !== undefined ? { parallel } : {}),\r\n ...(partSize !== undefined ? { partSize } : {}),\r\n ContentDisposition: `attachment;filename=${encodeURIComponent(baseName)}${ext};filename*=${encodeURIComponent(baseName)}${ext}`,\r\n ...options,\r\n };\r\n\r\n // 获取阿里云临时上传权限\r\n const { AccessKeyId, AccessKeySecret, SecurityToken } = await useAliossTokenStore().getAliossTokenAsync({\r\n config_id: bucket,\r\n });\r\n\r\n // 创建阿里云OSS客户端\r\n const client = new AliOss({\r\n region: 'oss-cn-shenzhen',\r\n accessKeyId: AccessKeyId,\r\n accessKeySecret: AccessKeySecret,\r\n stsToken: SecurityToken,\r\n refreshSTSTokenInterval: 300000,\r\n bucket,\r\n });\r\n\r\n // 根据并行数选择上传方法\r\n const uploadMethod = uploadOptions.parallel === 1 ? 'put' : 'multipartUpload';\r\n\r\n // 添加进度回调\r\n const progressCallback = onProgress\r\n ? (p: { percent: number; loaded: number; total: number }) => {\r\n onProgress(p);\r\n aliossProgress.trigger({ file, progress: p });\r\n }\r\n : undefined;\r\n\r\n // 处理上传\r\n if (uploadMethod === 'multipartUpload') {\r\n // 分片上传\r\n try {\r\n // 创建一个可取消的上传任务\r\n // 注意:使用as any来绕过TypeScript类型检查,因为ali-oss类型定义可能不完整\r\n const uploadOptions2 = { ...uploadOptions };\r\n if (progressCallback) {\r\n (uploadOptions2 as any).progress = progressCallback;\r\n }\r\n\r\n const uploadPromise = client.multipartUpload(path, file, uploadOptions2 as any);\r\n\r\n // 创建一个取消函数\r\n const cancelFn = () => {\r\n // 注意:ali-oss SDK可能没有直接提供取消方法\r\n // 这里我们需要根据SDK文档调整实际取消逻辑\r\n console.warn('尝试取消上传,但ali-oss SDK可能不支持取消操作');\r\n };\r\n\r\n uploadTasks.set(uid, { cancel: cancelFn });\r\n\r\n // 监听取消信号\r\n if (abortSignal) {\r\n abortSignal.addEventListener('abort', () => {\r\n cancelFn();\r\n });\r\n }\r\n\r\n // 等待上传完成\r\n const result = await uploadPromise;\r\n uploadTasks.delete(uid);\r\n\r\n if (!result || !result.res || result.res.status !== 200) {\r\n throw new AliOssError(`上传失败: ${result?.res ? `HTTP状态码 ${result.res.status}` : '未知错误'}`, 'UPLOAD_FAILED', result);\r\n }\r\n } catch (err) {\r\n uploadTasks.delete(uid);\r\n throw err;\r\n }\r\n } else {\r\n // 普通上传\r\n const result = await client.put(path, file, uploadOptions as any);\r\n\r\n if (!result || !result.res || result.res.status !== 200) {\r\n throw new AliOssError(`上传失败: ${result?.res ? `HTTP状态码 ${result.res.status}` : '未知错误'}`, 'UPLOAD_FAILED', result);\r\n }\r\n }\r\n\r\n // 构建结果URL\r\n const resultUrl = cdn + path;\r\n\r\n // 构建响应对象\r\n const result: AliOssResponse = {\r\n url: resultUrl,\r\n name: finalFileName,\r\n md5: md5Code,\r\n type: fileType,\r\n uid,\r\n lastModified,\r\n size,\r\n isExist: false,\r\n };\r\n\r\n // 如果需要保存到素材库\r\n if (saveStore) {\r\n saveFileToStore(result).catch(error => {\r\n console.error('保存文件到素材库失败:', error);\r\n });\r\n }\r\n\r\n // 触发成功事件\r\n aliossResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n // 移除上传任务\r\n uploadTasks.delete(uid);\r\n\r\n // 处理错误\r\n const err =\r\n error instanceof AliOssError\r\n ? error\r\n : new AliOssError(`上传文件失败: ${error instanceof Error ? error.message : String(error)}`, 'UPLOAD_ERROR', error);\r\n\r\n // 触发错误事件\r\n aliossError.trigger(err);\r\n throw err;\r\n }\r\n };\r\n\r\n /**\r\n * 保存文件到素材库\r\n * @param params 文件保存参数\r\n * @returns 保存结果\r\n */\r\n const saveFileToStore = async (params: AliOssResponse): Promise<AliOssResponse> => {\r\n try {\r\n const { url, md5: md5_code, size: file_size } = params;\r\n const { data } = await postSaveFileResources({ fileData: { url, md5_code, file_size } });\r\n\r\n if (data?.code !== 0) {\r\n const errorMsg = data?.comment || data?.data?.message || '未知错误';\r\n const error = new Error(`保存文件到素材库失败: ${errorMsg}`);\r\n saveFileError.trigger(error);\r\n throw error;\r\n }\r\n\r\n const result = { ...params, existId: data.data.id ?? data.comment };\r\n saveFileResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(`保存文件到素材库失败: ${String(error)}`);\r\n\r\n saveFileError.trigger(err);\r\n throw err;\r\n }\r\n };\r\n\r\n /**\r\n * 取消文件上传\r\n * @param uid 文件唯一标识\r\n * @returns 是否成功取消\r\n */\r\n const cancelUpload = (uid: number): boolean => {\r\n const task = uploadTasks.get(uid);\r\n if (task) {\r\n task.cancel();\r\n uploadTasks.delete(uid);\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n /**\r\n * 取消所有上传任务\r\n */\r\n const cancelAllUploads = (): void => {\r\n uploadTasks.forEach(task => task.cancel());\r\n uploadTasks.clear();\r\n };\r\n\r\n return {\r\n // 事件监听器\r\n aliossResult: aliossResult.on,\r\n aliossError: aliossError.on,\r\n aliossProgress: aliossProgress.on,\r\n saveFileResult: saveFileResult.on,\r\n saveFileError: saveFileError.on,\r\n\r\n // 主要方法\r\n uploadFile,\r\n saveFileToStore,\r\n cancelUpload,\r\n cancelAllUploads,\r\n\r\n // 辅助方法\r\n checkFileExists,\r\n };\r\n});\r\n"],"names":["defineStore","createEventHook","getAdFileExist","file","fileMd5","useAliossTokenStore","result","postSaveFileResources"],"mappings":"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"}
@@ -63,3 +63,10 @@ export declare function base64ToBlob(base64: string, options?: FileConversionOpt
63
63
  * @returns
64
64
  */
65
65
  export declare function fileToUrl(file: File | Blob): string;
66
+ export declare function fileValidType(file: File, validTypes: string): boolean;
67
+ /**
68
+ * 计算文件的MD5哈希值
69
+ * @param file 要计算哈希值的文件
70
+ * @returns 文件的MD5哈希值
71
+ */
72
+ export declare const fileMd5: (file: File) => Promise<string>;