@ai-group/chat-sdk 3.0.1-alpha.6 → 3.0.3

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 (68) hide show
  1. package/dist/cjs/components/FileGallery/index.d.ts +33 -0
  2. package/dist/cjs/components/FileGallery/index.js +301 -0
  3. package/dist/cjs/components/FileGallery/index.js.map +7 -0
  4. package/dist/{esm/components/XAdkChatbot → cjs}/components/FileGallery/styles.d.ts +11 -6
  5. package/dist/cjs/components/FileGallery/styles.js +188 -0
  6. package/dist/cjs/components/FileGallery/styles.js.map +7 -0
  7. package/dist/cjs/components/XAdkChatbot/index.js +1 -1
  8. package/dist/cjs/components/XAdkChatbot/index.js.map +1 -1
  9. package/dist/cjs/components/XAdkSender/index.d.ts +1 -1
  10. package/dist/cjs/components/XAdkSender/index.js +94 -77
  11. package/dist/cjs/components/XAdkSender/index.js.map +3 -3
  12. package/dist/cjs/index.d.ts +2 -2
  13. package/dist/cjs/index.js +1 -1
  14. package/dist/cjs/index.js.map +3 -3
  15. package/dist/cjs/types/FileGallery.d.ts +54 -0
  16. package/dist/cjs/types/FileGallery.js +18 -0
  17. package/dist/cjs/types/FileGallery.js.map +7 -0
  18. package/dist/cjs/types/XAdkSender.d.ts +17 -8
  19. package/dist/cjs/types/XAdkSender.js.map +1 -1
  20. package/dist/cjs/types/index.d.ts +2 -0
  21. package/dist/cjs/types/index.js +4 -0
  22. package/dist/cjs/types/index.js.map +2 -2
  23. package/dist/cjs/utils/file.d.ts +2 -0
  24. package/dist/cjs/utils/file.js +33 -0
  25. package/dist/cjs/utils/file.js.map +7 -0
  26. package/dist/esm/components/FileGallery/index.d.ts +33 -0
  27. package/dist/esm/components/FileGallery/index.js +439 -0
  28. package/dist/esm/components/FileGallery/index.js.map +1 -0
  29. package/dist/{cjs/components/XAdkChatbot → esm}/components/FileGallery/styles.d.ts +11 -6
  30. package/dist/esm/components/FileGallery/styles.js +23 -0
  31. package/dist/esm/components/FileGallery/styles.js.map +1 -0
  32. package/dist/esm/components/XAdkChatbot/index.js +1 -1
  33. package/dist/esm/components/XAdkChatbot/index.js.map +1 -1
  34. package/dist/esm/components/XAdkSender/index.d.ts +1 -1
  35. package/dist/esm/components/XAdkSender/index.js +106 -99
  36. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  37. package/dist/esm/index.d.ts +2 -2
  38. package/dist/esm/index.js +2 -2
  39. package/dist/esm/index.js.map +1 -1
  40. package/dist/esm/types/FileGallery.d.ts +54 -0
  41. package/dist/esm/types/FileGallery.js +2 -0
  42. package/dist/esm/types/FileGallery.js.map +1 -0
  43. package/dist/esm/types/XAdkSender.d.ts +17 -8
  44. package/dist/esm/types/XAdkSender.js.map +1 -1
  45. package/dist/esm/types/index.d.ts +2 -0
  46. package/dist/esm/types/index.js +2 -0
  47. package/dist/esm/types/index.js.map +1 -1
  48. package/dist/esm/utils/file.d.ts +2 -0
  49. package/dist/esm/utils/file.js +10 -0
  50. package/dist/esm/utils/file.js.map +1 -0
  51. package/dist/umd/chat-sdk.min.js +1 -1
  52. package/package.json +1 -1
  53. package/dist/cjs/components/XAdkChatbot/components/FileGallery/index.d.ts +0 -12
  54. package/dist/cjs/components/XAdkChatbot/components/FileGallery/index.js +0 -92
  55. package/dist/cjs/components/XAdkChatbot/components/FileGallery/index.js.map +0 -7
  56. package/dist/cjs/components/XAdkChatbot/components/FileGallery/styles.js +0 -137
  57. package/dist/cjs/components/XAdkChatbot/components/FileGallery/styles.js.map +0 -7
  58. package/dist/cjs/components/XAdkSender/FileGallery.d.ts +0 -8
  59. package/dist/cjs/components/XAdkSender/FileGallery.js +0 -444
  60. package/dist/cjs/components/XAdkSender/FileGallery.js.map +0 -7
  61. package/dist/esm/components/XAdkChatbot/components/FileGallery/index.d.ts +0 -12
  62. package/dist/esm/components/XAdkChatbot/components/FileGallery/index.js +0 -104
  63. package/dist/esm/components/XAdkChatbot/components/FileGallery/index.js.map +0 -1
  64. package/dist/esm/components/XAdkChatbot/components/FileGallery/styles.js +0 -20
  65. package/dist/esm/components/XAdkChatbot/components/FileGallery/styles.js.map +0 -1
  66. package/dist/esm/components/XAdkSender/FileGallery.d.ts +0 -8
  67. package/dist/esm/components/XAdkSender/FileGallery.js +0 -347
  68. package/dist/esm/components/XAdkSender/FileGallery.js.map +0 -1
