@ai-group/chat-sdk 3.0.4 → 3.0.5

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 (42) hide show
  1. package/dist/cjs/components/FileGallery/FileGallery.stories.d.ts +6 -0
  2. package/dist/cjs/components/FileGallery/FileGallery.stories.js +143 -0
  3. package/dist/cjs/components/FileGallery/FileGallery.stories.js.map +7 -0
  4. package/dist/cjs/components/FileGallery/index.d.ts +13 -12
  5. package/dist/cjs/components/FileGallery/index.js +165 -159
  6. package/dist/cjs/components/FileGallery/index.js.map +2 -2
  7. package/dist/cjs/components/FileGallery/styles.js +5 -0
  8. package/dist/cjs/components/FileGallery/styles.js.map +2 -2
  9. package/dist/cjs/components/XAdkChatbot/XAdkChatbot.stories.js +18 -9
  10. package/dist/cjs/components/XAdkChatbot/XAdkChatbot.stories.js.map +2 -2
  11. package/dist/cjs/components/XAdkChatbot/index.js +11 -3
  12. package/dist/cjs/components/XAdkChatbot/index.js.map +2 -2
  13. package/dist/cjs/components/XAdkChatbot/styles.d.ts +1 -0
  14. package/dist/cjs/components/XAdkChatbot/styles.js +7 -0
  15. package/dist/cjs/components/XAdkChatbot/styles.js.map +2 -2
  16. package/dist/cjs/components/XAdkSender/index.js +9 -1
  17. package/dist/cjs/components/XAdkSender/index.js.map +2 -2
  18. package/dist/cjs/types/FileGallery.d.ts +1 -21
  19. package/dist/cjs/types/FileGallery.js.map +1 -1
  20. package/dist/cjs/types/XAdkSender.js.map +1 -1
  21. package/dist/esm/components/FileGallery/FileGallery.stories.d.ts +6 -0
  22. package/dist/esm/components/FileGallery/FileGallery.stories.js +48 -0
  23. package/dist/esm/components/FileGallery/FileGallery.stories.js.map +1 -0
  24. package/dist/esm/components/FileGallery/index.d.ts +13 -12
  25. package/dist/esm/components/FileGallery/index.js +48 -69
  26. package/dist/esm/components/FileGallery/index.js.map +1 -1
  27. package/dist/esm/components/FileGallery/styles.js +1 -1
  28. package/dist/esm/components/FileGallery/styles.js.map +1 -1
  29. package/dist/esm/components/XAdkChatbot/XAdkChatbot.stories.js +17 -13
  30. package/dist/esm/components/XAdkChatbot/XAdkChatbot.stories.js.map +1 -1
  31. package/dist/esm/components/XAdkChatbot/index.js +23 -6
  32. package/dist/esm/components/XAdkChatbot/index.js.map +1 -1
  33. package/dist/esm/components/XAdkChatbot/styles.d.ts +1 -0
  34. package/dist/esm/components/XAdkChatbot/styles.js +21 -20
  35. package/dist/esm/components/XAdkChatbot/styles.js.map +1 -1
  36. package/dist/esm/components/XAdkSender/index.js +14 -4
  37. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  38. package/dist/esm/types/FileGallery.d.ts +1 -21
  39. package/dist/esm/types/FileGallery.js.map +1 -1
  40. package/dist/esm/types/XAdkSender.js.map +1 -1
  41. package/dist/umd/chat-sdk.min.js +1 -1
  42. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/XAdkSender/index.tsx"],
