@blueking/chat-x 0.0.5 → 0.0.7

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 (85) hide show
  1. package/dist/components/ai-selection/ai-selection.vue.d.ts +2 -2
  2. package/dist/components/index.d.ts +2 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.js +6 -6
  5. package/dist/index.js.map +1 -1
  6. package/dist/mcp/generated/docs/activity-message.md +428 -0
  7. package/dist/mcp/generated/docs/ai-image.md +227 -0
  8. package/dist/mcp/generated/docs/ai-loading.md +129 -0
  9. package/dist/mcp/generated/docs/ai-selection.md +436 -0
  10. package/dist/mcp/generated/docs/animation-text.md +199 -0
  11. package/dist/mcp/generated/docs/assistant-message.md +424 -0
  12. package/dist/mcp/generated/docs/chat-container.md +402 -0
  13. package/dist/mcp/generated/docs/chat-input.md +625 -0
  14. package/dist/mcp/generated/docs/cite-content.md +138 -0
  15. package/dist/mcp/generated/docs/code-content.md +199 -0
  16. package/dist/mcp/generated/docs/common-error-content.md +70 -0
  17. package/dist/mcp/generated/docs/constants.md +216 -0
  18. package/dist/mcp/generated/docs/content-render.md +238 -0
  19. package/dist/mcp/generated/docs/delete-tool.md +188 -0
  20. package/dist/mcp/generated/docs/desc-panel.md +139 -0
  21. package/dist/mcp/generated/docs/execution-summary.md +126 -0
  22. package/dist/mcp/generated/docs/file-content.md +300 -0
  23. package/dist/mcp/generated/docs/file-upload-btn.md +174 -0
  24. package/dist/mcp/generated/docs/flow-message.md +305 -0
  25. package/dist/mcp/generated/docs/highlight-keyword.md +144 -0
  26. package/dist/mcp/generated/docs/image-content.md +178 -0
  27. package/dist/mcp/generated/docs/image-preview-group.md +181 -0
  28. package/dist/mcp/generated/docs/image-preview.md +224 -0
  29. package/dist/mcp/generated/docs/info-message.md +124 -0
  30. package/dist/mcp/generated/docs/key-value-content.md +124 -0
  31. package/dist/mcp/generated/docs/latex-content.md +196 -0
  32. package/dist/mcp/generated/docs/loading-message.md +171 -0
  33. package/dist/mcp/generated/docs/markdown-content.md +186 -0
  34. package/dist/mcp/generated/docs/markdown-latex.md +208 -0
  35. package/dist/mcp/generated/docs/markdown-mermaid.md +250 -0
  36. package/dist/mcp/generated/docs/mermaid-content.md +185 -0
  37. package/dist/mcp/generated/docs/message-container.md +534 -0
  38. package/dist/mcp/generated/docs/message-render.md +329 -0
  39. package/dist/mcp/generated/docs/message-tools.md +376 -0
  40. package/dist/mcp/generated/docs/messages.md +472 -0
  41. package/dist/mcp/generated/docs/overflow-tips.md +209 -0
  42. package/dist/mcp/generated/docs/reasoning-message.md +233 -0
  43. package/dist/mcp/generated/docs/reference-content.md +132 -0
  44. package/dist/mcp/generated/docs/scroll-btn.md +155 -0
  45. package/dist/mcp/generated/docs/selection-footer.md +75 -0
  46. package/dist/mcp/generated/docs/shortcut-btn.md +202 -0
  47. package/dist/mcp/generated/docs/shortcut-btns.md +264 -0
  48. package/dist/mcp/generated/docs/shortcut-render.md +418 -0
  49. package/dist/mcp/generated/docs/text-content.md +74 -0
  50. package/dist/mcp/generated/docs/theme.md +388 -0
  51. package/dist/mcp/generated/docs/tool-btn.md +254 -0
  52. package/dist/mcp/generated/docs/tool-message.md +217 -0
  53. package/dist/mcp/generated/docs/toolcall-render.md +299 -0
  54. package/dist/mcp/generated/docs/use-animation-text.md +198 -0
  55. package/dist/mcp/generated/docs/use-clipboard.md +206 -0
  56. package/dist/mcp/generated/docs/use-command-selection.md +128 -0
  57. package/dist/mcp/generated/docs/use-container-scroll.md +56 -0
  58. package/dist/mcp/generated/docs/use-custom-tab.md +122 -0
  59. package/dist/mcp/generated/docs/use-global-config.md +154 -0
  60. package/dist/mcp/generated/docs/use-menu-keydown.md +164 -0
  61. package/dist/mcp/generated/docs/use-message-group.md +175 -0
  62. package/dist/mcp/generated/docs/use-observer-visible-list.md +189 -0
  63. package/dist/mcp/generated/docs/use-parent-scrolling.md +46 -0
  64. package/dist/mcp/generated/docs/user-feedback.md +229 -0
  65. package/dist/mcp/generated/docs/user-message.md +347 -0
  66. package/dist/mcp/generated/index.json +1311 -0
  67. package/dist/mcp/index.d.ts +2 -0
  68. package/dist/mcp/index.js +42 -0
  69. package/dist/mcp/index.js.map +1 -0
  70. package/dist/mcp/server.d.ts +2 -0
  71. package/dist/mcp/server.js +43 -0
  72. package/dist/mcp/server.js.map +1 -0
  73. package/dist/mcp/tools/get-component-doc.d.ts +19 -0
  74. package/dist/mcp/tools/get-component-doc.js +60 -0
  75. package/dist/mcp/tools/get-component-doc.js.map +1 -0
  76. package/dist/mcp/tools/list-components.d.ts +35 -0
  77. package/dist/mcp/tools/list-components.js +147 -0
  78. package/dist/mcp/tools/list-components.js.map +1 -0
  79. package/dist/mcp/tools/search-docs.d.ts +14 -0
  80. package/dist/mcp/tools/search-docs.js +82 -0
  81. package/dist/mcp/tools/search-docs.js.map +1 -0
  82. package/dist/mcp/utils/doc-loader.d.ts +35 -0
  83. package/dist/mcp/utils/doc-loader.js +64 -0
  84. package/dist/mcp/utils/doc-loader.js.map +1 -0
  85. package/package.json +5 -7
