(pageId: string)
| 52 | } |
| 53 | |
| 54 | export function useAttachment(pageId: string): UseAttachmentResult { |
| 55 | const { getState, addPendingAttachment, removePendingAttachment, clearPendingAttachments } = |
| 56 | useChatUIStore() |
| 57 | const pendingAttachments = getState(pageId).pendingAttachments |
| 58 | |
| 59 | // 从拖拽或粘贴的 File 对象添加附件 |
| 60 | const addAttachments = useCallback( |
| 61 | async (files: FileList | File[]) => { |
| 62 | const fileArray = Array.from(files) |
| 63 | |
| 64 | for (const file of fileArray) { |
| 65 | // 类型校验 |
| 66 | if (!ALLOWED_TYPES.includes(file.type)) { |
| 67 | console.warn(`不支持的文件类型: ${file.type}`) |
| 68 | continue |
| 69 | } |
| 70 | |
| 71 | // 大小校验 |
| 72 | if (file.size > MAX_SIZE) { |
| 73 | console.warn(`文件过大: ${file.name} (${(file.size / 1024 / 1024).toFixed(2)}MB)`) |
| 74 | continue |
| 75 | } |
| 76 | |
| 77 | const fileId = generateId() |
| 78 | |
| 79 | // 读取文件为 base64 |
| 80 | const base64Content = await readFileAsBase64(file) |
| 81 | |
| 82 | // 保存到 temp 目录 |
| 83 | const result = await window.api.attachment.save({ |
| 84 | fileId, |
| 85 | fileName: file.name, |
| 86 | base64Content |
| 87 | }) |
| 88 | |
| 89 | if (result.success && result.localPath) { |
| 90 | const attachment: FileAttachment = { |
| 91 | id: fileId, |
| 92 | name: file.name, |
| 93 | type: file.type, |
| 94 | size: file.size, |
| 95 | localPath: result.localPath, |
| 96 | createdAt: Date.now() |
| 97 | } |
| 98 | addPendingAttachment(pageId, attachment) |
| 99 | } else { |
| 100 | console.error('保存附件失败:', result.error) |
| 101 | } |
| 102 | } |
| 103 | }, |
| 104 | [pageId, addPendingAttachment] |
| 105 | ) |
| 106 | |
| 107 | // 从文件选择器添加附件 |
| 108 | const addAttachmentsFromSelector = useCallback(async () => { |
| 109 | const result = await window.api.selectFiles({ |
| 110 | multiple: true, |
| 111 | filters: [{ name: 'Images', extensions: ['jpg', 'jpeg', 'png', 'gif', 'webp'] }] |
no test coverage detected