4
- "sourcesContent": ["import React, { useState, useRef, useCallback } from \"react\";\nimport { Popconfirm, message, Tooltip, Input, Modal } from \"antd\";\nimport {\n ClearOutlined,\n LoadingOutlined,\n ArrowUpOutlined,\n PaperClipOutlined,\n} from \"@ant-design/icons\";\nimport {\n XAdkSenderProps,\n ServerFile,\n LocalFile,\n ActionsComponents,\n FileValidator,\n} from \"@/types\";\nimport { useStyles } from \"./styles\";\nimport FileGallery from \"../FileGallery\";\nimport { getExt } from \"@/utils/file\";\n\nconst XAdkSender: React.FC<XAdkSenderProps> = ({\n clearBtnShow = true,\n allowUpload = false,\n loading = false,\n disabled = false,\n uploadRequest = () => {},\n onClear,\n onChange,\n onSubmit,\n onStop,\n onFilesChange,\n onUploadSuccess,\n onUploadError,\n maxFileSize = 10,\n validators: customValidators = [],\n // allowedFileTypes = [\n // \"image/*\",\n // \"audio/*\",\n // \"video/*\",\n // \"application/pdf\",\n // \"text/plain\",\n // \".doc\",\n // \".docx\",\n // \".xls\",\n // \".xlsx\",\n // \".ppt\",\n // \".pptx\",\n // \"\",\n // ],\n allowedFileTypes = [],\n maxFiles = 5,\n suffix,\n header,\n prefix,\n footer,\n}) => {\n const styles = useStyles();\n const [value, setValue] = useState<string>(\"\");\n const [files, setFiles] = useState<LocalFile[]>([]);\n const [isDragOver, setIsDragOver] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // 生成唯一ID\n const generateId = () => {\n return Date.now().toString(36) + Math.random().toString(36).substr(2);\n };\n\n // 检查文件类型\n const checkFileType = (file: File): boolean => {\n if (allowedFileTypes?.length > 0) {\n const ext = getExt(file);\n\n return allowedFileTypes.some((type) => {\n // 1️⃣ MIME 校验\n if (type.includes(\"/\")) {\n if (type.endsWith(\"/*\")) {\n return file.type.startsWith(type.split(\"/\")[0]);\n }\n return file.type === type;\n }\n\n if (type.startsWith(\".\")) {\n return ext === type.slice(1);\n }\n\n return false;\n });\n }\n return true;\n };\n\n // 检查文件大小\n const checkFileSize = (file: File): boolean => {\n const maxSize = maxFileSize * 1024 * 1024;\n return file.size <= maxSize;\n };\n\n // 重复文件检测\n const isDuplicateFile = (file: File, files: LocalFile[]) => {\n return files.some((f) => f.name === file.name && f.size === file.size);\n };\n\n // 内置校验器集合\n const builtInValidators: FileValidator[] = [\n // 数量校验(修复批量 bug)\n (_file, { files }) => {\n if (files.length >= maxFiles) {\n return `最多只能上传 ${maxFiles} 个文件`;\n }\n return null;\n },\n\n // 大小校验\n (file) => {\n const maxSize = maxFileSize * 1024 * 1024;\n if (file.size > maxSize) {\n return `文件大小不能超过 ${maxFileSize}MB`;\n }\n return null;\n },\n\n // 类型校验\n (file) => {\n if (!checkFileType(file)) {\n return \"不支持的文件类型\";\n }\n return null;\n },\n\n // ⭐ 新增:去重校验\n (file, { files }) => {\n if (isDuplicateFile(file, files)) {\n return \"文件已存在\";\n }\n return null;\n },\n ];\n\n const allValidators = [...builtInValidators, ...customValidators];\n\n // 验证文件\n const validateFile = (file: File): { valid: boolean; message?: string } => {\n for (const validator of allValidators) {\n const error = validator(file, { files });\n if (error) {\n return { valid: false, message: error };\n }\n }\n return { valid: true };\n };\n\n // 处理文件选择\n const handleFileSelect = useCallback(\n (selectedFiles: File[]) => {\n const fileArray = Array.from(selectedFiles);\n\n if (files.length + fileArray.length > maxFiles) {\n message.error(`最多只能上传 ${maxFiles} 个文件`);\n return;\n }\n\n const validFiles: LocalFile[] = [];\n\n fileArray.forEach((file) => {\n const validation = validateFile(file);\n\n if (validation.valid) {\n validFiles.push({\n id: generateId(),\n uid: generateId(),\n name: file.name,\n size: file.size,\n type: file.type,\n file,\n progress: 0,\n status: \"pending\",\n response: null,\n });\n } else {\n message.error(validation.message);\n }\n });\n\n if (validFiles.length > 0) {\n setFiles((prev) => {\n const next = [...prev, ...validFiles];\n onFilesChange?.(next);\n return next;\n });\n uploadFiles(validFiles);\n }\n },\n [files, maxFiles, maxFileSize, allowedFileTypes],\n );\n\n // 上传文件\n const uploadFiles = async (fileList: LocalFile[]) => {\n for (const localFile of fileList) {\n // 开始上传\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id ? { ...f, status: \"uploading\" } : f,\n ),\n );\n\n try {\n await uploadRequest({\n file: localFile.file,\n onProgress: (e) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id ? { ...f, progress: e.percent } : f,\n ),\n );\n },\n onSuccess: (response) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"success\",\n progress: 100,\n response,\n }\n : f,\n ),\n );\n\n onUploadSuccess?.({\n ...localFile,\n status: \"success\",\n response,\n });\n },\n onError: (error) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"error\",\n errorMessage: error.message,\n }\n : f,\n ),\n );\n onUploadError?.(localFile, error);\n },\n });\n } catch (error) {\n console.error(\"上传处理错误:\", error);\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"error\",\n errorMessage:\n error instanceof Error ? error.message : \"上传处理失败\",\n }\n : f,\n ),\n );\n message.error(`${localFile.name} 上传失败`);\n }\n }\n };\n\n // 删除文件\n const handleRemoveFile = (id: string) => {\n setFiles((prev) => {\n const next = prev.filter((file) => file.id !== id);\n\n onFilesChange?.(next);\n\n return next;\n });\n };\n\n // 触发文件选择\n const triggerFileSelect = () => {\n if (fileInputRef.current) {\n fileInputRef.current.click();\n }\n };\n\n // 处理拖拽事件\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(true);\n }\n },\n [allowUpload],\n );\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(false);\n }\n },\n [allowUpload],\n );\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n\n if (\n allowUpload &&\n e.dataTransfer.files &&\n e.dataTransfer.files.length > 0\n ) {\n handleFileSelect(Array.from(e.dataTransfer.files));\n }\n },\n [allowUpload, handleFileSelect],\n );\n\n // 处理提交\n const handleSubmit = () => {\n if (!value.trim() && files.length === 0) {\n message.warning(\"请输入消息或选择文件\");\n return;\n }\n\n const successFiles = files.filter((file) => file.status === \"success\");\n const uploadingFiles = files.filter((file) => file.status === \"uploading\");\n\n if (uploadingFiles.length > 0) {\n Modal.confirm({\n title: \"文件上传中\",\n content: `还有 ${uploadingFiles.length} 个文件正在上传,是否继续发送?`,\n okText: \"发送已完成的\",\n cancelText: \"等待全部完成\",\n onOk: () => {\n const formattedFiles = formatFilesForServer(successFiles);\n if (onSubmit) {\n onSubmit({\n text: value,\n files: formattedFiles,\n });\n }\n\n setValue(\"\");\n setFiles((prev) => prev.filter((f) => f.status !== \"success\"));\n },\n onCancel: () => {\n message.info(\"请等待文件上传完成后再发送\");\n },\n });\n } else {\n const formattedFiles = formatFilesForServer(successFiles);\n\n if (onSubmit) {\n onSubmit({\n text: value,\n files: formattedFiles,\n });\n }\n\n setValue(\"\");\n setFiles((prev) => prev.filter((f) => f.status !== \"success\"));\n }\n };\n\n // 格式化文件列表为服务端格式\n const formatFilesForServer = (fileList: LocalFile[]): ServerFile[] => {\n return fileList\n .filter((file) => file.status === \"success\" && file.response?.data)\n .map((file) => {\n const responseData = file.response.data;\n\n return {\n fileName: file.name,\n fileId: responseData.fileId || responseData.id || 0,\n tempUrl: responseData.tempUrl || responseData.url || \"\",\n type: responseData.fileType || getExt(file),\n mimeType: file.type,\n };\n });\n };\n\n // 处理输入框变化\n const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value;\n setValue(newValue);\n onChange?.(newValue);\n };\n\n // 处理回车键\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n // 渲染文件列表 - 使用新的 FileGallery 组件\n const renderFileList = () => {\n if (files.length === 0) return null;\n\n return <FileGallery files={files} removable onRemove={handleRemoveFile} />;\n };\n\n const containerClass = `${styles.container} ${isDragOver ? \"drag-over\" : \"\"}`;\n const uploading = files.some((f) => f.status === \"uploading\");\n const isDisabled = disabled || uploading || loading;\n\n // 定义按钮组件\n const SendButton = (props: any) => (\n <Tooltip title={loading ? \"停止生成\" : \"发送消息\"}>\n <button\n className={`${styles.iconButton} ${styles.sendButton} ${loading ? \"stop\" : \"\"}`}\n onClick={loading ? onStop : handleSubmit}\n disabled={uploading || disabled}\n aria-label={loading ? \"停止生成\" : \"发送消息\"}\n {...props}\n >\n {loading ? <LoadingOutlined /> : <ArrowUpOutlined />}\n </button>\n </Tooltip>\n );\n\n const UploadButton = (props: any) => (\n <Tooltip title=\"上传文件\">\n <button\n className={`${styles.iconButton} ${styles.uploadButton}`}\n onClick={triggerFileSelect}\n disabled={isDisabled}\n aria-label=\"上传文件\"\n {...props}\n >\n <PaperClipOutlined />\n </button>\n </Tooltip>\n );\n\n const ClearButton = (props: any) => (\n <Popconfirm\n title=\"确定要清空聊天记录吗?\"\n onConfirm={onClear}\n placement=\"top\"\n okText=\"确定\"\n cancelText=\"取消\"\n disabled={isDisabled}\n >\n <button\n className={`${styles.iconButton} ${styles.clearButton}`}\n disabled={isDisabled}\n aria-label=\"清空聊天记录\"\n {...props}\n >\n <ClearOutlined />\n </button>\n </Popconfirm>\n );\n\n const actionsComponents: ActionsComponents = {\n SendButton,\n UploadButton,\n ClearButton,\n };\n\n // 渲染插槽内容\n const renderSlot = (\n slot:\n | React.ReactNode\n | false\n | ((\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n ) => React.ReactNode | false)\n | undefined,\n oriNode: React.ReactNode,\n ): React.ReactNode | null => {\n if (slot === false) return null;\n if (slot === undefined) return oriNode;\n if (typeof slot === \"function\") {\n const result = slot(oriNode, { components: actionsComponents });\n return result === false ? null : result;\n }\n return slot;\n };\n\n // 默认的后缀内容(操作按钮组)\n const defaultSuffix = (\n <div className={styles.buttonGroup}>\n {allowUpload && <UploadButton />}\n <SendButton />\n </div>\n );\n\n return (\n <div\n ref={containerRef}\n className={containerClass}\n onDragOver={allowUpload ? handleDragOver : undefined}\n onDragLeave={allowUpload ? handleDragLeave : undefined}\n onDrop={allowUpload ? handleDrop : undefined}\n >\n {/* 头部插槽 */}\n {renderSlot(header, false)}\n\n {allowUpload && files.length > 0 && renderFileList()}\n\n {/* 隐藏的原生 file input */}\n {allowUpload && (\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n accept={allowedFileTypes.join(\",\")}\n style={{ display: \"none\" }}\n onChange={(e) => {\n if (e.target.files) {\n handleFileSelect(Array.from(e.target.files));\n e.target.value = \"\";\n }\n }}\n />\n )}\n\n <div className={styles.mainArea}>\n <div className={styles.senderWrap}>\n {/* 清除按钮 */}\n {clearBtnShow && <ClearButton />}\n\n <div className={styles.inputAndButtons}>\n {/* 前缀插槽 */}\n {renderSlot(prefix, false)}\n\n <div className={styles.textAreaWrapper}>\n <Input.TextArea\n className={styles.textArea}\n value={value}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n placeholder=\"请输入消息...\"\n disabled={isDisabled}\n autoSize={{ minRows: 1, maxRows: 4 }}\n style={{\n border: \"none\",\n boxShadow: \"none\",\n outline: \"none\",\n padding: 0,\n }}\n />\n </div>\n\n {/* 后缀插槽(默认显示操作按钮) */}\n {renderSlot(suffix, defaultSuffix)}\n </div>\n </div>\n\n {/* 底部插槽(默认显示提示文字) */}\n {renderSlot(\n footer,\n <div className={styles.tip}>\n 内容由AI生成,无法确保真实准确,仅供参考\n </div>,\n )}\n </div>\n </div>\n );\n};\n\nexport default XAdkSender;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqD;AACrD,kBAA2D;AAC3D,mBAKO;AAQP,oBAA0B;AAC1B,yBAAwB;AACxB,kBAAuB;AAyYZ;AAvYX,IAAM,aAAwC,CAAC;AAAA,EAC7C,eAAe;AAAA,EACf,cAAc;AAAA,EACd,UAAU;AAAA,EACV,WAAW;AAAA,EACX,gBAAgB,MAAM;AAAA,EAAC;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,YAAY,mBAAmB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAehC,mBAAmB,CAAC;AAAA,EACpB,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,aAAS,yBAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAiB,EAAE;AAC7C,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAsB,CAAC,CAAC;AAClD,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAClD,QAAM,mBAAe,qBAAuB,IAAI;AAChD,QAAM,mBAAe,qBAAyB,IAAI;AAGlD,QAAM,aAAa,MAAM;AACvB,WAAO,KAAK,IAAI,EAAE,SAAS,EAAE,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC;AAAA,EACtE;AAGA,QAAM,gBAAgB,CAAC,SAAwB;AAC7C,SAAI,qDAAkB,UAAS,GAAG;AAChC,YAAM,UAAM,oBAAO,IAAI;AAEvB,aAAO,iBAAiB,KAAK,CAAC,SAAS;AAErC,YAAI,KAAK,SAAS,GAAG,GAAG;AACtB,cAAI,KAAK,SAAS,IAAI,GAAG;AACvB,mBAAO,KAAK,KAAK,WAAW,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,UAChD;AACA,iBAAO,KAAK,SAAS;AAAA,QACvB;AAEA,YAAI,KAAK,WAAW,GAAG,GAAG;AACxB,iBAAO,QAAQ,KAAK,MAAM,CAAC;AAAA,QAC7B;AAEA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAGA,QAAM,gBAAgB,CAAC,SAAwB;AAC7C,UAAM,UAAU,cAAc,OAAO;AACrC,WAAO,KAAK,QAAQ;AAAA,EACtB;AAGA,QAAM,kBAAkB,CAAC,MAAYA,WAAuB;AAC1D,WAAOA,OAAM,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK,QAAQ,EAAE,SAAS,KAAK,IAAI;AAAA,EACvE;AAGA,QAAM,oBAAqC;AAAA;AAAA,IAEzC,CAAC,OAAO,EAAE,OAAAA,OAAM,MAAM;AACpB,UAAIA,OAAM,UAAU,UAAU;AAC5B,eAAO,UAAU;AAAA,MACnB;AACA,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,CAAC,SAAS;AACR,YAAM,UAAU,cAAc,OAAO;AACrC,UAAI,KAAK,OAAO,SAAS;AACvB,eAAO,YAAY;AAAA,MACrB;AACA,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,CAAC,SAAS;AACR,UAAI,CAAC,cAAc,IAAI,GAAG;AACxB,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA;AAAA,IAGA,CAAC,MAAM,EAAE,OAAAA,OAAM,MAAM;AACnB,UAAI,gBAAgB,MAAMA,MAAK,GAAG;AAChC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,GAAG,mBAAmB,GAAG,gBAAgB;AAGhE,QAAM,eAAe,CAAC,SAAqD;AACzE,eAAW,aAAa,eAAe;AACrC,YAAM,QAAQ,UAAU,MAAM,EAAE,MAAM,CAAC;AACvC,UAAI,OAAO;AACT,eAAO,EAAE,OAAO,OAAO,SAAS,MAAM;AAAA,MACxC;AAAA,IACF;AACA,WAAO,EAAE,OAAO,KAAK;AAAA,EACvB;AAGA,QAAM,uBAAmB;AAAA,IACvB,CAAC,kBAA0B;AACzB,YAAM,YAAY,MAAM,KAAK,aAAa;AAE1C,UAAI,MAAM,SAAS,UAAU,SAAS,UAAU;AAC9C,4BAAQ,MAAM,UAAU,cAAc;AACtC;AAAA,MACF;AAEA,YAAM,aAA0B,CAAC;AAEjC,gBAAU,QAAQ,CAAC,SAAS;AAC1B,cAAM,aAAa,aAAa,IAAI;AAEpC,YAAI,WAAW,OAAO;AACpB,qBAAW,KAAK;AAAA,YACd,IAAI,WAAW;AAAA,YACf,KAAK,WAAW;AAAA,YAChB,MAAM,KAAK;AAAA,YACX,MAAM,KAAK;AAAA,YACX,MAAM,KAAK;AAAA,YACX;AAAA,YACA,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,UAAU;AAAA,UACZ,CAAC;AAAA,QACH,OAAO;AACL,8BAAQ,MAAM,WAAW,OAAO;AAAA,QAClC;AAAA,MACF,CAAC;AAED,UAAI,WAAW,SAAS,GAAG;AACzB,iBAAS,CAAC,SAAS;AACjB,gBAAM,OAAO,CAAC,GAAG,MAAM,GAAG,UAAU;AACpC,yDAAgB;AAChB,iBAAO;AAAA,QACT,CAAC;AACD,oBAAY,UAAU;AAAA,MACxB;AAAA,IACF;AAAA,IACA,CAAC,OAAO,UAAU,aAAa,gBAAgB;AAAA,EACjD;AAGA,QAAM,cAAc,OAAO,aAA0B;AACnD,eAAW,aAAa,UAAU;AAEhC;AAAA,QAAS,CAAC,SACR,KAAK;AAAA,UAAI,CAAC,MACR,EAAE,OAAO,UAAU,KAAK,EAAE,GAAG,GAAG,QAAQ,YAAY,IAAI;AAAA,QAC1D;AAAA,MACF;AAEA,UAAI;AACF,cAAM,cAAc;AAAA,UAClB,MAAM,UAAU;AAAA,UAChB,YAAY,CAAC,MAAM;AACjB;AAAA,cAAS,CAAC,SACR,KAAK;AAAA,gBAAI,CAAC,MACR,EAAE,OAAO,UAAU,KAAK,EAAE,GAAG,GAAG,UAAU,EAAE,QAAQ,IAAI;AAAA,cAC1D;AAAA,YACF;AAAA,UACF;AAAA,UACA,WAAW,CAAC,aAAa;AACvB;AAAA,cAAS,CAAC,SACR,KAAK;AAAA,gBAAI,CAAC,MACR,EAAE,OAAO,UAAU,KACf;AAAA,kBACE,GAAG;AAAA,kBACH,QAAQ;AAAA,kBACR,UAAU;AAAA,kBACV;AAAA,gBACF,IACA;AAAA,cACN;AAAA,YACF;AAEA,+DAAkB;AAAA,cAChB,GAAG;AAAA,cACH,QAAQ;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,UACA,SAAS,CAAC,UAAU;AAClB;AAAA,cAAS,CAAC,SACR,KAAK;AAAA,gBAAI,CAAC,MACR,EAAE,OAAO,UAAU,KACf;AAAA,kBACE,GAAG;AAAA,kBACH,QAAQ;AAAA,kBACR,cAAc,MAAM;AAAA,gBACtB,IACA;AAAA,cACN;AAAA,YACF;AACA,2DAAgB,WAAW;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH,SAAS,OAAP;AACA,gBAAQ,MAAM,WAAW,KAAK;AAC9B;AAAA,UAAS,CAAC,SACR,KAAK;AAAA,YAAI,CAAC,MACR,EAAE,OAAO,UAAU,KACf;AAAA,cACE,GAAG;AAAA,cACH,QAAQ;AAAA,cACR,cACE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,YAC7C,IACA;AAAA,UACN;AAAA,QACF;AACA,4BAAQ,MAAM,GAAG,UAAU,WAAW;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAGA,QAAM,mBAAmB,CAAC,OAAe;AACvC,aAAS,CAAC,SAAS;AACjB,YAAM,OAAO,KAAK,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE;AAEjD,qDAAgB;AAEhB,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAGA,QAAM,oBAAoB,MAAM;AAC9B,QAAI,aAAa,SAAS;AACxB,mBAAa,QAAQ,MAAM;AAAA,IAC7B;AAAA,EACF;AAGA,QAAM,qBAAiB;AAAA,IACrB,CAAC,MAAuB;AACtB,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,UAAI,aAAa;AACf,sBAAc,IAAI;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,sBAAkB;AAAA,IACtB,CAAC,MAAuB;AACtB,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,UAAI,aAAa;AACf,sBAAc,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,iBAAa;AAAA,IACjB,CAAC,MAAuB;AACtB,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,oBAAc,KAAK;AAEnB,UACE,eACA,EAAE,aAAa,SACf,EAAE,aAAa,MAAM,SAAS,GAC9B;AACA,yBAAiB,MAAM,KAAK,EAAE,aAAa,KAAK,CAAC;AAAA,MACnD;AAAA,IACF;AAAA,IACA,CAAC,aAAa,gBAAgB;AAAA,EAChC;AAGA,QAAM,eAAe,MAAM;AACzB,QAAI,CAAC,MAAM,KAAK,KAAK,MAAM,WAAW,GAAG;AACvC,0BAAQ,QAAQ,YAAY;AAC5B;AAAA,IACF;AAEA,UAAM,eAAe,MAAM,OAAO,CAAC,SAAS,KAAK,WAAW,SAAS;AACrE,UAAM,iBAAiB,MAAM,OAAO,CAAC,SAAS,KAAK,WAAW,WAAW;AAEzE,QAAI,eAAe,SAAS,GAAG;AAC7B,wBAAM,QAAQ;AAAA,QACZ,OAAO;AAAA,QACP,SAAS,MAAM,eAAe;AAAA,QAC9B,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,MAAM,MAAM;AACV,gBAAM,iBAAiB,qBAAqB,YAAY;AACxD,cAAI,UAAU;AACZ,qBAAS;AAAA,cACP,MAAM;AAAA,cACN,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAEA,mBAAS,EAAE;AACX,mBAAS,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AAAA,QAC/D;AAAA,QACA,UAAU,MAAM;AACd,8BAAQ,KAAK,eAAe;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,YAAM,iBAAiB,qBAAqB,YAAY;AAExD,UAAI,UAAU;AACZ,iBAAS;AAAA,UACP,MAAM;AAAA,UACN,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAEA,eAAS,EAAE;AACX,eAAS,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AAAA,IAC/D;AAAA,EACF;AAGA,QAAM,uBAAuB,CAAC,aAAwC;AACpE,WAAO,SACJ,OAAO,CAAC,SAAM;AAzXrB;AAyXwB,kBAAK,WAAW,eAAa,UAAK,aAAL,mBAAe;AAAA,KAAI,EACjE,IAAI,CAAC,SAAS;AACb,YAAM,eAAe,KAAK,SAAS;AAEnC,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,QAAQ,aAAa,UAAU,aAAa,MAAM;AAAA,QAClD,SAAS,aAAa,WAAW,aAAa,OAAO;AAAA,QACrD,MAAM,aAAa,gBAAY,oBAAO,IAAI;AAAA,QAC1C,UAAU,KAAK;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACL;AAGA,QAAM,oBAAoB,CAAC,MAA8C;AACvE,UAAM,WAAW,EAAE,OAAO;AAC1B,aAAS,QAAQ;AACjB,yCAAW;AAAA,EACb;AAGA,QAAM,gBAAgB,CAAC,MAAgD;AACrE,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,QAAE,eAAe;AACjB,mBAAa;AAAA,IACf;AAAA,EACF;AAGA,QAAM,iBAAiB,MAAM;AAC3B,QAAI,MAAM,WAAW;AAAG,aAAO;AAE/B,WAAO,4CAAC,mBAAAC,SAAA,EAAY,OAAc,WAAS,MAAC,UAAU,kBAAkB;AAAA,EAC1E;AAEA,QAAM,iBAAiB,GAAG,OAAO,aAAa,aAAa,cAAc;AACzE,QAAM,YAAY,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,WAAW;AAC5D,QAAM,aAAa,YAAY,aAAa;AAG5C,QAAM,aAAa,CAAC,UAClB,4CAAC,uBAAQ,OAAO,UAAU,SAAS,QACjC;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,OAAO,cAAc,OAAO,cAAc,UAAU,SAAS;AAAA,MAC3E,SAAS,UAAU,SAAS;AAAA,MAC5B,UAAU,aAAa;AAAA,MACvB,cAAY,UAAU,SAAS;AAAA,MAC9B,GAAG;AAAA,MAEH,oBAAU,4CAAC,gCAAgB,IAAK,4CAAC,gCAAgB;AAAA;AAAA,EACpD,GACF;AAGF,QAAM,eAAe,CAAC,UACpB,4CAAC,uBAAQ,OAAM,QACb;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,OAAO,cAAc,OAAO;AAAA,MAC1C,SAAS;AAAA,MACT,UAAU;AAAA,MACV,cAAW;AAAA,MACV,GAAG;AAAA,MAEJ,sDAAC,kCAAkB;AAAA;AAAA,EACrB,GACF;AAGF,QAAM,cAAc,CAAC,UACnB;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,WAAW;AAAA,MACX,WAAU;AAAA,MACV,QAAO;AAAA,MACP,YAAW;AAAA,MACX,UAAU;AAAA,MAEV;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,GAAG,OAAO,cAAc,OAAO;AAAA,UAC1C,UAAU;AAAA,UACV,cAAW;AAAA,UACV,GAAG;AAAA,UAEJ,sDAAC,8BAAc;AAAA;AAAA,MACjB;AAAA;AAAA,EACF;AAGF,QAAM,oBAAuC;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,QAAM,aAAa,CACjB,MAQA,YAC2B;AAC3B,QAAI,SAAS;AAAO,aAAO;AAC3B,QAAI,SAAS;AAAW,aAAO;AAC/B,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,SAAS,KAAK,SAAS,EAAE,YAAY,kBAAkB,CAAC;AAC9D,aAAO,WAAW,QAAQ,OAAO;AAAA,IACnC;AACA,WAAO;AAAA,EACT;AAGA,QAAM,gBACJ,6CAAC,SAAI,WAAW,OAAO,aACpB;AAAA,mBAAe,4CAAC,gBAAa;AAAA,IAC9B,4CAAC,cAAW;AAAA,KACd;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW;AAAA,MACX,YAAY,cAAc,iBAAiB;AAAA,MAC3C,aAAa,cAAc,kBAAkB;AAAA,MAC7C,QAAQ,cAAc,aAAa;AAAA,MAGlC;AAAA,mBAAW,QAAQ,KAAK;AAAA,QAExB,eAAe,MAAM,SAAS,KAAK,eAAe;AAAA,QAGlD,eACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,UAAQ;AAAA,YACR,QAAQ,iBAAiB,KAAK,GAAG;AAAA,YACjC,OAAO,EAAE,SAAS,OAAO;AAAA,YACzB,UAAU,CAAC,MAAM;AACf,kBAAI,EAAE,OAAO,OAAO;AAClB,iCAAiB,MAAM,KAAK,EAAE,OAAO,KAAK,CAAC;AAC3C,kBAAE,OAAO,QAAQ;AAAA,cACnB;AAAA,YACF;AAAA;AAAA,QACF;AAAA,QAGF,6CAAC,SAAI,WAAW,OAAO,UACrB;AAAA,uDAAC,SAAI,WAAW,OAAO,YAEpB;AAAA,4BAAgB,4CAAC,eAAY;AAAA,YAE9B,6CAAC,SAAI,WAAW,OAAO,iBAEpB;AAAA,yBAAW,QAAQ,KAAK;AAAA,cAEzB,4CAAC,SAAI,WAAW,OAAO,iBACrB;AAAA,gBAAC,kBAAM;AAAA,gBAAN;AAAA,kBACC,WAAW,OAAO;AAAA,kBAClB;AAAA,kBACA,UAAU;AAAA,kBACV,WAAW;AAAA,kBACX,aAAY;AAAA,kBACZ,UAAU;AAAA,kBACV,UAAU,EAAE,SAAS,GAAG,SAAS,EAAE;AAAA,kBACnC,OAAO;AAAA,oBACL,QAAQ;AAAA,oBACR,WAAW;AAAA,oBACX,SAAS;AAAA,oBACT,SAAS;AAAA,kBACX;AAAA;AAAA,cACF,GACF;AAAA,cAGC,WAAW,QAAQ,aAAa;AAAA,eACnC;AAAA,aACF;AAAA,UAGC;AAAA,YACC;AAAA,YACA,4CAAC,SAAI,WAAW,OAAO,KAAK,mCAE5B;AAAA,UACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,qBAAQ;",
4
+ "sourcesContent": ["import React, { useState, useRef, useCallback } from \"react\";\nimport { Popconfirm, message, Tooltip, Input, Modal } from \"antd\";\nimport {\n ClearOutlined,\n LoadingOutlined,\n ArrowUpOutlined,\n PaperClipOutlined,\n} from \"@ant-design/icons\";\nimport {\n XAdkSenderProps,\n ServerFile,\n LocalFile,\n ActionsComponents,\n FileValidator,\n} from \"@/types\";\nimport { useStyles } from \"./styles\";\nimport FileGallery from \"../FileGallery\";\nimport { getExt } from \"@/utils/file\";\n\nconst XAdkSender: React.FC<XAdkSenderProps> = ({\n clearBtnShow = true,\n allowUpload = false,\n loading = false,\n disabled = false,\n uploadRequest = () => {},\n onClear,\n onChange,\n onSubmit,\n onStop,\n onFilesChange,\n onUploadSuccess,\n onUploadError,\n maxFileSize = 10,\n validators: customValidators = [],\n // allowedFileTypes = [\n // \"image/*\",\n // \"audio/*\",\n // \"video/*\",\n // \"application/pdf\",\n // \"text/plain\",\n // \".doc\",\n // \".docx\",\n // \".xls\",\n // \".xlsx\",\n // \".ppt\",\n // \".pptx\",\n // \"\",\n // ],\n allowedFileTypes = [],\n maxFiles = 5,\n suffix,\n header,\n prefix,\n footer,\n}) => {\n const styles = useStyles();\n const [value, setValue] = useState<string>(\"\");\n const [files, setFiles] = useState<LocalFile[]>([]);\n const [isDragOver, setIsDragOver] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // 生成唯一ID\n const generateId = () => {\n return Date.now().toString(36) + Math.random().toString(36).substr(2);\n };\n\n // 检查文件类型\n const checkFileType = (file: File): boolean => {\n if (allowedFileTypes?.length > 0) {\n const ext = getExt(file);\n\n return allowedFileTypes.some((type) => {\n // 1️⃣ MIME 校验\n if (type.includes(\"/\")) {\n if (type.endsWith(\"/*\")) {\n return file.type.startsWith(type.split(\"/\")[0]);\n }\n return file.type === type;\n }\n\n if (type.startsWith(\".\")) {\n return ext === type.slice(1);\n }\n\n return false;\n });\n }\n return true;\n };\n\n // 检查文件大小\n const checkFileSize = (file: File): boolean => {\n const maxSize = maxFileSize * 1024 * 1024;\n return file.size <= maxSize;\n };\n\n // 重复文件检测\n const isDuplicateFile = (file: File, files: LocalFile[]) => {\n return files.some((f) => f.name === file.name && f.size === file.size);\n };\n\n // 内置校验器集合\n const builtInValidators: FileValidator[] = [\n // 数量校验(修复批量 bug)\n (_file, { files }) => {\n if (files.length >= maxFiles) {\n return `最多只能上传 ${maxFiles} 个文件`;\n }\n return null;\n },\n\n // 大小校验\n (file) => {\n const maxSize = maxFileSize * 1024 * 1024;\n if (file.size > maxSize) {\n return `文件大小不能超过 ${maxFileSize}MB`;\n }\n return null;\n },\n\n // 类型校验\n (file) => {\n if (!checkFileType(file)) {\n return \"不支持的文件类型\";\n }\n return null;\n },\n\n // ⭐ 新增:去重校验\n (file, { files }) => {\n if (isDuplicateFile(file, files)) {\n return \"文件已存在\";\n }\n return null;\n },\n ];\n\n const allValidators = [...builtInValidators, ...customValidators];\n\n // 验证文件\n const validateFile = (file: File): { valid: boolean; message?: string } => {\n for (const validator of allValidators) {\n const error = validator(file, { files });\n if (error) {\n return { valid: false, message: error };\n }\n }\n return { valid: true };\n };\n\n // 处理文件选择\n const handleFileSelect = useCallback(\n (selectedFiles: File[]) => {\n const fileArray = Array.from(selectedFiles);\n\n if (files.length + fileArray.length > maxFiles) {\n message.error(`最多只能上传 ${maxFiles} 个文件`);\n return;\n }\n\n const validFiles: LocalFile[] = [];\n\n fileArray.forEach((file) => {\n const validation = validateFile(file);\n\n if (validation.valid) {\n validFiles.push({\n id: generateId(),\n uid: generateId(),\n name: file.name,\n size: file.size,\n type: file.type,\n file,\n progress: 0,\n status: \"pending\",\n response: null,\n });\n } else {\n message.error(validation.message);\n }\n });\n\n if (validFiles.length > 0) {\n setFiles((prev) => {\n const next = [...prev, ...validFiles];\n onFilesChange?.(next);\n return next;\n });\n uploadFiles(validFiles);\n }\n },\n [files, maxFiles, maxFileSize, allowedFileTypes],\n );\n\n // 上传文件\n const uploadFiles = async (fileList: LocalFile[]) => {\n for (const localFile of fileList) {\n // 开始上传\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id ? { ...f, status: \"uploading\" } : f,\n ),\n );\n\n try {\n await uploadRequest({\n file: localFile.file,\n onProgress: (e) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id ? { ...f, progress: e.percent } : f,\n ),\n );\n },\n onSuccess: (response) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"success\",\n progress: 100,\n response,\n }\n : f,\n ),\n );\n\n onUploadSuccess?.({\n ...localFile,\n status: \"success\",\n response,\n });\n },\n onError: (error) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"error\",\n errorMessage: error.message,\n }\n : f,\n ),\n );\n onUploadError?.(localFile, error);\n },\n });\n } catch (error) {\n console.error(\"上传处理错误:\", error);\n setFiles((prev) =>\n prev.map((f) =>\n f.id === localFile.id\n ? {\n ...f,\n status: \"error\",\n errorMessage:\n error instanceof Error ? error.message : \"上传处理失败\",\n }\n : f,\n ),\n );\n message.error(`${localFile.name} 上传失败`);\n }\n }\n };\n\n // 删除文件\n const handleRemoveFile = (id: string) => {\n setFiles((prev) => {\n const next = prev.filter((file) => file.id !== id);\n\n onFilesChange?.(next);\n\n return next;\n });\n };\n\n // 触发文件选择\n const triggerFileSelect = () => {\n if (fileInputRef.current) {\n fileInputRef.current.click();\n }\n };\n\n // 处理拖拽事件\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(true);\n }\n },\n [allowUpload],\n );\n\n const handleDragLeave = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (allowUpload) {\n setIsDragOver(false);\n }\n },\n [allowUpload],\n );\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n\n if (\n allowUpload &&\n e.dataTransfer.files &&\n e.dataTransfer.files.length > 0\n ) {\n handleFileSelect(Array.from(e.dataTransfer.files));\n }\n },\n [allowUpload, handleFileSelect],\n );\n\n // 处理提交\n const handleSubmit = () => {\n if (!value.trim() && files.length === 0) {\n message.warning(\"请输入消息或选择文件\");\n return;\n }\n\n const successFiles = files.filter((file) => file.status === \"success\");\n const uploadingFiles = files.filter((file) => file.status === \"uploading\");\n\n if (uploadingFiles.length > 0) {\n Modal.confirm({\n title: \"文件上传中\",\n content: `还有 ${uploadingFiles.length} 个文件正在上传,是否继续发送?`,\n okText: \"发送已完成的\",\n cancelText: \"等待全部完成\",\n onOk: () => {\n const formattedFiles = formatFilesForServer(successFiles);\n if (onSubmit) {\n onSubmit({\n text: value,\n files: formattedFiles,\n });\n }\n\n setValue(\"\");\n setFiles((prev) => prev.filter((f) => f.status !== \"success\"));\n },\n onCancel: () => {\n message.info(\"请等待文件上传完成后再发送\");\n },\n });\n } else {\n const formattedFiles = formatFilesForServer(successFiles);\n\n if (onSubmit) {\n onSubmit({\n text: value,\n files: formattedFiles,\n });\n }\n\n setValue(\"\");\n setFiles((prev) => prev.filter((f) => f.status !== \"success\"));\n }\n };\n\n // 格式化文件列表为服务端格式\n const formatFilesForServer = (fileList: LocalFile[]): ServerFile[] => {\n return fileList\n .filter((file) => file.status === \"success\" && file.response?.data)\n .map((file) => {\n const responseData = file.response.data;\n\n return {\n fileName: file.name,\n fileId: responseData.fileId || responseData.id || 0,\n tempUrl: responseData.tempUrl || responseData.url || \"\",\n type: responseData.fileType || getExt(file),\n mimeType: file.type,\n };\n });\n };\n\n // 处理输入框变化\n const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value;\n setValue(newValue);\n onChange?.(newValue);\n };\n\n // 处理回车键\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n // 渲染文件列表 - 使用新的 FileGallery 组件\n const renderFileList = () => {\n if (files.length === 0) return null;\n\n return (\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"8px\", padding: \"12px 0\" }}>\n {files.map((file) => (\n <FileGallery\n key={file.id}\n file={file}\n removable\n onRemove={handleRemoveFile}\n />\n ))}\n </div>\n );\n };\n\n const containerClass = `${styles.container} ${isDragOver ? \"drag-over\" : \"\"}`;\n const uploading = files.some((f) => f.status === \"uploading\");\n const isDisabled = disabled || uploading || loading;\n\n // 定义按钮组件\n const SendButton = (props: any) => (\n <Tooltip title={loading ? \"停止生成\" : \"发送消息\"}>\n <button\n className={`${styles.iconButton} ${styles.sendButton} ${loading ? \"stop\" : \"\"}`}\n onClick={loading ? onStop : handleSubmit}\n disabled={uploading || disabled}\n aria-label={loading ? \"停止生成\" : \"发送消息\"}\n {...props}\n >\n {loading ? <LoadingOutlined /> : <ArrowUpOutlined />}\n </button>\n </Tooltip>\n );\n\n const UploadButton = (props: any) => (\n <Tooltip title=\"上传文件\">\n <button\n className={`${styles.iconButton} ${styles.uploadButton}`}\n onClick={triggerFileSelect}\n disabled={isDisabled}\n aria-label=\"上传文件\"\n {...props}\n >\n <PaperClipOutlined />\n </button>\n </Tooltip>\n );\n\n const ClearButton = (props: any) => (\n <Popconfirm\n title=\"确定要清空聊天记录吗?\"\n onConfirm={onClear}\n placement=\"top\"\n okText=\"确定\"\n cancelText=\"取消\"\n disabled={isDisabled}\n >\n <button\n className={`${styles.iconButton} ${styles.clearButton}`}\n disabled={isDisabled}\n aria-label=\"清空聊天记录\"\n {...props}\n >\n <ClearOutlined />\n </button>\n </Popconfirm>\n );\n\n const actionsComponents: ActionsComponents = {\n SendButton,\n UploadButton,\n ClearButton,\n };\n\n // 渲染插槽内容\n const renderSlot = (\n slot:\n | React.ReactNode\n | false\n | ((\n oriNode: React.ReactNode,\n info: { components: ActionsComponents },\n ) => React.ReactNode | false)\n | undefined,\n oriNode: React.ReactNode,\n ): React.ReactNode | null => {\n if (slot === false) return null;\n if (slot === undefined) return oriNode;\n if (typeof slot === \"function\") {\n const result = slot(oriNode, { components: actionsComponents });\n return result === false ? null : result;\n }\n return slot;\n };\n\n // 默认的后缀内容(操作按钮组)\n const defaultSuffix = (\n <div className={styles.buttonGroup}>\n {allowUpload && <UploadButton />}\n <SendButton />\n </div>\n );\n\n return (\n <div\n ref={containerRef}\n className={containerClass}\n onDragOver={allowUpload ? handleDragOver : undefined}\n onDragLeave={allowUpload ? handleDragLeave : undefined}\n onDrop={allowUpload ? handleDrop : undefined}\n >\n {/* 头部插槽 */}\n {renderSlot(header, false)}\n\n {allowUpload && files.length > 0 && renderFileList()}\n\n {/* 隐藏的原生 file input */}\n {allowUpload && (\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n accept={allowedFileTypes.join(\",\")}\n style={{ display: \"none\" }}\n onChange={(e) => {\n if (e.target.files) {\n handleFileSelect(Array.from(e.target.files));\n e.target.value = \"\";\n }\n }}\n />\n )}\n\n <div className={styles.mainArea}>\n <div className={styles.senderWrap}>\n {/* 清除按钮 */}\n {clearBtnShow && <ClearButton />}\n\n <div className={styles.inputAndButtons}>\n {/* 前缀插槽 */}\n {renderSlot(prefix, false)}\n\n <div className={styles.textAreaWrapper}>\n <Input.TextArea\n className={styles.textArea}\n value={value}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n placeholder=\"请输入消息...\"\n disabled={isDisabled}\n autoSize={{ minRows: 1, maxRows: 4 }}\n style={{\n border: \"none\",\n boxShadow: \"none\",\n outline: \"none\",\n padding: 0,\n }}\n />\n </div>\n\n {/* 后缀插槽(默认显示操作按钮) */}\n {renderSlot(suffix, defaultSuffix)}\n </div>\n </div>\n\n {/* 底部插槽(默认显示提示文字) */}\n {renderSlot(\n footer,\n <div className={styles.tip}>\n 内容由AI生成,无法确保真实准确,仅供参考\n </div>,\n )}\n </div>\n </div>\n );\n};\n\nexport default XAdkSender;\n"],
5
+ "mappings": "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",
6
6
  "names": ["files", "FileGallery"]
7
7
  }