@@ -0,0 +1,18 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
14
+
15
+ // src/types/FileGallery.ts
16
+ var FileGallery_exports = {};
17
+ module.exports = __toCommonJS(FileGallery_exports);
18
+ //# sourceMappingURL=FileGallery.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/types/FileGallery.ts"],
4
+ "sourcesContent": ["/**\n * 统一的文件数据接口\n * 兼容 LocalFile (XAdkSender) 和 FileData (XadkChatbot)\n */\nexport interface FileItem {\n // 基础字段\n id?: string;\n uid?: string;\n name?: string;\n displayName?: string;\n size?: number;\n type?: string;\n mimeType?: string;\n\n // 本地文件对象 (XAdkSender)\n file?: File;\n\n // 上传状态 (XAdkSender)\n status?: \"pending\" | \"uploading\" | \"success\" | \"error\";\n progress?: number;\n errorMessage?: string;\n\n // URL 字段\n fileUri?: string; // XadkChatbot\n tempUrl?: string; // XAdkSender\n response?: any;\n}\n\nexport interface FileGalleryProps {\n /**\n * 文件列表\n */\n files: FileItem[];\n\n /**\n * 对齐方式\n * @default 'left'\n */\n align?: \"left\" | \"right\";\n\n /**\n * 是否可删除\n * @default false\n */\n removable?: boolean;\n\n /**\n * 删除文件回调\n */\n onRemove?: (id: string) => void;\n\n /**\n * 自定义样式类名\n */\n className?: string;\n\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n}\n\nexport interface FileItemComponentProps {\n file: FileItem;\n removable: boolean;\n onRemove: (id: string) => void;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  interface uploadRequestProps {
3
3
  (options: {
4
4
  file: File;
@@ -24,12 +24,15 @@ export interface LocalFile {
24
24
  size: number;
25
25
  type: string;
26
26
  progress: number;
27
- status: 'pending' | 'uploading' | 'success' | 'error';
27
+ status: "pending" | "uploading" | "success" | "error";
28
28
  fileId?: number;
29
29
  tempUrl?: string;
30
30
  response?: any;
31
31
  errorMessage?: string;
32
32
  }
33
+ export type FileValidator = (file: File, context: {
34
+ files: LocalFile[];
35
+ }) => string | null;
33
36
  export interface ActionsComponents {
34
37
  SendButton: React.ComponentType<any>;
35
38
  UploadButton: React.ComponentType<any>;
@@ -38,7 +41,17 @@ export interface ActionsComponents {
38
41
  export type SlotRenderFunction = (oriNode: React.ReactNode, info: {
39
42
  components: ActionsComponents;
40
43
  }) => React.ReactNode | false;
41
- export interface XAdkSenderProps {
44
+ export interface UploaderCoreProps {
45
+ uploadRequest?: uploadRequestProps;
46
+ maxFileSize?: number;
47
+ allowedFileTypes?: string[];
48
+ maxFiles?: number;
49
+ validators?: FileValidator[];
50
+ onFilesChange?: (files: LocalFile[]) => void;
51
+ onUploadSuccess?: (file: LocalFile) => void;
52
+ onUploadError?: (file: LocalFile, error: Error) => void;
53
+ }
54
+ export interface SenderUIProps {
42
55
  clearBtnShow?: boolean;
43
56
  allowUpload?: boolean;
44
57
  loading?: boolean;
@@ -50,11 +63,6 @@ export interface XAdkSenderProps {
50
63
  files: ServerFile[];
51
64
  }) => void;
52
65
  onStop?: () => void;
53
- uploadRequest?: uploadRequestProps;
54
- maxFileSize?: number;
55
- allowedFileTypes?: string[];
56
- maxFiles?: number;
57
- onFilesChange?: (files: ServerFile[]) => void;
58
66
  /** 后缀内容,默认展示操作按钮,设为 false 时不显示 */
59
67
  suffix?: React.ReactNode | false | SlotRenderFunction;
60
68
  /** 头部面板 */
@@ -64,4 +72,5 @@ export interface XAdkSenderProps {
64
72
  /** 底部内容 */
65
73
  footer?: React.ReactNode | false | SlotRenderFunction;
66
74
  }
75
+ export type XAdkSenderProps = SenderUIProps & UploaderCoreProps;
67
76
  export {};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/types/XAdkSender.ts"],
4
- "sourcesContent": ["// types/XAdkSender.ts\nimport React from 'react';\n\ninterface uploadRequestProps {\n (options: {\n file: File;\n onProgress?: (e: { percent: number }) => void;\n onSuccess?: (response: any) => void;\n onError?: (error: Error) => void;\n }): Promise<void> | void;\n}\n\nexport interface ServerFile {\n fileName: string;\n fileId: number;\n tempUrl: string;\n type: string;\n mimeType: string;\n}\n\nexport interface LocalFile {\n id: string;\n uid: string;\n name: string;\n file: File;\n size: number;\n type: string;\n progress: number;\n status: 'pending' | 'uploading' | 'success' | 'error';\n // 服务器返回字段\n fileId?: number;\n tempUrl?: string;\n response?: any;\n errorMessage?: string; // 上传错误信息\n}\n\nexport interface ActionsComponents {\n SendButton: React.ComponentType<any>;\n UploadButton: React.ComponentType<any>;\n ClearButton: React.ComponentType<any>;\n}\n\nexport type SlotRenderFunction = (\n oriNode: React.ReactNode,\n info: { components: ActionsComponents }\n) => React.ReactNode | false;\n\nexport interface XAdkSenderProps {\n clearBtnShow?: boolean;\n allowUpload?: boolean;\n loading?: boolean;\n disabled?: boolean; // 只读状态\n onClear?: () => void;\n onChange?: (value: string) => void;\n onSubmit?: (data: {\n text: string;\n files: ServerFile[];\n }) => void;\n onStop?: () => void;\n\n // 上传相关配置\n uploadRequest?: uploadRequestProps;\n maxFileSize?: number; // 最大文件大小(MB)\n allowedFileTypes?: string[]; // 允许的文件类型\n maxFiles?: number; // 最大文件数量\n\n // 文件状态回调\n onFilesChange?: (files: ServerFile[]) => void;\n\n // 插槽功能\n /** 后缀内容,默认展示操作按钮,设为 false 时不显示 */\n suffix?: React.ReactNode | false | SlotRenderFunction;\n /** 头部面板 */\n header?: React.ReactNode | false | SlotRenderFunction;\n /** 前缀内容 */\n prefix?: React.ReactNode | false | SlotRenderFunction;\n /** 底部内容 */\n footer?: React.ReactNode | false | SlotRenderFunction;\n}"],
4
+ "sourcesContent": ["// types/XAdkSender.ts\nimport React from \"react\";\n\ninterface uploadRequestProps {\n (options: {\n file: File;\n onProgress?: (e: { percent: number }) => void;\n onSuccess?: (response: any) => void;\n onError?: (error: Error) => void;\n }): Promise<void> | void;\n}\n\nexport interface ServerFile {\n fileName: string;\n fileId: number;\n tempUrl: string;\n type: string;\n mimeType: string;\n}\n\nexport interface LocalFile {\n id: string;\n uid: string;\n name: string;\n file: File;\n size: number;\n type: string;\n progress: number;\n status: \"pending\" | \"uploading\" | \"success\" | \"error\";\n // 服务器返回字段\n fileId?: number;\n tempUrl?: string;\n response?: any;\n errorMessage?: string; // 上传错误信息\n}\n\nexport type FileValidator = (\n file: File,\n context: { files: LocalFile[] },\n) => string | null;\n\nexport interface ActionsComponents {\n SendButton: React.ComponentType<any>;\n UploadButton: React.ComponentType<any>;\n ClearButton: React.ComponentType<any>;\n}\n\nexport type SlotRenderFunction = (\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n) => React.ReactNode | false;\n\n// 上传相关\nexport interface UploaderCoreProps {\n uploadRequest?: uploadRequestProps;\n\n maxFileSize?: number;\n allowedFileTypes?: string[];\n maxFiles?: number;\n\n validators?: FileValidator[]; // ⭐ 关键扩展点\n\n // 数据层回调(比 onFilesChange 更底层)\n onFilesChange?: (files: LocalFile[]) => void;\n onUploadSuccess?: (file: LocalFile) => void;\n onUploadError?: (file: LocalFile, error: Error) => void;\n}\n\n// UI 相关\nexport interface SenderUIProps {\n clearBtnShow?: boolean;\n allowUpload?: boolean;\n loading?: boolean;\n disabled?: boolean; // 只读状态\n onClear?: () => void;\n onChange?: (value: string) => void;\n onSubmit?: (data: { text: string; files: ServerFile[] }) => void;\n onStop?: () => void;\n\n // UI插槽功能\n /** 后缀内容,默认展示操作按钮,设为 false 时不显示 */\n suffix?: React.ReactNode | false | SlotRenderFunction;\n /** 头部面板 */\n header?: React.ReactNode | false | SlotRenderFunction;\n /** 前缀内容 */\n prefix?: React.ReactNode | false | SlotRenderFunction;\n /** 底部内容 */\n footer?: React.ReactNode | false | SlotRenderFunction;\n}\n\nexport type XAdkSenderProps = SenderUIProps & UploaderCoreProps;\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -5,5 +5,7 @@ export * from "./XAiSender";
5
5
  export * from "./XAiConversations";
6
6
  export * from "./XAdkProvider";
7
7
  export * from "./XAdkChatbot";
8
+ export * from "./XAdkSender";
8
9
  export * from "./XAiThoughtChain";
10
+ export * from "./FileGallery";
9
11
  export * from "./common";
@@ -23,7 +23,9 @@ __reExport(types_exports, require("./XAiSender"), module.exports);
23
23
  __reExport(types_exports, require("./XAiConversations"), module.exports);
24
24
  __reExport(types_exports, require("./XAdkProvider"), module.exports);
25
25
  __reExport(types_exports, require("./XAdkChatbot"), module.exports);
26
+ __reExport(types_exports, require("./XAdkSender"), module.exports);
26
27
  __reExport(types_exports, require("./XAiThoughtChain"), module.exports);
28
+ __reExport(types_exports, require("./FileGallery"), module.exports);
27
29
  __reExport(types_exports, require("./common"), module.exports);
28
30
  // Annotate the CommonJS export names for ESM import in node:
29
31
  0 && (module.exports = {
@@ -34,7 +36,9 @@ __reExport(types_exports, require("./common"), module.exports);
34
36
  ...require("./XAiConversations"),
35
37
  ...require("./XAdkProvider"),
36
38
  ...require("./XAdkChatbot"),
39
+ ...require("./XAdkSender"),
37
40
  ...require("./XAiThoughtChain"),
41
+ ...require("./FileGallery"),
38
42
  ...require("./common")
39
43
  });
40
44
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/types/index.ts"],
4
- "sourcesContent": ["export * from \"./XAiChatbot\";\nexport * from \"./XAiMessage\";\nexport * from \"./XAiProvider\";\nexport * from \"./XAiSender\";\nexport * from \"./XAiConversations\";\nexport * from \"./XAdkProvider\";\nexport * from \"./XAdkChatbot\";\nexport * from \"./XAiThoughtChain\";\nexport * from \"./common\";\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,yBAAd;AACA,0BAAc,yBADd;AAEA,0BAAc,0BAFd;AAGA,0BAAc,wBAHd;AAIA,0BAAc,+BAJd;AAKA,0BAAc,2BALd;AAMA,0BAAc,0BANd;AAOA,0BAAc,8BAPd;AAQA,0BAAc,qBARd;",
4
+ "sourcesContent": ["export * from \"./XAiChatbot\";\nexport * from \"./XAiMessage\";\nexport * from \"./XAiProvider\";\nexport * from \"./XAiSender\";\nexport * from \"./XAiConversations\";\nexport * from \"./XAdkProvider\";\nexport * from \"./XAdkChatbot\";\nexport * from \"./XAdkSender\";\nexport * from \"./XAiThoughtChain\";\nexport * from \"./FileGallery\";\nexport * from \"./common\";\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,yBAAd;AACA,0BAAc,yBADd;AAEA,0BAAc,0BAFd;AAGA,0BAAc,wBAHd;AAIA,0BAAc,+BAJd;AAKA,0BAAc,2BALd;AAMA,0BAAc,0BANd;AAOA,0BAAc,yBAPd;AAQA,0BAAc,8BARd;AASA,0BAAc,0BATd;AAUA,0BAAc,qBAVd;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,2 @@
1
+ import { LocalFile } from "../types";
2
+ export declare const getExt: (file: File | LocalFile) => string;
@@ -0,0 +1,33 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils/file.ts
20
+ var file_exports = {};
21
+ __export(file_exports, {
22
+ getExt: () => getExt
23
+ });
24
+ module.exports = __toCommonJS(file_exports);
25
+ var getExt = (file) => {
26
+ var _a;
27
+ return ((_a = file.name.split(".").pop()) == null ? void 0 : _a.toLowerCase()) || "";
28
+ };
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ getExt
32
+ });
33
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/file.ts"],
4
+ "sourcesContent": ["import { LocalFile } from \"@/types\";\n\n// 获取文件后缀\nexport const getExt = (file: File | LocalFile) => {\n return file.name.split(\".\").pop()?.toLowerCase() || \"\";\n};\n\n// export const sanitizeFileName = (name: string) => {\n// return name.replace(/[^a-zA-Z0-9.\\-_]/g, \"_\");\n// };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,IAAM,SAAS,CAAC,SAA2B;AAHlD;AAIE,WAAO,UAAK,KAAK,MAAM,GAAG,EAAE,IAAI,MAAzB,mBAA4B,kBAAiB;AACtD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { FileGalleryProps } from "../../types";
3
+ /**
4
+ * FileGallery - 通用文件展示组件
5
+ *
6
+ * 功能特性:
7
+ * - 📁 支持多种文件类型展示 (图片、音频、视频、文档等)
8
+ * - 🖼️ 图片支持预览和缩略图
9
+ * - 🎵 音频文件支持内联播放
10
+ * - 🎬 视频文件支持内联播放
11
+ * - 📊 显示文件大小、类型图标
12
+ * - 🗑️ 支持删除操作
13
+ * - 📤 支持上传进度显示
14
+ * - 🎨 支持左右对齐
15
+ *
16
+ * @example
17
+ * // XAdkSender 场景 - 可删除的本地文件
18
+ * <FileGallery
19
+ * files={localFiles}
20
+ * removable
21
+ * onRemove={handleRemove}
22
+ * align="left"
23
+ * />
24
+ *
25
+ * @example
26
+ * // XadkChatbot 场景 - 只读的远程文件
27
+ * <FileGallery
28
+ * files={remoteFiles}
29
+ * align="right"
30
+ * />
31
+ */
32
+ declare const FileGallery: React.FC<FileGalleryProps>;
33
+ export default FileGallery;
@@ -0,0 +1,439 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import React, { useState, useEffect } from "react";
3
+ import { Image, Tooltip, Progress } from "antd";
4
+ import { FileOutlined, FilePdfOutlined, FileWordOutlined, FileExcelOutlined, FilePptOutlined, FileImageOutlined, CloseOutlined, AudioOutlined, VideoCameraOutlined } from "@ant-design/icons";
5
+ import { useStyles } from "./styles";
6
+
7
+ // ==================== 工具函数 ====================
8
+
9
+ /**
10
+ * 获取文件名
11
+ */
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { jsxs as _jsxs } from "react/jsx-runtime";
14
+ var getFileName = function getFileName(file) {
15
+ return file.displayName || file.name || "";
16
+ };
17
+
18
+ /**
19
+ * 获取文件大小
20
+ */
21
+ var getFileSize = function getFileSize(file) {
22
+ return file.size || 0;
23
+ };
24
+
25
+ /**
26
+ * 获取文件 MIME 类型
27
+ */
28
+ var getMimeType = function getMimeType(file) {
29
+ return file.mimeType || file.type || "";
30
+ };
31
+
32
+ /**
33
+ * 获取文件 URL
34
+ */
35
+ var getFileUrl = function getFileUrl(file) {
36
+ var _file$response, _file$response2;
37
+ return file.fileUri || ((_file$response = file.response) === null || _file$response === void 0 ? void 0 : _file$response.fileUrl) || ((_file$response2 = file.response) === null || _file$response2 === void 0 ? void 0 : _file$response2.tempUrl) || file.tempUrl || "";
38
+ };
39
+
40
+ /**
41
+ * 获取文件唯一标识
42
+ */
43
+ var getFileId = function getFileId(file) {
44
+ return file.id || file.uid || "";
45
+ };
46
+
47
+ /**
48
+ * 判断是否是图片文件
49
+ */
50
+ var isImageFile = function isImageFile(file) {
51
+ var mimeType = getMimeType(file);
52
+ if (mimeType && mimeType.startsWith("image/")) return true;
53
+ var fileName = getFileName(file);
54
+ if (fileName && fileName.match(/\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i)) return true;
55
+ var url = getFileUrl(file);
56
+ if (url && url.match(/\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?.*)?$/i)) return true;
57
+ return false;
58
+ };
59
+
60
+ /**
61
+ * 判断是否是音频文件
62
+ */
63
+ var isAudioFile = function isAudioFile(file) {
64
+ var mimeType = getMimeType(file);
65
+ if (mimeType && mimeType.startsWith("audio/")) return true;
66
+ var fileName = getFileName(file);
67
+ return !!(fileName !== null && fileName !== void 0 && fileName.match(/\.(mp3|wav|m4a|aac|ogg|flac)$/i));
68
+ };
69
+
70
+ /**
71
+ * 判断是否是视频文件
72
+ */
73
+ var isVideoFile = function isVideoFile(file) {
74
+ var mimeType = getMimeType(file);
75
+ if (mimeType && mimeType.startsWith("video/")) return true;
76
+ var fileName = getFileName(file);
77
+ return !!(fileName !== null && fileName !== void 0 && fileName.match(/\.(mp4|mov|webm|mkv|avi)$/i));
78
+ };
79
+
80
+ /**
81
+ * 获取文件扩展名
82
+ */
83
+ var getFileExtension = function getFileExtension(filename) {
84
+ var ext = filename.split(".").pop();
85
+ return ext ? ext.toLowerCase() : "";
86
+ };
87
+
88
+ /**
89
+ * 获取文件图标和颜色
90
+ */
91
+ var getFileIcon = function getFileIcon(file) {
92
+ var ext = getFileExtension(getFileName(file));
93
+
94
+ // PDF
95
+ if (ext === "pdf") {
96
+ return {
97
+ icon: /*#__PURE__*/_jsx(FilePdfOutlined, {}),
98
+ color: "#ff4d4f"
99
+ };
100
+ }
101
+
102
+ // Word
103
+ if (["doc", "docx"].includes(ext)) {
104
+ return {
105
+ icon: /*#__PURE__*/_jsx(FileWordOutlined, {}),
106
+ color: "#1677ff"
107
+ };
108
+ }
109
+
110
+ // Excel
111
+ if (["xls", "xlsx", "csv"].includes(ext)) {
112
+ return {
113
+ icon: /*#__PURE__*/_jsx(FileExcelOutlined, {}),
114
+ color: "#22b35e"
115
+ };
116
+ }
117
+
118
+ // PPT
119
+ if (["ppt", "pptx"].includes(ext)) {
120
+ return {
121
+ icon: /*#__PURE__*/_jsx(FilePptOutlined, {}),
122
+ color: "#ff6e31"
123
+ };
124
+ }
125
+
126
+ // Audio
127
+ if (["mp3", "wav", "m4a", "aac", "ogg", "flac"].includes(ext)) {
128
+ return {
129
+ icon: /*#__PURE__*/_jsx(AudioOutlined, {}),
130
+ color: "#722ed1"
131
+ };
132
+ }
133
+
134
+ // Video
135
+ if (["mp4", "mov", "webm", "mkv", "avi"].includes(ext)) {
136
+ return {
137
+ icon: /*#__PURE__*/_jsx(VideoCameraOutlined, {}),
138
+ color: "#fa8c16"
139
+ };
140
+ }
141
+
142
+ // 图片
143
+ if (isImageFile(file)) {
144
+ return {
145
+ icon: /*#__PURE__*/_jsx(FileImageOutlined, {}),
146
+ color: "#8c8c8c"
147
+ };
148
+ }
149
+
150
+ // 默认
151
+ return {
152
+ icon: /*#__PURE__*/_jsx(FileOutlined, {}),
153
+ color: "#8c8c8c"
154
+ };
155
+ };
156
+
157
+ /**
158
+ * 格式化文件大小
159
+ */
160
+ var formatFileSize = function formatFileSize(bytes) {
161
+ if (bytes < 1024) return bytes + " B";
162
+ if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
163
+ return (bytes / (1024 * 1024)).toFixed(1) + " MB";
164
+ };
165
+ var styles = useStyles();
166
+
167
+ // ==================== 子组件 ====================
168
+
169
+ var FileItemComponent = function FileItemComponent(_ref) {
170
+ var file = _ref.file,
171
+ removable = _ref.removable,
172
+ onRemove = _ref.onRemove;
173
+ var _useState = useState(""),
174
+ _useState2 = _slicedToArray(_useState, 2),
175
+ objectUrl = _useState2[0],
176
+ setObjectUrl = _useState2[1];
177
+ useEffect(function () {
178
+ if (!file.file) return;
179
+ var url = URL.createObjectURL(file.file);
180
+ setObjectUrl(url);
181
+ return function () {
182
+ return URL.revokeObjectURL(url);
183
+ };
184
+ }, [file.file]);
185
+ var isImage = isImageFile(file);
186
+ var isAudio = isAudioFile(file);
187
+ var isVideo = isVideoFile(file);
188
+ var fileName = getFileName(file);
189
+ var fileSize = getFileSize(file);
190
+ var fileId = getFileId(file);
191
+ var url = getFileUrl(file) || objectUrl;
192
+
193
+ // 图片文件
194
+ if (isImage) {
195
+ return /*#__PURE__*/_jsxs("div", {
196
+ className: styles.fileCard,
197
+ children: [/*#__PURE__*/_jsxs("div", {
198
+ className: styles.imageThumbnail,
199
+ children: [/*#__PURE__*/_jsx(Image, {
200
+ src: url,
201
+ alt: fileName,
202
+ fallback: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mN8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==",
203
+ preview: {
204
+ src: url
205
+ }
206
+ }), file.status === "uploading" && /*#__PURE__*/_jsx("div", {
207
+ className: styles.imageOverlay,
208
+ children: /*#__PURE__*/_jsx(Progress, {
209
+ type: "circle",
210
+ percent: file.progress,
211
+ size: 30,
212
+ strokeColor: "#1677ff"
213
+ })
214
+ })]
215
+ }), /*#__PURE__*/_jsxs("div", {
216
+ className: styles.fileInfo,
217
+ children: [/*#__PURE__*/_jsx(Tooltip, {
218
+ title: fileName,
219
+ children: /*#__PURE__*/_jsx("div", {
220
+ className: styles.fileName,
221
+ children: fileName.length > 15 ? "".concat(fileName.substring(0, 15), "...") : fileName
222
+ })
223
+ }), /*#__PURE__*/_jsx("div", {
224
+ className: styles.fileSize,
225
+ children: formatFileSize(fileSize)
226
+ })]
227
+ }), removable && /*#__PURE__*/_jsx("button", {
228
+ className: styles.fileRemoveBtn,
229
+ onClick: function onClick() {
230
+ return onRemove(fileId);
231
+ },
232
+ disabled: file.status === "uploading",
233
+ "aria-label": "\u5220\u9664\u6587\u4EF6",
234
+ children: /*#__PURE__*/_jsx(CloseOutlined, {})
235
+ })]
236
+ });
237
+ }
238
+
239
+ // 音频文件
240
+ if (isAudio) {
241
+ return /*#__PURE__*/_jsxs("div", {
242
+ className: styles.fileCard,
243
+ children: [/*#__PURE__*/_jsx("div", {
244
+ className: styles.fileIcon,
245
+ style: {
246
+ color: "#722ed1"
247
+ },
248
+ children: /*#__PURE__*/_jsx(AudioOutlined, {})
249
+ }), /*#__PURE__*/_jsxs("div", {
250
+ className: styles.fileInfo,
251
+ children: [/*#__PURE__*/_jsx(Tooltip, {
252
+ title: fileName,
253
+ children: /*#__PURE__*/_jsx("div", {
254
+ className: styles.fileName,
255
+ children: fileName
256
+ })
257
+ }), /*#__PURE__*/_jsx("audio", {
258
+ src: url,
259
+ controls: true,
260
+ className: styles.mediaWrapper,
261
+ style: {
262
+ width: "100%",
263
+ height: 28
264
+ }
265
+ })]
266
+ }), removable && /*#__PURE__*/_jsx("button", {
267
+ className: styles.fileRemoveBtn,
268
+ onClick: function onClick() {
269
+ return onRemove(fileId);
270
+ },
271
+ disabled: file.status === "uploading",
272
+ "aria-label": "\u5220\u9664\u6587\u4EF6",
273
+ children: /*#__PURE__*/_jsx(CloseOutlined, {})
274
+ })]
275
+ });
276
+ }
277
+
278
+ // 视频文件
279
+ if (isVideo) {
280
+ return /*#__PURE__*/_jsxs("div", {
281
+ className: styles.fileCard,
282
+ children: [/*#__PURE__*/_jsx("div", {
283
+ className: styles.fileIcon,
284
+ style: {
285
+ color: "#fa8c16"
286
+ },
287
+ children: /*#__PURE__*/_jsx(VideoCameraOutlined, {})
288
+ }), /*#__PURE__*/_jsxs("div", {
289
+ className: styles.fileInfo,
290
+ children: [/*#__PURE__*/_jsx(Tooltip, {
291
+ title: fileName,
292
+ children: /*#__PURE__*/_jsx("div", {
293
+ className: styles.fileName,
294
+ children: fileName
295
+ })
296
+ }), /*#__PURE__*/_jsx("video", {
297
+ src: url,
298
+ controls: true,
299
+ className: styles.mediaWrapper,
300
+ style: {
301
+ width: "100%",
302
+ height: 40
303
+ }
304
+ })]
305
+ }), removable && /*#__PURE__*/_jsx("button", {
306
+ className: styles.fileRemoveBtn,
307
+ onClick: function onClick() {
308
+ return onRemove(fileId);
309
+ },
310
+ disabled: file.status === "uploading",
311
+ "aria-label": "\u5220\u9664\u6587\u4EF6",
312
+ children: /*#__PURE__*/_jsx(CloseOutlined, {})
313
+ })]
314
+ });
315
+ }
316
+
317
+ // 其他文件
318
+ var _getFileIcon = getFileIcon(file),
319
+ icon = _getFileIcon.icon,
320
+ color = _getFileIcon.color;
321
+ var isExternalUrl = url && url.startsWith("http");
322
+ return /*#__PURE__*/_jsxs("div", {
323
+ className: styles.fileCard,
324
+ children: [/*#__PURE__*/_jsx("div", {
325
+ className: styles.fileIcon,
326
+ style: {
327
+ color: color
328
+ },
329
+ children: icon
330
+ }), /*#__PURE__*/_jsxs("div", {
331
+ className: styles.fileInfo,
332
+ children: [isExternalUrl ? /*#__PURE__*/_jsx("a", {
333
+ href: url,
334
+ target: "_blank",
335
+ rel: "noopener noreferrer",
336
+ className: styles.fileLink,
337
+ children: /*#__PURE__*/_jsx(Tooltip, {
338
+ title: fileName,
339
+ children: /*#__PURE__*/_jsx("div", {
340
+ className: styles.fileName,
341
+ children: fileName.length > 15 ? "".concat(fileName.substring(0, 15), "...") : fileName
342
+ })
343
+ })
344
+ }) : /*#__PURE__*/_jsx(Tooltip, {
345
+ title: fileName,
346
+ children: /*#__PURE__*/_jsx("div", {
347
+ className: styles.fileName,
348
+ children: fileName.length > 15 ? "".concat(fileName.substring(0, 15), "...") : fileName
349
+ })
350
+ }), file.status === "uploading" ? /*#__PURE__*/_jsx(Progress, {
351
+ percent: file.progress,
352
+ size: "small",
353
+ showInfo: false,
354
+ strokeColor: "#1677ff",
355
+ className: styles.progress
356
+ }) : fileSize > 0 && /*#__PURE__*/_jsx("div", {
357
+ className: styles.fileSize,
358
+ children: formatFileSize(fileSize)
359
+ }), file.status === "error" && file.errorMessage && /*#__PURE__*/_jsx("div", {
360
+ style: {
361
+ fontSize: "11px",
362
+ color: "#ff4d4f",
363
+ marginTop: "2px"
364
+ },
365
+ children: file.errorMessage
366
+ })]
367
+ }), removable && /*#__PURE__*/_jsx("button", {
368
+ className: styles.fileRemoveBtn,
369
+ onClick: function onClick() {
370
+ return onRemove(fileId);
371
+ },
372
+ disabled: file.status === "uploading",
373
+ "aria-label": "\u5220\u9664\u6587\u4EF6",
374
+ children: /*#__PURE__*/_jsx(CloseOutlined, {})
375
+ })]
376
+ });
377
+ };
378
+
379
+ // ==================== 主组件 ====================
380
+
381
+ /**
382
+ * FileGallery - 通用文件展示组件
383
+ *
384
+ * 功能特性:
385
+ * - 📁 支持多种文件类型展示 (图片、音频、视频、文档等)
386
+ * - 🖼️ 图片支持预览和缩略图
387
+ * - 🎵 音频文件支持内联播放
388
+ * - 🎬 视频文件支持内联播放
389
+ * - 📊 显示文件大小、类型图标
390
+ * - 🗑️ 支持删除操作
391
+ * - 📤 支持上传进度显示
392
+ * - 🎨 支持左右对齐
393
+ *
394
+ * @example
395
+ * // XAdkSender 场景 - 可删除的本地文件
396
+ * <FileGallery
397
+ * files={localFiles}
398
+ * removable
399
+ * onRemove={handleRemove}
400
+ * align="left"
401
+ * />
402
+ *
403
+ * @example
404
+ * // XadkChatbot 场景 - 只读的远程文件
405
+ * <FileGallery
406
+ * files={remoteFiles}
407
+ * align="right"
408
+ * />
409
+ */
410
+ var FileGallery = function FileGallery(_ref2) {
411
+ var files = _ref2.files,
412
+ _ref2$align = _ref2.align,
413
+ align = _ref2$align === void 0 ? "left" : _ref2$align,
414
+ _ref2$removable = _ref2.removable,
415
+ removable = _ref2$removable === void 0 ? false : _ref2$removable,
416
+ _ref2$onRemove = _ref2.onRemove,
417
+ onRemove = _ref2$onRemove === void 0 ? function () {} : _ref2$onRemove,
418
+ className = _ref2.className,
419
+ style = _ref2.style;
420
+ if (!files || files.length === 0) return null;
421
+ return /*#__PURE__*/_jsx("div", {
422
+ className: "".concat(styles.container, " ").concat(align === "right" ? "align-right" : "", " ").concat(className || ""),
423
+ style: style,
424
+ children: /*#__PURE__*/_jsx("div", {
425
+ className: styles.fileList,
426
+ children: /*#__PURE__*/_jsx(Image.PreviewGroup, {
427
+ children: files.map(function (file, index) {
428
+ return /*#__PURE__*/_jsx(FileItemComponent, {
429
+ file: file,
430
+ removable: removable,
431
+ onRemove: onRemove
432
+ }, getFileId(file) || index);
433
+ })
434
+ })
435
+ })
436
+ });
437
+ };
438
+ export default FileGallery;
439
+ //# sourceMappingURL=index.js.map