@@ -0,0 +1,300 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ FileContent 展示消息或输入区附件列表:图片显示缩略图并可进入 ImagePreview,文档以卡片展示文件名、类型与大小。 支持删除、图片加载失败占位及仅有远端文件名的降级展示。
5
+
6
+ ### 关联组件
7
+ - **image-preview** — 点击图片缩略图打开全屏预览
8
+ - **user-message** — 用户消息只读展示附件列表
9
+
10
+ ---
11
+ <!-- FULL DOC -->
12
+
13
+ # FileContent 文件内容展示
14
+
15
+ > **层级**:分子组件 · **功能域**:文件与图片
16
+
17
+ 文件列表展示组件,支持图片缩略图预览、点击图片全屏预览(`ImagePreview`)、文档卡片展示(文件名/扩展名/文件大小)、图片加载失败占位和删除操作。
18
+
19
+ ## 渲染决策逻辑
20
+
21
+ 每个文件按以下优先级决定渲染方式:
22
+
23
+ ```
24
+ file.url 存在?
25
+ ├── 是 → 图片模式(用 file.url 作为 <img src>,点击可全屏预览)
26
+ │ 图片加载失败 → 错误占位(粉色背景 + 红色边框 + 灰色图标)
27
+ └── 否 → 检查 mimeType 或 file.file?.type
28
+ ├── 以 'image/' 开头 → 图片模式(用 getFilePreviewUrl(file.file) 作为 src,点击可全屏预览)
29
+ └── 其他 → 文档卡片模式(图标 + 文件名 + 扩展名 + 大小)
30
+ ```
31
+
32
+ > **注意**:`file.url` 存在时**无论文件 MIME 类型是什么**都会走图片模式。若要将 PDF 等非图片文件显示为文档卡片,确保不设置 `url` 字段(或设为 `undefined`)。
33
+
34
+ ## 基础用法(文档文件)
35
+
36
+ 无 `url` 字段、MIME 类型非 `image/*` 的文件,渲染为文档卡片(文档图标 + 文件名 + 扩展名 + 大小):
37
+
38
+ ```vue
39
+ <template>
40
+ <FileContent
41
+ :files="files"
42
+ @delete-file="handleDeleteFile"
43
+ />
44
+ </template>
45
+
46
+ <script setup lang="ts">
47
+ import { ref } from 'vue';
48
+ import { FileContent, type UploadFile } from '@blueking/chat-x';
49
+
50
+ const files = ref<Partial<UploadFile>[]>([
51
+ { file: new File(['content'], 'report.pdf', { type: 'application/pdf' }) },
52
+ { file: new File(['content'], 'data.xlsx', { type: 'application/vnd.ms-excel' }) },
53
+ { file: new File(['readme'], 'README.md', { type: 'text/markdown' }) },
54
+ ]);
55
+
56
+ const handleDeleteFile = (file: Partial<UploadFile>) => {
57
+ files.value = files.value.filter(f => f !== file);
58
+ };
59
+ </script>
60
+ ```
61
+
62
+ **渲染效果**(悬停文件卡片,右上角出现删除按钮)
63
+
64
+ ## 图片文件预览
65
+
66
+ 设置了 `url` 字段时,渲染为 48×48 的图片缩略图(`cursor: zoom-in`)。点击图片可打开全屏预览(内部集成 `ImagePreview` 组件),支持缩放、旋转、下载等操作:
67
+
68
+ ```vue
69
+ <script setup lang="ts">
70
+ import { ref } from 'vue';
71
+ import { type UploadFile } from '@blueking/chat-x';
72
+
73
+ const imageFiles = ref<Partial<UploadFile>[]>([
74
+ {
75
+ url: 'https://example.com/cat.jpg', // 有 url → 图片模式
76
+ filename: 'cat.jpg',
77
+ mimeType: 'image/jpeg',
78
+ file: new File([''], 'cat.jpg', { type: 'image/jpeg' }),
79
+ },
80
+ {
81
+ url: 'https://example.com/dog.png',
82
+ filename: 'dog.png',
83
+ mimeType: 'image/png',
84
+ file: new File([''], 'dog.png', { type: 'image/png' }),
85
+ },
86
+ ]);
87
+ </script>
88
+ ```
89
+
90
+ **渲染效果**
91
+
92
+ ## 图片点击预览
93
+
94
+ 图片模式下点击缩略图会打开全屏预览弹窗。多张图片时支持左右切换。加载失败的图片不会出现在预览列表中:
95
+
96
+ ```vue
97
+ <template>
98
+ <FileContent :files="imageFiles" />
99
+ </template>
100
+
101
+ <script setup lang="ts">
102
+ import { ref } from 'vue';
103
+ import { FileContent, type UploadFile } from '@blueking/chat-x';
104
+
105
+ const imageFiles = ref<Partial<UploadFile>[]>([
106
+ { url: 'https://example.com/cat.jpg', filename: 'cat.jpg', mimeType: 'image/jpeg' },
107
+ { url: 'https://example.com/dog.png', filename: 'dog.png', mimeType: 'image/png' },
108
+ ]);
109
+ </script>
110
+ ```
111
+
112
+ > **预览行为**:组件内部自动维护 `ImagePreview` 实例,无需外部管理预览状态。只有加载成功的图片才会进入预览列表,加载失败的图片被自动过滤。
113
+
114
+ ## 图片加载失败
115
+
116
+ `<img>` 触发 `onerror` 时,切换为粉色背景 + 红色边框的错误占位:
117
+
118
+ ## 混合文件(图片 + 文档)
119
+
120
+ 同一列表中可同时包含图片和文档文件,横向 flex 布局、换行排列:
121
+
122
+ ```vue
123
+ <script setup lang="ts">
124
+ const files = [
125
+ { url: 'https://example.com/photo.jpg', filename: 'photo.jpg', mimeType: 'image/jpeg' },
126
+ { file: new File(['content'], 'report.pdf', { type: 'application/pdf' }) },
127
+ { file: new File(['data'], 'data.xlsx', { type: 'application/vnd.ms-excel' }) },
128
+ ];
129
+ </script>
130
+ ```
131
+
132
+ **渲染效果**
133
+
134
+ ## 只读模式(readonly)
135
+
136
+ 传入 `readonly` 时,隐藏删除按钮,适用于用户消息中展示已发送的文件:
137
+
138
+ ```vue
139
+ <FileContent :files="files" :readonly="true" />
140
+ ```
141
+
142
+ **渲染效果**(悬停无删除按钮)
143
+
144
+ ## 仅有 filename(无 File 对象)
145
+
146
+ 从服务端恢复的历史文件没有 `File` 对象时,仍可渲染文档卡片,但**文件大小不显示**,扩展名从 `filename` 或 `mimeType` 推断:
147
+
148
+ ```vue
149
+ <script setup lang="ts">
150
+ const remoteFiles = [
151
+ // 无 file 对象,文件大小显示为空
152
+ { filename: 'server-report.pdf', mimeType: 'application/pdf' },
153
+ { filename: 'config.json', mimeType: 'application/json' },
154
+ ];
155
+ </script>
156
+ ```
157
+
158
+ **渲染效果**(大小区域为空)
159
+
160
+ ## 在 ChatInput 中使用
161
+
162
+ `FileContent` 由 `ChatInput` 内部自动渲染在文件预览区(`slot#files` 的默认内容),通常不需要手动引入。当 `ChatInput` 收到上传文件时,自动更新 `uploadFiles` 并渲染:
163
+
164
+ ```vue
165
+ <template>
166
+ <ChatInput
167
+ v-model="inputValue"
168
+ :on-send-message="handleSendMessage"
169
+ :on-upload="handleUpload"
170
+ />
171
+ </template>
172
+ ```
173
+
174
+ 若需自定义文件展示,通过 `slot#files` 替换默认 `FileContent`:
175
+
176
+ ```vue
177
+ <template>
178
+ <ChatInput
179
+ v-model="inputValue"
180
+ :on-upload="handleUpload"
181
+ >
182
+ <template #files="{ files }">
183
+ <!-- 自定义文件列表 UI -->
184
+ <FileContent
185
+ :files="files"
186
+ readonly
187
+ />
188
+ </template>
189
+ </ChatInput>
190
+ </template>
191
+ ```
192
+
193
+ ## API
194
+
195
+ ### Props
196
+
197
+ | 属性名 | 类型 | 默认值 | 必填 | 说明 |
198
+ | -------- | ----------------------- | ------- | ---- | ------------------------------- |
199
+ | files | `Partial<UploadFile>[]` | - | ✅ | 文件列表 |
200
+ | readonly | `boolean` | `false` | - | 只读模式,`true` 时隐藏删除按钮 |
201
+
202
+ ### Events
203
+
204
+ | 事件名 | 参数 | 触发时机 |
205
+ | ---------- | ----------------------------- | ------------------ |
206
+ | deleteFile | `(file: Partial<UploadFile>)` | 点击删除按钮时触发 |
207
+
208
+ ## 渲染模式详解
209
+
210
+ ### 图片模式
211
+
212
+ | 条件 | 图片 src | 点击行为 |
213
+ | ---------------------------------- | -------------------------------- | -------------- |
214
+ | `file.url` 有值(优先) | `file.url` | 打开全屏预览 |
215
+ | MIME 以 `image/` 开头(无 url 时) | `URL.createObjectURL(file.file)` | 打开全屏预览 |
216
+ | 图片加载失败 | 错误占位 | 不进入预览列表 |
217
+
218
+ ### 文档卡片模式
219
+
220
+ | 字段 | 取值优先级 |
221
+ | -------- | ------------------------------------------------------------------------------------------------------------ |
222
+ | 文件名 | `file.filename` → `file.file?.name` |
223
+ | 扩展名 | 有 `file.file`:取文件名最后一段 `.xxx` 或 MIME 后缀<br>无 `file.file`:取 `filename` 后缀 → `mimeType` 后缀 |
224
+ | 文件大小 | 仅当有 `file.file`(`File` 对象)时显示,否则为空 |
225
+
226
+ ## 类型定义
227
+
228
+ ```typescript
229
+ import type { UploadFile, BinaryInputContent } from '@blueking/chat-x';
230
+
231
+ // 上传状态(ChatInput 内部使用,FileContent 不使用此字段)
232
+ enum UploadStatus {
233
+ Pending = 'pending', // 上传中
234
+ Success = 'success', // 上传成功
235
+ Error = 'error', // 上传失败
236
+ }
237
+
238
+ // 上传文件(FileContent 的 files 数组中每一项)
239
+ type UploadFile = BinaryInputContent & {
240
+ file?: File; // 原始 File 对象,无则文件大小不显示
241
+ status?: UploadStatus; // 上传状态(ChatInput 使用,FileContent 不消费)
242
+ };
243
+
244
+ // 二进制内容基础类型
245
+ interface BinaryInputContent {
246
+ type: 'binary';
247
+ url?: string; // 文件访问地址,存在时强制走图片模式
248
+ filename?: string; // 文件名(用于文档卡片)
249
+ mimeType?: string; // MIME 类型(用于图片判断和扩展名推断)
250
+ }
251
+ ```
252
+
253
+ ## 工具函数(内部使用)
254
+
255
+ ```typescript
256
+ // 判断是否走图片模式
257
+ // ⚠️ file.url 存在时直接返回 true,不判断 MIME 类型
258
+ const isImage = (file: Partial<UploadFile>): boolean => {
259
+ if (file.url) return true;
260
+ return isImageFile(file.mimeType || file.file?.type);
261
+ };
262
+
263
+ // 判断 MIME 类型是否为图片
264
+ const isImageFile = (mimeType?: string): boolean => {
265
+ if (!mimeType) return false;
266
+ return mimeType.startsWith('image/');
267
+ };
268
+
269
+ // 获取 File 对象的临时预览 URL(无 url 时的图片模式备选)
270
+ const getFilePreviewUrl = (file?: File): string => {
271
+ if (!file) return '';
272
+ return URL.createObjectURL(file);
273
+ };
274
+
275
+ // 获取文件扩展名
276
+ const getFileExtension = (file?: File): string => {
277
+ if (!file) return '';
278
+ return file.name.split('.').pop() || file.type?.split('/').pop() || '';
279
+ };
280
+
281
+ // 格式化文件大小(需要 File 对象)
282
+ const formatFileSize = (file?: File): string => {
283
+ if (!file) return '';
284
+ const size = file.size;
285
+ const units = ['B', 'KB', 'M', 'GB'];
286
+ const index = Math.floor(Math.log2(size || 1) / 10);
287
+ return `${(size / Math.pow(1024, index)).toFixed(2)} ${units[index]}`;
288
+ };
289
+ ```
290
+
291
+ ## 使用场景
292
+
293
+ - **ChatInput 文件预览区**:上传文件后在编辑器上方展示待发送的文件列表(可删除)
294
+ - **用户消息展示**:`UserMessage` 内部以 `readonly` 模式展示已发送的图片和附件
295
+ - **历史消息回放**:服务端返回的文件信息(无 `File` 对象)也能正常渲染文档卡片
296
+
297
+ ## 关联组件
298
+
299
+ - [ImagePreview](./image-preview.md) — 图片全屏预览
300
+ - [UserMessage](./user-message.md) — 用户消息内附件展示
@@ -0,0 +1,174 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ FileUploadBtn 提供隐藏 file input 与图标按钮,选择文件后 emit upload,并内置数量与单文件大小上限校验。 常用于 ChatInput 工具条;与 FileContent 等展示列表配合形成「选择 → 展示 → 发送」链路。
5
+
6
+ ### 关联组件
7
+ - **chat-input** — 输入区附件上传按钮常见挂载位置
8
+ - **file-content** — 选中文件常以列表形式展示待发送内容
9
+
10
+ ---
11
+ <!-- FULL DOC -->
12
+
13
+ # FileUploadBtn 文件上传按钮
14
+
15
+ > **层级**:原子组件 · **功能域**:文件与图片
16
+
17
+ 聊天输入框内置的文件上传触发按钮,点击后弹出系统文件选择框。内部包含隐藏的 `<input type="file">` 与可见的图标按钮,并内置文件数量及大小校验逻辑。
18
+
19
+ ## 组件结构
20
+
21
+ ```
22
+ .file-upload-btn(display: flex,align-items: center)
23
+ ├── input[type="file"](.file-upload-btn-input,display: none,multiple,:accept)
24
+ │ 触发后走 handleFileInputChange → 校验 → emit upload → target.value = ''
25
+ └── span.ai-shortcut-btn.file-upload-btn-icon(24×24px,color: #979ba5,hover: cursor: pointer)
26
+ v-tippy: "上传图片, 最多支持上传 3 个, 最大支持 2.4MB"(theme: ai-chat-box,offset: [0, 16],可通过 tippyOptions 扩展)
27
+ @click → fileInputRef.click()
28
+ └── <slot> 默认:FileUploadIcon
29
+ ```
30
+
31
+ ## 文件校验逻辑
32
+
33
+ ```
34
+ 用户选择文件
35
+
36
+ ├─ files.length > Math.max(maxFiles, MAX_UPLOAD_FILES[3])
37
+ │ ↓ true → bkui-vue Message.error("最多上传 N 个文件"),终止,不 emit
38
+
39
+ └─ emit('upload', files.filter(f => f.size > 0 && f.size < MAX_UPLOAD_FILE_SIZE[2.5MB]))
40
+
41
+ target.value = ''(重置 input,允许再次选择同一文件)
42
+ ```
43
+
44
+ **关键边界行为**:
45
+
46
+ | 场景 | 结果 |
47
+ | ----------------------------------------- | ----------------------------------------------------------- |
48
+ | 文件数超过 `Math.max(maxFiles, 3)` | 弹出错误 toast,**不触发** `upload` |
49
+ | 文件数未超限,但部分文件被大小过滤 | **仍触发** `upload`,payload 为过滤后的数组(可能为空数组) |
50
+ | `file.size === 0` | 被过滤(空文件) |
51
+ | `file.size >= 2.5MB`(即 `2621440` 字节) | 被过滤(使用严格小于 `<`,等于 2.5MB 也会被过滤) |
52
+ | `maxFiles` 设为小于 3 的值(如 `1`) | 实际限制取 `Math.max(1, 3) = 3`,不低于全局下限 |
53
+ | 选择后取消 | `files.length === 0`,不触发 `upload` |
54
+
55
+ > `multiple` prop 声明存在但当前模板中 `input` 的 `multiple` 属性为**硬编码**(非 `:multiple="multiple"` 绑定),始终允许多选,该 prop 暂时无实际效果。
56
+
57
+ ## 基础用法
58
+
59
+ ```vue
60
+ <template>
61
+ <FileUploadBtn @upload="handleUpload" />
62
+ </template>
63
+
64
+ <script setup lang="ts">
65
+ import { FileUploadBtn } from '@blueking/chat-x';
66
+
67
+ const handleUpload = (files: File[]) => {
68
+ console.log(
69
+ '选中文件:',
70
+ files.map(f => `${f.name}(${f.size}B)`),
71
+ );
72
+ };
73
+ </script>
74
+ ```
75
+
76
+ ## 限制文件类型
77
+
78
+ 通过 `accept` 属性控制系统文件选择框的过滤条件,遵循 `<input type="file">` 的 `accept` 规范:
79
+
80
+ ```vue
81
+ <template>
82
+ <!-- 仅图片(默认) -->
83
+ <FileUploadBtn
84
+ accept="image/*"
85
+ @upload="handleUpload"
86
+ />
87
+
88
+ <!-- 文档类型 -->
89
+ <FileUploadBtn
90
+ accept=".pdf,.doc,.docx,.xlsx,.pptx"
91
+ @upload="handleUpload"
92
+ />
93
+
94
+ <!-- 不限制类型 -->
95
+ <FileUploadBtn
96
+ accept="*/*"
97
+ @upload="handleUpload"
98
+ />
99
+ </template>
100
+ ```
101
+
102
+ > `accept` 仅影响文件选择框的过滤 UI,不做服务端验证,请在 `upload` 回调中自行校验 MIME 类型。
103
+
104
+ ## 限制上传数量
105
+
106
+ `maxFiles` 限制单次选择的文件上传上限,实际生效值为 `Math.max(maxFiles, 3)`,不会低于全局下限 3:
107
+
108
+ ```vue
109
+ <template>
110
+ <!-- maxFiles=5:可一次选 5 个文件 -->
111
+ <FileUploadBtn
112
+ :max-files="5"
113
+ @upload="handleUpload"
114
+ />
115
+
116
+ <!-- maxFiles=1:实际等效 maxFiles=3(取 Math.max(1,3)) -->
117
+ <FileUploadBtn
118
+ :max-files="1"
119
+ @upload="handleUpload"
120
+ />
121
+ </template>
122
+ ```
123
+
124
+ ## 自定义图标
125
+
126
+ 通过默认插槽替换上传图标:
127
+
128
+ ```vue
129
+ <template>
130
+ <FileUploadBtn @upload="handleUpload">
131
+ <span style="font-size: 16px; line-height: 1;">📎</span>
132
+ </FileUploadBtn>
133
+ </template>
134
+ ```
135
+
136
+ ## API
137
+
138
+ ### Props
139
+
140
+ | 属性名 | 类型 | 默认值 | 说明 |
141
+ | ------------ | -------------- | ----------- | ------------------------------------------------------ |
142
+ | accept | `string` | `'image/*'` | 文件选择框过滤类型,遵循 `<input accept>` 规范 |
143
+ | maxFiles | `number` | `3` | 单次选择文件数上限;实际限制为 `Math.max(maxFiles, 3)` |
144
+ | multiple | `boolean` | `true` | 声明属性(当前版本未实际绑定到 input,始终多选) |
145
+ | tippyOptions | `AITippyProps` | — | 扩展 tooltip 配置,会与内置配置合并 |
146
+
147
+ ### Events
148
+
149
+ | 事件名 | 参数 | 说明 |
150
+ | ------ | ----------------- | ----------------------------------------------------------------------------------------- |
151
+ | upload | `(files: File[])` | 校验通过后触发;`files` 为过滤掉空文件和超大文件(≥ 2.5MB)后的数组;超出数量限制时不触发 |
152
+
153
+ ### Slots
154
+
155
+ | 插槽名 | 说明 |
156
+ | ------- | ----------------------------------------------- |
157
+ | default | 自定义按钮图标内容,默认为内置 `FileUploadIcon` |
158
+
159
+ ## 使用场景
160
+
161
+ `FileUploadBtn` 由 `ChatInput` 组件内置,当 `ChatInput` 的 `supportUpload` prop 为 `true`(默认值)时自动渲染。一般不需要单独引入,除非构建完全自定义的输入区域。
162
+
163
+ ## 类型定义
164
+
165
+ ```typescript
166
+ import type { TippyOptions } from 'vue-tippy';
167
+
168
+ type AITippyProps = Partial<Omit<TippyOptions, 'content' | 'getReferenceClientRect' | 'theme' | 'triggerTarget'>>;
169
+ ```
170
+
171
+ ## 关联组件
172
+
173
+ - [ChatInput](../molecular/chat-input.md) — 默认内置上传入口
174
+ - [FileContent](../molecular/file-content.md) — 选中文件列表展示