@@ -20,31 +20,11 @@ export interface FileItem {
20
20
  response?: any;
21
21
  }
22
22
  export interface FileGalleryProps {
23
- /**
24
- * 文件列表
25
- */
26
- files: FileItem[];
27
- /**
28
- * 对齐方式
29
- * @default 'left'
30
- */
23
+ file: FileItem;
31
24
  align?: "left" | "right";
32
- /**
33
- * 是否可删除
34
- * @default false
35
- */
36
25
  removable?: boolean;
37
- /**
38
- * 删除文件回调
39
- */
40
26
  onRemove?: (id: string) => void;
41
- /**
42
- * 自定义样式类名
43
- */
44
27
  className?: string;
45
- /**
46
- * 自定义样式
47
- */
48
28
  style?: React.CSSProperties;
49
29
  }
50
30
  export interface FileItemComponentProps {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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"],
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 file: FileItem;\n align?: \"left\" | \"right\"; // 卡片内部布局:图标在左(默认)或右\n removable?: boolean;\n onRemove?: (id: string) => void;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport interface FileItemComponentProps {\n file: FileItem;\n removable: boolean;\n onRemove: (id: string) => void;\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -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 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"],
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 // 数据层回调\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
  }
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import FileGallery from "./index";
3
+ declare const meta: Meta<typeof FileGallery>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const 基础用法: Story;
@@ -0,0 +1,48 @@
1
+ import FileGallery from "./index";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ var meta = {
4
+ title: "AI组件/FileGallery 附件卡片",
5
+ component: FileGallery,
6
+ parameters: {
7
+ layout: "padded",
8
+ docs: {
9
+ description: {
10
+ component: "\n\n\u4E00\u4E2A\u901A\u7528\u7684\u5355\u6587\u4EF6\u5C55\u793A\u7EC4\u4EF6\uFF0C\u7C7B\u4F3C antd-design-x \u7684\u8BBE\u8BA1\u98CE\u683C\uFF0C\u652F\u6301\u591A\u79CD\u6587\u4EF6\u7C7B\u578B\u7684\u5C55\u793A\u548C\u4EA4\u4E92\u3002\n\n## \u2728 \u7279\u6027\n\n- \uD83D\uDCC1 \u652F\u6301\u591A\u79CD\u6587\u4EF6\u7C7B\u578B\u5C55\u793A (\u56FE\u7247\u3001\u97F3\u9891\u3001\u89C6\u9891\u3001\u6587\u6863\u7B49)\n- \uD83D\uDDBC\uFE0F \u56FE\u7247\u652F\u6301\u9884\u89C8\u548C\u7F29\u7565\u56FE\n- \uD83C\uDFB5 \u97F3\u9891\u6587\u4EF6\u652F\u6301\u5185\u8054\u64AD\u653E\n- \uD83C\uDFAC \u89C6\u9891\u6587\u4EF6\u652F\u6301\u5185\u8054\u64AD\u653E\n- \uD83D\uDCCA \u663E\u793A\u6587\u4EF6\u5927\u5C0F\u3001\u7C7B\u578B\u56FE\u6807\n- \uD83D\uDDD1\uFE0F \u652F\u6301\u5220\u9664\u64CD\u4F5C\n- \uD83D\uDCE4 \u652F\u6301\u4E0A\u4F20\u8FDB\u5EA6\u663E\u793A\n- \uD83C\uDFAF \u5355\u6587\u4EF6\u8BBE\u8BA1\uFF0C\u5E03\u5C40\u7075\u6D3B\u53EF\u63A7\n- \uD83C\uDFA8 \u652F\u6301\u5361\u7247\u5185\u90E8\u5E03\u5C40\u63A7\u5236\uFF08\u56FE\u6807\u5728\u5DE6/\u53F3\uFF09\n\n## \uD83C\uDFA8 \u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B\n\n### \u56FE\u7247 (\u5E26\u9884\u89C8)\n\n- jpg, jpeg, png, gif, webp, bmp, svg\n\n### \u97F3\u9891 (\u5185\u8054\u64AD\u653E)\n\n- mp3, wav, m4a, aac, ogg, flac\n\n### \u89C6\u9891 (\u5185\u8054\u64AD\u653E)\n\n- mp4, mov, webm, mkv, avi\n\n### \u6587\u6863 (\u56FE\u6807\u5C55\u793A)\n\n- PDF: pdf\n- Word: doc, docx\n- Excel: xls, xlsx, csv\n- PowerPoint: ppt, pptx\n- \u5176\u4ED6: \u901A\u7528\u6587\u4EF6\u56FE\u6807\n\n## \uD83D\uDCDD Props \u8BF4\u660E\n\n| \u5C5E\u6027 | \u7C7B\u578B | \u9ED8\u8BA4\u503C | \u8BF4\u660E |\n| --------- | --------------------- | ------ | ------------------------------------------ |\n| file | FileItem | - | \u6587\u4EF6\u5BF9\u8C61\uFF08\u5FC5\u9700\uFF09 |\n| align | \"left\" | \"right\" | \"left\" | \u5361\u7247\u5185\u90E8\u5E03\u5C40\uFF1A\u56FE\u6807\u5728\u5DE6(left)\u6216\u53F3(right) |\n| removable | boolean | false | \u662F\u5426\u663E\u793A\u5220\u9664\u6309\u94AE |\n| onRemove | (id: string) => void | - | \u5220\u9664\u6587\u4EF6\u56DE\u8C03 |\n| className | string | - | \u81EA\u5B9A\u4E49\u6837\u5F0F\u7C7B\u540D |\n| style | React.CSSProperties | - | \u81EA\u5B9A\u4E49\u6837\u5F0F |\n\n\n## \uD83D\uDCA1 \u8BBE\u8BA1\u7406\u5FF5\n\n### \u4E3A\u4EC0\u4E48\u662F\u5355\u6587\u4EF6\u8BBE\u8BA1\uFF1F\n\n1. **\u5E03\u5C40\u7075\u6D3B\u6027**\uFF1A\u4E0A\u5C42\u7EC4\u4EF6\u53EF\u4EE5\u81EA\u7531\u63A7\u5236\u6587\u4EF6\u5217\u8868\u7684\u5E03\u5C40\u65B9\u5F0F\uFF08flex\u3001grid\u3001\u6C34\u5E73\u3001\u5782\u76F4\u7B49\uFF09\n2. **\u5BF9\u9F50\u63A7\u5236**\uFF1A\u901A\u8FC7\u5BB9\u5668\u7684 CSS \u63A7\u5236\u6574\u4E2A\u5217\u8868\u7684\u5BF9\u9F50\u65B9\u5F0F\uFF0C\u800C\u975E\u7EC4\u4EF6\u5185\u90E8\u63A7\u5236\n3. **\u8D23\u4EFB\u5355\u4E00**\uFF1A\u7EC4\u4EF6\u4E13\u6CE8\u4E8E\u5355\u4E2A\u6587\u4EF6\u7684\u5C55\u793A\uFF0C\u4E0D\u5173\u5FC3\u5217\u8868\u5E03\u5C40\n4. **\u6613\u4E8E\u6269\u5C55**\uFF1A\u53EF\u4EE5\u8F7B\u677E\u63D2\u5165\u5176\u4ED6\u5143\u7D20\uFF08\u5982\u5206\u9694\u7B26\u3001\u6807\u7B7E\u7B49\uFF09\n "
11
+ }
12
+ }
13
+ },
14
+ tags: ["autodocs"],
15
+ argTypes: {}
16
+ };
17
+ export default meta;
18
+ // ============================================
19
+ // 示例 1: 基础用法
20
+ // ============================================
21
+ export var 基础用法 = {
22
+ render: function render() {
23
+ var remoteFiles = [{
24
+ displayName: "report.xlsx",
25
+ mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
26
+ fileUri: "https://example.com/report.xlsx"
27
+ }, {
28
+ displayName: "photo.png",
29
+ mimeType: "image/png",
30
+ fileUri: "https://example.com/photo.png"
31
+ }];
32
+ return /*#__PURE__*/_jsx("div", {
33
+ style: {
34
+ display: "flex",
35
+ flexWrap: "wrap",
36
+ gap: "8px",
37
+ justifyContent: "flex-start"
38
+ },
39
+ children: remoteFiles.map(function (file, index) {
40
+ return /*#__PURE__*/_jsx(FileGallery, {
41
+ file: file,
42
+ align: "left"
43
+ }, index);
44
+ })
45
+ });
46
+ }
47
+ };
48
+ //# sourceMappingURL=FileGallery.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["FileGallery","jsx","_jsx","meta","title","component","parameters","layout","docs","description","tags","argTypes","基础用法","render","remoteFiles","displayName","mimeType","fileUri","style","display","flexWrap","gap","justifyContent","children","map","file","index","align"],"sources":["../../../../src/components/FileGallery/FileGallery.stories.tsx"],"sourcesContent":["import type { Meta, StoryObj } from \"@storybook/react-vite\";\nimport FileGallery from \"./index\";\n\nconst meta: Meta<typeof FileGallery> = {\n title: \"AI组件/FileGallery 附件卡片\",\n component: FileGallery,\n parameters: {\n layout: \"padded\",\n docs: {\n description: {\n component: `\n\n一个通用的单文件展示组件,类似 antd-design-x 的设计风格,支持多种文件类型的展示和交互。\n\n## ✨ 特性\n\n- 📁 支持多种文件类型展示 (图片、音频、视频、文档等)\n- 🖼️ 图片支持预览和缩略图\n- 🎵 音频文件支持内联播放\n- 🎬 视频文件支持内联播放\n- 📊 显示文件大小、类型图标\n- 🗑️ 支持删除操作\n- 📤 支持上传进度显示\n- 🎯 单文件设计,布局灵活可控\n- 🎨 支持卡片内部布局控制(图标在左/右)\n\n## 🎨 支持的文件类型\n\n### 图片 (带预览)\n\n- jpg, jpeg, png, gif, webp, bmp, svg\n\n### 音频 (内联播放)\n\n- mp3, wav, m4a, aac, ogg, flac\n\n### 视频 (内联播放)\n\n- mp4, mov, webm, mkv, avi\n\n### 文档 (图标展示)\n\n- PDF: pdf\n- Word: doc, docx\n- Excel: xls, xlsx, csv\n- PowerPoint: ppt, pptx\n- 其他: 通用文件图标\n\n## 📝 Props 说明\n\n| 属性 | 类型 | 默认值 | 说明 |\n| --------- | --------------------- | ------ | ------------------------------------------ |\n| file | FileItem | - | 文件对象(必需) |\n| align | \"left\" \\| \"right\" | \"left\" | 卡片内部布局:图标在左(left)或右(right) |\n| removable | boolean | false | 是否显示删除按钮 |\n| onRemove | (id: string) => void | - | 删除文件回调 |\n| className | string | - | 自定义样式类名 |\n| style | React.CSSProperties | - | 自定义样式 |\n\n\n## 💡 设计理念\n\n### 为什么是单文件设计?\n\n1. **布局灵活性**:上层组件可以自由控制文件列表的布局方式(flex、grid、水平、垂直等)\n2. **对齐控制**:通过容器的 CSS 控制整个列表的对齐方式,而非组件内部控制\n3. **责任单一**:组件专注于单个文件的展示,不关心列表布局\n4. **易于扩展**:可以轻松插入其他元素(如分隔符、标签等)\n `,\n },\n },\n },\n tags: [\"autodocs\"],\n argTypes: {},\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\n// ============================================\n// 示例 1: 基础用法\n// ============================================\nexport const 基础用法: Story = {\n render: () => {\n const remoteFiles = [\n {\n displayName: \"report.xlsx\",\n mimeType:\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n fileUri: \"https://example.com/report.xlsx\",\n },\n {\n displayName: \"photo.png\",\n mimeType: \"image/png\",\n fileUri: \"https://example.com/photo.png\",\n },\n ];\n\n return (\n <div\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"8px\",\n justifyContent: \"flex-start\",\n }}\n >\n {remoteFiles.map((file, index) => (\n <FileGallery key={index} file={file} align=\"left\" />\n ))}\n </div>\n );\n },\n};\n"],"mappings":"AACA,OAAOA,WAAW;AAAgB,SAAAC,GAAA,IAAAC,IAAA;AAElC,IAAMC,IAA8B,GAAG;EACrCC,KAAK,EAAE,uBAAuB;EAC9BC,SAAS,EAAEL,WAAW;EACtBM,UAAU,EAAE;IACVC,MAAM,EAAE,QAAQ;IAChBC,IAAI,EAAE;MACJC,WAAW,EAAE;QACXJ,SAAS;MA2DX;IACF;EACF,CAAC;EACDK,IAAI,EAAE,CAAC,UAAU,CAAC;EAClBC,QAAQ,EAAE,CAAC;AACb,CAAC;AAED,eAAeR,IAAI;AAGnB;AACA;AACA;AACA,OAAO,IAAMS,IAAW,GAAG;EACzBC,MAAM,EAAE,SAAAA,OAAA,EAAM;IACZ,IAAMC,WAAW,GAAG,CAClB;MACEC,WAAW,EAAE,aAAa;MAC1BC,QAAQ,EACN,mEAAmE;MACrEC,OAAO,EAAE;IACX,CAAC,EACD;MACEF,WAAW,EAAE,WAAW;MACxBC,QAAQ,EAAE,WAAW;MACrBC,OAAO,EAAE;IACX,CAAC,CACF;IAED,oBACEf,IAAA;MACEgB,KAAK,EAAE;QACLC,OAAO,EAAE,MAAM;QACfC,QAAQ,EAAE,MAAM;QAChBC,GAAG,EAAE,KAAK;QACVC,cAAc,EAAE;MAClB,CAAE;MAAAC,QAAA,EAEDT,WAAW,CAACU,GAAG,CAAC,UAACC,IAAI,EAAEC,KAAK;QAAA,oBAC3BxB,IAAA,CAACF,WAAW;UAAayB,IAAI,EAAEA,IAAK;UAACE,KAAK,EAAC;QAAM,GAA/BD,KAAiC,CAAC;MAAA,CACrD;IAAC,CACC,CAAC;EAEV;AACF,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { FileGalleryProps } from "../../types";
3
3
  /**
4
- * FileGallery - 通用文件展示组件
4
+ * FileGallery - 单文件展示组件
5
5
  *
6
6
  * 功能特性:
7
7
  * - 📁 支持多种文件类型展示 (图片、音频、视频、文档等)
@@ -11,23 +11,24 @@ import { FileGalleryProps } from "../../types";
11
11
  * - 📊 显示文件大小、类型图标
12
12
  * - 🗑️ 支持删除操作
13
13
  * - 📤 支持上传进度显示
14
- * - 🎨 支持左右对齐
14
+ * - 🎨 支持卡片内部布局控制(align:图标和信息的排列方式)
15
15
  *
16
16
  * @example
17
17
  * // XAdkSender 场景 - 可删除的本地文件
18
- * <FileGallery
19
- * files={localFiles}
20
- * removable
21
- * onRemove={handleRemove}
22
- * align="left"
23
- * />
18
+ * {files.map(file => (
19
+ * <FileGallery
20
+ * key={file.id}
21
+ * file={file}
22
+ * removable
23
+ * onRemove={handleRemove}
24
+ * />
25
+ * ))}
24
26
  *
25
27
  * @example
26
28
  * // XadkChatbot 场景 - 只读的远程文件
27
- * <FileGallery
28
- * files={remoteFiles}
29
- * align="right"
30
- * />
29
+ * {files.map(file => (
30
+ * <FileGallery key={file.id} file={file} />
31
+ * ))}
31
32
  */
32
33
  declare const FileGallery: React.FC<FileGalleryProps>;
33
34
  export default FileGallery;
@@ -164,12 +164,46 @@ var formatFileSize = function formatFileSize(bytes) {
164
164
  };
165
165
  var styles = useStyles();
166
166
 
167
- // ==================== 子组件 ====================
168
-
169
- var FileItemComponent = function FileItemComponent(_ref) {
167
+ /**
168
+ * FileGallery - 单文件展示组件
169
+ *
170
+ * 功能特性:
171
+ * - 📁 支持多种文件类型展示 (图片、音频、视频、文档等)
172
+ * - 🖼️ 图片支持预览和缩略图
173
+ * - 🎵 音频文件支持内联播放
174
+ * - 🎬 视频文件支持内联播放
175
+ * - 📊 显示文件大小、类型图标
176
+ * - 🗑️ 支持删除操作
177
+ * - 📤 支持上传进度显示
178
+ * - 🎨 支持卡片内部布局控制(align:图标和信息的排列方式)
179
+ *
180
+ * @example
181
+ * // XAdkSender 场景 - 可删除的本地文件
182
+ * {files.map(file => (
183
+ * <FileGallery
184
+ * key={file.id}
185
+ * file={file}
186
+ * removable
187
+ * onRemove={handleRemove}
188
+ * />
189
+ * ))}
190
+ *
191
+ * @example
192
+ * // XadkChatbot 场景 - 只读的远程文件
193
+ * {files.map(file => (
194
+ * <FileGallery key={file.id} file={file} />
195
+ * ))}
196
+ */
197
+ var FileGallery = function FileGallery(_ref) {
170
198
  var file = _ref.file,
171
- removable = _ref.removable,
172
- onRemove = _ref.onRemove;
199
+ _ref$align = _ref.align,
200
+ align = _ref$align === void 0 ? "left" : _ref$align,
201
+ _ref$removable = _ref.removable,
202
+ removable = _ref$removable === void 0 ? false : _ref$removable,
203
+ _ref$onRemove = _ref.onRemove,
204
+ onRemove = _ref$onRemove === void 0 ? function () {} : _ref$onRemove,
205
+ className = _ref.className,
206
+ style = _ref.style;
173
207
  var _useState = useState(""),
174
208
  _useState2 = _slicedToArray(_useState, 2),
175
209
  objectUrl = _useState2[0],
@@ -182,6 +216,7 @@ var FileItemComponent = function FileItemComponent(_ref) {
182
216
  return URL.revokeObjectURL(url);
183
217
  };
184
218
  }, [file.file]);
219
+ if (!file) return null;
185
220
  var isImage = isImageFile(file);
186
221
  var isAudio = isAudioFile(file);
187
222
  var isVideo = isVideoFile(file);
@@ -193,7 +228,8 @@ var FileItemComponent = function FileItemComponent(_ref) {
193
228
  // 图片文件
194
229
  if (isImage) {
195
230
  return /*#__PURE__*/_jsxs("div", {
196
- className: styles.fileCard,
231
+ className: "".concat(styles.fileCard, " ").concat(align === "right" ? "align-right" : "", " ").concat(className || ""),
232
+ style: style,
197
233
  children: [/*#__PURE__*/_jsxs("div", {
198
234
  className: styles.imageThumbnail,
199
235
  children: [/*#__PURE__*/_jsx(Image, {
@@ -239,7 +275,8 @@ var FileItemComponent = function FileItemComponent(_ref) {
239
275
  // 音频文件
240
276
  if (isAudio) {
241
277
  return /*#__PURE__*/_jsxs("div", {
242
- className: styles.fileCard,
278
+ className: "".concat(styles.fileCard, " ").concat(align === "right" ? "align-right" : "", " ").concat(className || ""),
279
+ style: style,
243
280
  children: [/*#__PURE__*/_jsx("div", {
244
281
  className: styles.fileIcon,
245
282
  style: {
@@ -278,7 +315,8 @@ var FileItemComponent = function FileItemComponent(_ref) {
278
315
  // 视频文件
279
316
  if (isVideo) {
280
317
  return /*#__PURE__*/_jsxs("div", {
281
- className: styles.fileCard,
318
+ className: "".concat(styles.fileCard, " ").concat(align === "right" ? "align-right" : "", " ").concat(className || ""),
319
+ style: style,
282
320
  children: [/*#__PURE__*/_jsx("div", {
283
321
  className: styles.fileIcon,
284
322
  style: {
@@ -320,7 +358,8 @@ var FileItemComponent = function FileItemComponent(_ref) {
320
358
  color = _getFileIcon.color;
321
359
  var isExternalUrl = url && url.startsWith("http");
322
360
  return /*#__PURE__*/_jsxs("div", {
323
- className: styles.fileCard,
361
+ className: "".concat(styles.fileCard, " ").concat(align === "right" ? "align-right" : "", " ").concat(className || ""),
362
+ style: style,
324
363
  children: [/*#__PURE__*/_jsx("div", {
325
364
  className: styles.fileIcon,
326
365
  style: {
@@ -375,65 +414,5 @@ var FileItemComponent = function FileItemComponent(_ref) {
375
414
  })]
376
415
  });
377
416
  };
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
417
  export default FileGallery;
439
418
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","useState","useEffect","Image","Tooltip","Progress","FileOutlined","FilePdfOutlined","FileWordOutlined","FileExcelOutlined","FilePptOutlined","FileImageOutlined","CloseOutlined","AudioOutlined","VideoCameraOutlined","useStyles","jsx","_jsx","jsxs","_jsxs","getFileName","file","displayName","name","getFileSize","size","getMimeType","mimeType","type","getFileUrl","_file$response","_file$response2","fileUri","response","fileUrl","tempUrl","getFileId","id","uid","isImageFile","startsWith","fileName","match","url","isAudioFile","isVideoFile","getFileExtension","filename","ext","split","pop","toLowerCase","getFileIcon","icon","color","includes","formatFileSize","bytes","toFixed","styles","FileItemComponent","_ref","removable","onRemove","_useState","_useState2","_slicedToArray","objectUrl","setObjectUrl","URL","createObjectURL","revokeObjectURL","isImage","isAudio","isVideo","fileSize","fileId","className","fileCard","children","imageThumbnail","src","alt","fallback","preview","status","imageOverlay","percent","progress","strokeColor","fileInfo","title","length","concat","substring","fileRemoveBtn","onClick","disabled","fileIcon","style","controls","mediaWrapper","width","height","_getFileIcon","isExternalUrl","href","target","rel","fileLink","showInfo","errorMessage","fontSize","marginTop","FileGallery","_ref2","files","_ref2$align","align","_ref2$removable","_ref2$onRemove","container","fileList","PreviewGroup","map","index"],"sources":["../../../../src/components/FileGallery/index.tsx"],"sourcesContent":["import React, { useState, useEffect } from \"react\";\nimport { Image, Tooltip, Progress } from \"antd\";\nimport {\n FileOutlined,\n FilePdfOutlined,\n FileWordOutlined,\n FileExcelOutlined,\n FilePptOutlined,\n FileImageOutlined,\n CloseOutlined,\n AudioOutlined,\n VideoCameraOutlined,\n} from \"@ant-design/icons\";\nimport { FileItem, FileGalleryProps, FileItemComponentProps } from \"@/types\";\nimport { useStyles } from \"./styles\";\n\n// ==================== 工具函数 ====================\n\n/**\n * 获取文件名\n */\nconst getFileName = (file: FileItem): string => {\n return file.displayName || file.name || \"\";\n};\n\n/**\n * 获取文件大小\n */\nconst getFileSize = (file: FileItem): number => {\n return file.size || 0;\n};\n\n/**\n * 获取文件 MIME 类型\n */\nconst getMimeType = (file: FileItem): string => {\n return file.mimeType || file.type || \"\";\n};\n\n/**\n * 获取文件 URL\n */\nconst getFileUrl = (file: FileItem): string => {\n return (\n file.fileUri ||\n file.response?.fileUrl ||\n file.response?.tempUrl ||\n file.tempUrl ||\n \"\"\n );\n};\n\n/**\n * 获取文件唯一标识\n */\nconst getFileId = (file: FileItem): string => {\n return file.id || file.uid || \"\";\n};\n\n/**\n * 判断是否是图片文件\n */\nconst isImageFile = (file: FileItem): boolean => {\n const mimeType = getMimeType(file);\n if (mimeType && mimeType.startsWith(\"image/\")) return true;\n\n const fileName = getFileName(file);\n if (fileName && fileName.match(/\\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i))\n return true;\n\n const url = getFileUrl(file);\n if (url && url.match(/\\.(jpg|jpeg|png|gif|webp|bmp|svg)(\\?.*)?$/i))\n return true;\n\n return false;\n};\n\n/**\n * 判断是否是音频文件\n */\nconst isAudioFile = (file: FileItem): boolean => {\n const mimeType = getMimeType(file);\n if (mimeType && mimeType.startsWith(\"audio/\")) return true;\n\n const fileName = getFileName(file);\n return !!fileName?.match(/\\.(mp3|wav|m4a|aac|ogg|flac)$/i);\n};\n\n/**\n * 判断是否是视频文件\n */\nconst isVideoFile = (file: FileItem): boolean => {\n const mimeType = getMimeType(file);\n if (mimeType && mimeType.startsWith(\"video/\")) return true;\n\n const fileName = getFileName(file);\n return !!fileName?.match(/\\.(mp4|mov|webm|mkv|avi)$/i);\n};\n\n/**\n * 获取文件扩展名\n */\nconst getFileExtension = (filename: string): string => {\n const ext = filename.split(\".\").pop();\n return ext ? ext.toLowerCase() : \"\";\n};\n\n/**\n * 获取文件图标和颜色\n */\nconst getFileIcon = (\n file: FileItem,\n): { icon: React.ReactNode; color: string } => {\n const ext = getFileExtension(getFileName(file));\n\n // PDF\n if (ext === \"pdf\") {\n return { icon: <FilePdfOutlined />, color: \"#ff4d4f\" };\n }\n\n // Word\n if ([\"doc\", \"docx\"].includes(ext)) {\n return { icon: <FileWordOutlined />, color: \"#1677ff\" };\n }\n\n // Excel\n if ([\"xls\", \"xlsx\", \"csv\"].includes(ext)) {\n return { icon: <FileExcelOutlined />, color: \"#22b35e\" };\n }\n\n // PPT\n if ([\"ppt\", \"pptx\"].includes(ext)) {\n return { icon: <FilePptOutlined />, color: \"#ff6e31\" };\n }\n\n // Audio\n if ([\"mp3\", \"wav\", \"m4a\", \"aac\", \"ogg\", \"flac\"].includes(ext)) {\n return { icon: <AudioOutlined />, color: \"#722ed1\" };\n }\n\n // Video\n if ([\"mp4\", \"mov\", \"webm\", \"mkv\", \"avi\"].includes(ext)) {\n return { icon: <VideoCameraOutlined />, color: \"#fa8c16\" };\n }\n\n // 图片\n if (isImageFile(file)) {\n return { icon: <FileImageOutlined />, color: \"#8c8c8c\" };\n }\n\n // 默认\n return { icon: <FileOutlined />, color: \"#8c8c8c\" };\n};\n\n/**\n * 格式化文件大小\n */\nconst formatFileSize = (bytes: number): string => {\n if (bytes < 1024) return bytes + \" B\";\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + \" KB\";\n return (bytes / (1024 * 1024)).toFixed(1) + \" MB\";\n};\n\nconst styles = useStyles();\n\n// ==================== 子组件 ====================\n\nconst FileItemComponent: React.FC<FileItemComponentProps> = ({\n file,\n removable,\n onRemove,\n}) => {\n const [objectUrl, setObjectUrl] = useState(\"\");\n\n useEffect(() => {\n if (!file.file) return;\n\n const url = URL.createObjectURL(file.file);\n setObjectUrl(url);\n\n return () => URL.revokeObjectURL(url);\n }, [file.file]);\n\n const isImage = isImageFile(file);\n const isAudio = isAudioFile(file);\n const isVideo = isVideoFile(file);\n const fileName = getFileName(file);\n const fileSize = getFileSize(file);\n const fileId = getFileId(file);\n const url = getFileUrl(file) || objectUrl;\n\n // 图片文件\n if (isImage) {\n return (\n <div className={styles.fileCard}>\n {/* 图片缩略图 */}\n <div className={styles.imageThumbnail}>\n <Image\n src={url}\n alt={fileName}\n fallback=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mN8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==\"\n preview={{\n src: url,\n }}\n />\n\n {/* 上传进度遮罩 */}\n {file.status === \"uploading\" && (\n <div className={styles.imageOverlay}>\n <Progress\n type=\"circle\"\n percent={file.progress}\n size={30}\n strokeColor=\"#1677ff\"\n />\n </div>\n )}\n </div>\n\n {/* 文件信息 */}\n <div className={styles.fileInfo}>\n <Tooltip title={fileName}>\n <div className={styles.fileName}>\n {fileName.length > 15\n ? `${fileName.substring(0, 15)}...`\n : fileName}\n </div>\n </Tooltip>\n <div className={styles.fileSize}>{formatFileSize(fileSize)}</div>\n </div>\n\n {/* 删除按钮 */}\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n }\n\n // 音频文件\n if (isAudio) {\n return (\n <div className={styles.fileCard}>\n <div className={styles.fileIcon} style={{ color: \"#722ed1\" }}>\n <AudioOutlined />\n </div>\n\n <div className={styles.fileInfo}>\n <Tooltip title={fileName}>\n <div className={styles.fileName}>{fileName}</div>\n </Tooltip>\n\n <audio\n src={url}\n controls\n className={styles.mediaWrapper}\n style={{ width: \"100%\", height: 28 }}\n />\n </div>\n\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n }\n\n // 视频文件\n if (isVideo) {\n return (\n <div className={styles.fileCard}>\n <div className={styles.fileIcon} style={{ color: \"#fa8c16\" }}>\n <VideoCameraOutlined />\n </div>\n\n <div className={styles.fileInfo}>\n <Tooltip title={fileName}>\n <div className={styles.fileName}>{fileName}</div>\n </Tooltip>\n\n <video\n src={url}\n controls\n className={styles.mediaWrapper}\n style={{ width: \"100%\", height: 40 }}\n />\n </div>\n\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n }\n\n // 其他文件\n const { icon, color } = getFileIcon(file);\n const isExternalUrl = url && url.startsWith(\"http\");\n\n return (\n <div className={styles.fileCard}>\n <div className={styles.fileIcon} style={{ color }}>\n {icon}\n </div>\n\n <div className={styles.fileInfo}>\n {isExternalUrl ? (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={styles.fileLink}\n >\n <Tooltip title={fileName}>\n <div className={styles.fileName}>\n {fileName.length > 15\n ? `${fileName.substring(0, 15)}...`\n : fileName}\n </div>\n </Tooltip>\n </a>\n ) : (\n <Tooltip title={fileName}>\n <div className={styles.fileName}>\n {fileName.length > 15\n ? `${fileName.substring(0, 15)}...`\n : fileName}\n </div>\n </Tooltip>\n )}\n\n {file.status === \"uploading\" ? (\n <Progress\n percent={file.progress}\n size=\"small\"\n showInfo={false}\n strokeColor=\"#1677ff\"\n className={styles.progress}\n />\n ) : (\n fileSize > 0 && (\n <div className={styles.fileSize}>{formatFileSize(fileSize)}</div>\n )\n )}\n\n {file.status === \"error\" && file.errorMessage && (\n <div\n style={{\n fontSize: \"11px\",\n color: \"#ff4d4f\",\n marginTop: \"2px\",\n }}\n >\n {file.errorMessage}\n </div>\n )}\n </div>\n\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n};\n\n// ==================== 主组件 ====================\n\n/**\n * FileGallery - 通用文件展示组件\n *\n * 功能特性:\n * - 📁 支持多种文件类型展示 (图片、音频、视频、文档等)\n * - 🖼️ 图片支持预览和缩略图\n * - 🎵 音频文件支持内联播放\n * - 🎬 视频文件支持内联播放\n * - 📊 显示文件大小、类型图标\n * - 🗑️ 支持删除操作\n * - 📤 支持上传进度显示\n * - 🎨 支持左右对齐\n *\n * @example\n * // XAdkSender 场景 - 可删除的本地文件\n * <FileGallery\n * files={localFiles}\n * removable\n * onRemove={handleRemove}\n * align=\"left\"\n * />\n *\n * @example\n * // XadkChatbot 场景 - 只读的远程文件\n * <FileGallery\n * files={remoteFiles}\n * align=\"right\"\n * />\n */\nconst FileGallery: React.FC<FileGalleryProps> = ({\n files,\n align = \"left\",\n removable = false,\n onRemove = () => {},\n className,\n style,\n}) => {\n if (!files || files.length === 0) return null;\n\n return (\n <div\n className={`${styles.container} ${align === \"right\" ? \"align-right\" : \"\"} ${className || \"\"}`}\n style={style}\n >\n <div className={styles.fileList}>\n <Image.PreviewGroup>\n {files.map((file, index) => (\n <FileItemComponent\n key={getFileId(file) || index}\n file={file}\n removable={removable}\n onRemove={onRemove}\n />\n ))}\n </Image.PreviewGroup>\n </div>\n </div>\n );\n};\n\nexport default FileGallery;\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","useState","useEffect","Image","Tooltip","Progress","FileOutlined","FilePdfOutlined","FileWordOutlined","FileExcelOutlined","FilePptOutlined","FileImageOutlined","CloseOutlined","AudioOutlined","VideoCameraOutlined","useStyles","jsx","_jsx","jsxs","_jsxs","getFileName","file","displayName","name","getFileSize","size","getMimeType","mimeType","type","getFileUrl","_file$response","_file$response2","fileUri","response","fileUrl","tempUrl","getFileId","id","uid","isImageFile","startsWith","fileName","match","url","isAudioFile","isVideoFile","getFileExtension","filename","ext","split","pop","toLowerCase","getFileIcon","icon","color","includes","formatFileSize","bytes","toFixed","styles","FileGallery","_ref","_ref$align","align","_ref$removable","removable","_ref$onRemove","onRemove","className","style","_useState","_useState2","_slicedToArray","objectUrl","setObjectUrl","URL","createObjectURL","revokeObjectURL","isImage","isAudio","isVideo","fileSize","fileId","concat","fileCard","children","imageThumbnail","src","alt","fallback","preview","status","imageOverlay","percent","progress","strokeColor","fileInfo","title","length","substring","fileRemoveBtn","onClick","disabled","fileIcon","controls","mediaWrapper","width","height","_getFileIcon","isExternalUrl","href","target","rel","fileLink","showInfo","errorMessage","fontSize","marginTop"],"sources":["../../../../src/components/FileGallery/index.tsx"],"sourcesContent":["import React, { useState, useEffect } from \"react\";\nimport { Image, Tooltip, Progress } from \"antd\";\nimport {\n FileOutlined,\n FilePdfOutlined,\n FileWordOutlined,\n FileExcelOutlined,\n FilePptOutlined,\n FileImageOutlined,\n CloseOutlined,\n AudioOutlined,\n VideoCameraOutlined,\n} from \"@ant-design/icons\";\nimport { FileItem, FileGalleryProps, FileItemComponentProps } from \"@/types\";\nimport { useStyles } from \"./styles\";\n\n// ==================== 工具函数 ====================\n\n/**\n * 获取文件名\n */\nconst getFileName = (file: FileItem): string => {\n return file.displayName || file.name || \"\";\n};\n\n/**\n * 获取文件大小\n */\nconst getFileSize = (file: FileItem): number => {\n return file.size || 0;\n};\n\n/**\n * 获取文件 MIME 类型\n */\nconst getMimeType = (file: FileItem): string => {\n return file.mimeType || file.type || \"\";\n};\n\n/**\n * 获取文件 URL\n */\nconst getFileUrl = (file: FileItem): string => {\n return (\n file.fileUri ||\n file.response?.fileUrl ||\n file.response?.tempUrl ||\n file.tempUrl ||\n \"\"\n );\n};\n\n/**\n * 获取文件唯一标识\n */\nconst getFileId = (file: FileItem): string => {\n return file.id || file.uid || \"\";\n};\n\n/**\n * 判断是否是图片文件\n */\nconst isImageFile = (file: FileItem): boolean => {\n const mimeType = getMimeType(file);\n if (mimeType && mimeType.startsWith(\"image/\")) return true;\n\n const fileName = getFileName(file);\n if (fileName && fileName.match(/\\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i))\n return true;\n\n const url = getFileUrl(file);\n if (url && url.match(/\\.(jpg|jpeg|png|gif|webp|bmp|svg)(\\?.*)?$/i))\n return true;\n\n return false;\n};\n\n/**\n * 判断是否是音频文件\n */\nconst isAudioFile = (file: FileItem): boolean => {\n const mimeType = getMimeType(file);\n if (mimeType && mimeType.startsWith(\"audio/\")) return true;\n\n const fileName = getFileName(file);\n return !!fileName?.match(/\\.(mp3|wav|m4a|aac|ogg|flac)$/i);\n};\n\n/**\n * 判断是否是视频文件\n */\nconst isVideoFile = (file: FileItem): boolean => {\n const mimeType = getMimeType(file);\n if (mimeType && mimeType.startsWith(\"video/\")) return true;\n\n const fileName = getFileName(file);\n return !!fileName?.match(/\\.(mp4|mov|webm|mkv|avi)$/i);\n};\n\n/**\n * 获取文件扩展名\n */\nconst getFileExtension = (filename: string): string => {\n const ext = filename.split(\".\").pop();\n return ext ? ext.toLowerCase() : \"\";\n};\n\n/**\n * 获取文件图标和颜色\n */\nconst getFileIcon = (\n file: FileItem,\n): { icon: React.ReactNode; color: string } => {\n const ext = getFileExtension(getFileName(file));\n\n // PDF\n if (ext === \"pdf\") {\n return { icon: <FilePdfOutlined />, color: \"#ff4d4f\" };\n }\n\n // Word\n if ([\"doc\", \"docx\"].includes(ext)) {\n return { icon: <FileWordOutlined />, color: \"#1677ff\" };\n }\n\n // Excel\n if ([\"xls\", \"xlsx\", \"csv\"].includes(ext)) {\n return { icon: <FileExcelOutlined />, color: \"#22b35e\" };\n }\n\n // PPT\n if ([\"ppt\", \"pptx\"].includes(ext)) {\n return { icon: <FilePptOutlined />, color: \"#ff6e31\" };\n }\n\n // Audio\n if ([\"mp3\", \"wav\", \"m4a\", \"aac\", \"ogg\", \"flac\"].includes(ext)) {\n return { icon: <AudioOutlined />, color: \"#722ed1\" };\n }\n\n // Video\n if ([\"mp4\", \"mov\", \"webm\", \"mkv\", \"avi\"].includes(ext)) {\n return { icon: <VideoCameraOutlined />, color: \"#fa8c16\" };\n }\n\n // 图片\n if (isImageFile(file)) {\n return { icon: <FileImageOutlined />, color: \"#8c8c8c\" };\n }\n\n // 默认\n return { icon: <FileOutlined />, color: \"#8c8c8c\" };\n};\n\n/**\n * 格式化文件大小\n */\nconst formatFileSize = (bytes: number): string => {\n if (bytes < 1024) return bytes + \" B\";\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + \" KB\";\n return (bytes / (1024 * 1024)).toFixed(1) + \" MB\";\n};\n\nconst styles = useStyles();\n\n/**\n * FileGallery - 单文件展示组件\n *\n * 功能特性:\n * - 📁 支持多种文件类型展示 (图片、音频、视频、文档等)\n * - 🖼️ 图片支持预览和缩略图\n * - 🎵 音频文件支持内联播放\n * - 🎬 视频文件支持内联播放\n * - 📊 显示文件大小、类型图标\n * - 🗑️ 支持删除操作\n * - 📤 支持上传进度显示\n * - 🎨 支持卡片内部布局控制(align:图标和信息的排列方式)\n *\n * @example\n * // XAdkSender 场景 - 可删除的本地文件\n * {files.map(file => (\n * <FileGallery\n * key={file.id}\n * file={file}\n * removable\n * onRemove={handleRemove}\n * />\n * ))}\n *\n * @example\n * // XadkChatbot 场景 - 只读的远程文件\n * {files.map(file => (\n * <FileGallery key={file.id} file={file} />\n * ))}\n */\nconst FileGallery: React.FC<FileGalleryProps> = ({\n file,\n align = \"left\",\n removable = false,\n onRemove = () => {},\n className,\n style,\n}) => {\n const [objectUrl, setObjectUrl] = useState(\"\");\n\n useEffect(() => {\n if (!file.file) return;\n\n const url = URL.createObjectURL(file.file);\n setObjectUrl(url);\n\n return () => URL.revokeObjectURL(url);\n }, [file.file]);\n\n if (!file) return null;\n\n const isImage = isImageFile(file);\n const isAudio = isAudioFile(file);\n const isVideo = isVideoFile(file);\n const fileName = getFileName(file);\n const fileSize = getFileSize(file);\n const fileId = getFileId(file);\n const url = getFileUrl(file) || objectUrl;\n\n // 图片文件\n if (isImage) {\n return (\n <div\n className={`${styles.fileCard} ${align === \"right\" ? \"align-right\" : \"\"} ${className || \"\"}`}\n style={style}\n >\n {/* 图片缩略图 */}\n <div className={styles.imageThumbnail}>\n <Image\n src={url}\n alt={fileName}\n fallback=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mN8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==\"\n preview={{\n src: url,\n }}\n />\n\n {/* 上传进度遮罩 */}\n {file.status === \"uploading\" && (\n <div className={styles.imageOverlay}>\n <Progress\n type=\"circle\"\n percent={file.progress}\n size={30}\n strokeColor=\"#1677ff\"\n />\n </div>\n )}\n </div>\n\n {/* 文件信息 */}\n <div className={styles.fileInfo}>\n <Tooltip title={fileName}>\n <div className={styles.fileName}>\n {fileName.length > 15\n ? `${fileName.substring(0, 15)}...`\n : fileName}\n </div>\n </Tooltip>\n <div className={styles.fileSize}>{formatFileSize(fileSize)}</div>\n </div>\n\n {/* 删除按钮 */}\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n }\n\n // 音频文件\n if (isAudio) {\n return (\n <div\n className={`${styles.fileCard} ${align === \"right\" ? \"align-right\" : \"\"} ${className || \"\"}`}\n style={style}\n >\n <div className={styles.fileIcon} style={{ color: \"#722ed1\" }}>\n <AudioOutlined />\n </div>\n\n <div className={styles.fileInfo}>\n <Tooltip title={fileName}>\n <div className={styles.fileName}>{fileName}</div>\n </Tooltip>\n\n <audio\n src={url}\n controls\n className={styles.mediaWrapper}\n style={{ width: \"100%\", height: 28 }}\n />\n </div>\n\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n }\n\n // 视频文件\n if (isVideo) {\n return (\n <div\n className={`${styles.fileCard} ${align === \"right\" ? \"align-right\" : \"\"} ${className || \"\"}`}\n style={style}\n >\n <div className={styles.fileIcon} style={{ color: \"#fa8c16\" }}>\n <VideoCameraOutlined />\n </div>\n\n <div className={styles.fileInfo}>\n <Tooltip title={fileName}>\n <div className={styles.fileName}>{fileName}</div>\n </Tooltip>\n\n <video\n src={url}\n controls\n className={styles.mediaWrapper}\n style={{ width: \"100%\", height: 40 }}\n />\n </div>\n\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n }\n\n // 其他文件\n const { icon, color } = getFileIcon(file);\n const isExternalUrl = url && url.startsWith(\"http\");\n\n return (\n <div\n className={`${styles.fileCard} ${align === \"right\" ? \"align-right\" : \"\"} ${className || \"\"}`}\n style={style}\n >\n <div className={styles.fileIcon} style={{ color }}>\n {icon}\n </div>\n\n <div className={styles.fileInfo}>\n {isExternalUrl ? (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={styles.fileLink}\n >\n <Tooltip title={fileName}>\n <div className={styles.fileName}>\n {fileName.length > 15\n ? `${fileName.substring(0, 15)}...`\n : fileName}\n </div>\n </Tooltip>\n </a>\n ) : (\n <Tooltip title={fileName}>\n <div className={styles.fileName}>\n {fileName.length > 15\n ? `${fileName.substring(0, 15)}...`\n : fileName}\n </div>\n </Tooltip>\n )}\n\n {file.status === \"uploading\" ? (\n <Progress\n percent={file.progress}\n size=\"small\"\n showInfo={false}\n strokeColor=\"#1677ff\"\n className={styles.progress}\n />\n ) : (\n fileSize > 0 && (\n <div className={styles.fileSize}>{formatFileSize(fileSize)}</div>\n )\n )}\n\n {file.status === \"error\" && file.errorMessage && (\n <div\n style={{\n fontSize: \"11px\",\n color: \"#ff4d4f\",\n marginTop: \"2px\",\n }}\n >\n {file.errorMessage}\n </div>\n )}\n </div>\n\n {removable && (\n <button\n className={styles.fileRemoveBtn}\n onClick={() => onRemove(fileId)}\n disabled={file.status === \"uploading\"}\n aria-label=\"删除文件\"\n >\n <CloseOutlined />\n </button>\n )}\n </div>\n );\n};\n\nexport default FileGallery;\n"],"mappings":"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"}