@blueking/chat-x 0.0.51-beta.5 → 0.0.52-dev.1

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 (198) hide show
  1. package/README.md +15 -8
  2. package/dist/ag-ui/types/contents.d.ts +2 -0
  3. package/dist/ag-ui/types/messages.d.ts +6 -1
  4. package/dist/common/constants.d.ts +2 -0
  5. package/dist/components/ai-buttons/add-menu-btn/add-menu-btn.vue.d.ts +24 -0
  6. package/dist/components/chat-content/collapsible-content/collapsible-content.vue.d.ts +28 -0
  7. package/dist/components/chat-content/file-content/upload-file-item.vue.d.ts +5 -2
  8. package/dist/components/chat-content/file-content/upload-image-item.vue.d.ts +1 -0
  9. package/dist/components/chat-content/flow-agent-content/use-flow-node-actions.d.ts +1 -1
  10. package/dist/components/chat-input/ai-slash-input/ai-slash-input.vue.d.ts +21 -10
  11. package/dist/components/chat-input/ai-slash-input/command.d.ts +6 -3
  12. package/dist/components/chat-input/ai-slash-input/constants.d.ts +2 -0
  13. package/dist/components/chat-input/ai-slash-input/use-menu-trigger.d.ts +17 -0
  14. package/dist/components/chat-input/build-default-placeholder.d.ts +9 -3
  15. package/dist/components/chat-input/chat-input.vue.d.ts +30 -18
  16. package/dist/components/chat-input/input-menu/constants.d.ts +60 -0
  17. package/dist/components/chat-input/input-menu/index.d.ts +4 -0
  18. package/dist/components/chat-input/input-menu/input-menu-option.vue.d.ts +14 -0
  19. package/dist/components/chat-input/input-menu/input-menu-panel.vue.d.ts +17 -0
  20. package/dist/components/chat-input/input-menu/use-input-menu.d.ts +22 -0
  21. package/dist/components/chat-input/model-selector/types.d.ts +3 -2
  22. package/dist/components/chat-message/message-container/message-container.vue.d.ts +1 -1
  23. package/dist/components/chat-message/user-message/user-message.vue.d.ts +1 -1
  24. package/dist/components/mention/create-mention-tippy.d.ts +27 -0
  25. package/dist/components/mention/index.d.ts +4 -0
  26. package/dist/components/{chat-input/ai-slash-input/ai-prompt-list/ai-prompt-list.vue.d.ts → mention/mention-popover.vue.d.ts} +3 -2
  27. package/dist/components/{chat-input/ai-slash-input/ai-skill-list/ai-skill-list.vue.d.ts → mention/mention-tag.vue.d.ts} +7 -3
  28. package/dist/components/{chat-input/ai-slash-input/ai-slash-menu/ai-slash-menu.vue.d.ts → mention/mention-text.vue.d.ts} +3 -3
  29. package/dist/components/resource-icon/index.d.ts +1 -0
  30. package/dist/components/resource-icon/resource-icon.vue.d.ts +11 -0
  31. package/dist/composables/index.d.ts +1 -0
  32. package/dist/composables/use-artifact-preview.d.ts +5 -2
  33. package/dist/composables/use-common.d.ts +0 -9
  34. package/dist/composables/use-global-config.d.ts +4 -0
  35. package/dist/composables/use-input-mention.d.ts +13 -0
  36. package/dist/composables/use-message-group.d.ts +1011 -72
  37. package/dist/icons/index.d.ts +1 -0
  38. package/dist/icons/input.d.ts +21 -0
  39. package/dist/icons/menu-item.d.ts +22 -0
  40. package/dist/index.css +1 -1
  41. package/dist/index.js +4953 -4429
  42. package/dist/index.js.map +1 -1
  43. package/dist/lang/lang.d.ts +13 -3
  44. package/dist/mcp/generated/docs/activity-message.md +3 -3
  45. package/dist/mcp/generated/docs/add-menu-btn.md +91 -0
  46. package/dist/mcp/generated/docs/ai-slash-input.md +72 -26
  47. package/dist/mcp/generated/docs/assistant-message.md +7 -1
  48. package/dist/mcp/generated/docs/chat-container.md +45 -6
  49. package/dist/mcp/generated/docs/chat-input.md +327 -483
  50. package/dist/mcp/generated/docs/collapsible-content.md +78 -0
  51. package/dist/mcp/generated/docs/constants.md +36 -3
  52. package/dist/mcp/generated/docs/execution-summary.md +1 -23
  53. package/dist/mcp/generated/docs/file-artifact-panel.md +24 -5
  54. package/dist/mcp/generated/docs/file-content.md +4 -0
  55. package/dist/mcp/generated/docs/file-upload-btn.md +15 -12
  56. package/dist/mcp/generated/docs/flow-agent-content.md +10 -12
  57. package/dist/mcp/generated/docs/input-menu-panel.md +166 -0
  58. package/dist/mcp/generated/docs/mention-tag.md +83 -0
  59. package/dist/mcp/generated/docs/mention-text.md +86 -0
  60. package/dist/mcp/generated/docs/message-container.md +1 -1
  61. package/dist/mcp/generated/docs/message-render.md +1 -1
  62. package/dist/mcp/generated/docs/message-tools.md +15 -4
  63. package/dist/mcp/generated/docs/messages.md +3 -0
  64. package/dist/mcp/generated/docs/model-selector.md +4 -2
  65. package/dist/mcp/generated/docs/overflow-tips.md +3 -3
  66. package/dist/mcp/generated/docs/resource-icon.md +102 -0
  67. package/dist/mcp/generated/docs/text-content.md +7 -3
  68. package/dist/mcp/generated/docs/theme.md +27 -35
  69. package/dist/mcp/generated/docs/use-artifact-preview.md +7 -3
  70. package/dist/mcp/generated/docs/use-command-selection.md +1 -1
  71. package/dist/mcp/generated/docs/use-container-scroll.md +2 -1
  72. package/dist/mcp/generated/docs/use-flow-node-actions.md +8 -15
  73. package/dist/mcp/generated/docs/use-global-config.md +11 -4
  74. package/dist/mcp/generated/docs/use-input-mention.md +119 -0
  75. package/dist/mcp/generated/docs/use-menu-keydown.md +15 -16
  76. package/dist/mcp/generated/docs/use-message-group.md +3 -6
  77. package/dist/mcp/generated/docs/user-message.md +39 -17
  78. package/dist/mcp/generated/index.json +233 -81
  79. package/dist/types/editor.d.ts +0 -29
  80. package/dist/types/index.d.ts +1 -0
  81. package/dist/types/input-menu.d.ts +46 -0
  82. package/dist/utils/artifact-tags.d.ts +36 -0
  83. package/dist/utils/collect-message-artifacts.d.ts +14 -0
  84. package/dist/utils/file.d.ts +3 -3
  85. package/dist/utils/index.d.ts +2 -1
  86. package/dist/utils/upload-file.d.ts +6 -1
  87. package/package.json +3 -2
  88. package/skills/blueking-chat-x/SKILL.md +143 -0
  89. package/skills/blueking-chat-x/references/_index.md +153 -0
  90. package/skills/blueking-chat-x/references/components/activity-layout.md +134 -0
  91. package/skills/blueking-chat-x/references/components/activity-message.md +486 -0
  92. package/skills/blueking-chat-x/references/components/add-menu-btn.md +88 -0
  93. package/skills/blueking-chat-x/references/components/ai-image.md +230 -0
  94. package/skills/blueking-chat-x/references/components/ai-loading.md +131 -0
  95. package/skills/blueking-chat-x/references/components/ai-selection.md +439 -0
  96. package/skills/blueking-chat-x/references/components/ai-slash-input.md +102 -0
  97. package/skills/blueking-chat-x/references/components/animation-text.md +202 -0
  98. package/skills/blueking-chat-x/references/components/assistant-message.md +504 -0
  99. package/skills/blueking-chat-x/references/components/chat-container.md +912 -0
  100. package/skills/blueking-chat-x/references/components/chat-input.md +614 -0
  101. package/skills/blueking-chat-x/references/components/cite-content.md +142 -0
  102. package/skills/blueking-chat-x/references/components/code-content.md +211 -0
  103. package/skills/blueking-chat-x/references/components/collapsible-content.md +76 -0
  104. package/skills/blueking-chat-x/references/components/common-error-content.md +73 -0
  105. package/skills/blueking-chat-x/references/components/content-render.md +233 -0
  106. package/skills/blueking-chat-x/references/components/delete-tool.md +191 -0
  107. package/skills/blueking-chat-x/references/components/desc-panel.md +162 -0
  108. package/skills/blueking-chat-x/references/components/detail-section.md +91 -0
  109. package/skills/blueking-chat-x/references/components/execution-summary.md +150 -0
  110. package/skills/blueking-chat-x/references/components/file-artifact-panel.md +307 -0
  111. package/skills/blueking-chat-x/references/components/file-content.md +340 -0
  112. package/skills/blueking-chat-x/references/components/file-icon.md +109 -0
  113. package/skills/blueking-chat-x/references/components/file-upload-btn.md +162 -0
  114. package/skills/blueking-chat-x/references/components/flow-agent-content.md +266 -0
  115. package/skills/blueking-chat-x/references/components/flow-agent-node-detail.md +236 -0
  116. package/skills/blueking-chat-x/references/components/highlight-keyword.md +146 -0
  117. package/skills/blueking-chat-x/references/components/image-content.md +182 -0
  118. package/skills/blueking-chat-x/references/components/image-preview-group.md +184 -0
  119. package/skills/blueking-chat-x/references/components/image-preview.md +226 -0
  120. package/skills/blueking-chat-x/references/components/info-message.md +144 -0
  121. package/skills/blueking-chat-x/references/components/input-attachment.md +49 -0
  122. package/skills/blueking-chat-x/references/components/input-info-alert.md +42 -0
  123. package/skills/blueking-chat-x/references/components/input-menu-panel.md +162 -0
  124. package/skills/blueking-chat-x/references/components/interrupt-message.md +212 -0
  125. package/skills/blueking-chat-x/references/components/key-value-content.md +128 -0
  126. package/skills/blueking-chat-x/references/components/knowledge-rag-content.md +122 -0
  127. package/skills/blueking-chat-x/references/components/latex-content.md +200 -0
  128. package/skills/blueking-chat-x/references/components/loading-message.md +192 -0
  129. package/skills/blueking-chat-x/references/components/markdown-content.md +232 -0
  130. package/skills/blueking-chat-x/references/components/mention-tag.md +79 -0
  131. package/skills/blueking-chat-x/references/components/mention-text.md +83 -0
  132. package/skills/blueking-chat-x/references/components/mermaid-content.md +189 -0
  133. package/skills/blueking-chat-x/references/components/message-container.md +645 -0
  134. package/skills/blueking-chat-x/references/components/message-loading.md +118 -0
  135. package/skills/blueking-chat-x/references/components/message-render.md +327 -0
  136. package/skills/blueking-chat-x/references/components/message-time.md +177 -0
  137. package/skills/blueking-chat-x/references/components/message-tools.md +427 -0
  138. package/skills/blueking-chat-x/references/components/model-selector.md +157 -0
  139. package/skills/blueking-chat-x/references/components/preview-toolbar.md +42 -0
  140. package/skills/blueking-chat-x/references/components/questions-container.md +85 -0
  141. package/skills/blueking-chat-x/references/components/reasoning-message.md +232 -0
  142. package/skills/blueking-chat-x/references/components/reference-content.md +135 -0
  143. package/skills/blueking-chat-x/references/components/reference-doc-content.md +109 -0
  144. package/skills/blueking-chat-x/references/components/resource-icon.md +98 -0
  145. package/skills/blueking-chat-x/references/components/scroll-btn.md +159 -0
  146. package/skills/blueking-chat-x/references/components/selection-footer.md +78 -0
  147. package/skills/blueking-chat-x/references/components/selection-question.md +88 -0
  148. package/skills/blueking-chat-x/references/components/shortcut-btn.md +204 -0
  149. package/skills/blueking-chat-x/references/components/shortcut-btns.md +266 -0
  150. package/skills/blueking-chat-x/references/components/shortcut-render.md +424 -0
  151. package/skills/blueking-chat-x/references/components/simple-table.md +101 -0
  152. package/skills/blueking-chat-x/references/components/text-content.md +80 -0
  153. package/skills/blueking-chat-x/references/components/tool-approval-card.md +183 -0
  154. package/skills/blueking-chat-x/references/components/tool-btn.md +317 -0
  155. package/skills/blueking-chat-x/references/components/tool-message.md +235 -0
  156. package/skills/blueking-chat-x/references/components/toolcall-render.md +348 -0
  157. package/skills/blueking-chat-x/references/components/user-feedback.md +233 -0
  158. package/skills/blueking-chat-x/references/components/user-message.md +444 -0
  159. package/skills/blueking-chat-x/references/components/user-question-answered-card.md +104 -0
  160. package/skills/blueking-chat-x/references/components/user-question-card.md +231 -0
  161. package/skills/blueking-chat-x/references/components/user-question-choice.md +105 -0
  162. package/skills/blueking-chat-x/references/components/user-question-option.md +42 -0
  163. package/skills/blueking-chat-x/references/components/vnode-renderer.md +122 -0
  164. package/skills/blueking-chat-x/references/composables/use-animation-text.md +196 -0
  165. package/skills/blueking-chat-x/references/composables/use-artifact-preview.md +235 -0
  166. package/skills/blueking-chat-x/references/composables/use-clipboard.md +203 -0
  167. package/skills/blueking-chat-x/references/composables/use-command-selection.md +150 -0
  168. package/skills/blueking-chat-x/references/composables/use-container-scroll.md +57 -0
  169. package/skills/blueking-chat-x/references/composables/use-custom-tab.md +158 -0
  170. package/skills/blueking-chat-x/references/composables/use-flow-node-actions.md +164 -0
  171. package/skills/blueking-chat-x/references/composables/use-full-screen.md +112 -0
  172. package/skills/blueking-chat-x/references/composables/use-global-config.md +155 -0
  173. package/skills/blueking-chat-x/references/composables/use-input-mention.md +115 -0
  174. package/skills/blueking-chat-x/references/composables/use-menu-keydown.md +161 -0
  175. package/skills/blueking-chat-x/references/composables/use-message-group.md +244 -0
  176. package/skills/blueking-chat-x/references/composables/use-observer-visible-list.md +188 -0
  177. package/skills/blueking-chat-x/references/composables/use-parent-scrolling.md +46 -0
  178. package/skills/blueking-chat-x/references/directives/index.md +61 -0
  179. package/skills/blueking-chat-x/references/directives/overflow-tips.md +205 -0
  180. package/skills/blueking-chat-x/references/icons/index.md +185 -0
  181. package/skills/blueking-chat-x/references/plugins/index.md +56 -0
  182. package/skills/blueking-chat-x/references/plugins/markdown-container.md +55 -0
  183. package/skills/blueking-chat-x/references/plugins/markdown-latex.md +205 -0
  184. package/skills/blueking-chat-x/references/plugins/markdown-mermaid.md +247 -0
  185. package/skills/blueking-chat-x/references/theme/theme.md +423 -0
  186. package/skills/blueking-chat-x/references/types/constants.md +340 -0
  187. package/skills/blueking-chat-x/references/types/index.md +120 -0
  188. package/skills/blueking-chat-x/references/types/interrupt.md +379 -0
  189. package/skills/blueking-chat-x/references/types/messages.md +556 -0
  190. package/skills/blueking-chat-x/references/types/schema.md +91 -0
  191. package/skills/blueking-chat-x/references/utils/index.md +196 -0
  192. package/skills/blueking-chat-x/scripts/generate-references.mjs +536 -0
  193. package/dist/components/chat-input/ai-slash-editor/ai-slash-editor.vue.d.ts +0 -28
  194. package/dist/components/chat-input/ai-slash-editor/theme.d.ts +0 -24
  195. package/dist/mcp/generated/docs/ai-prompt-list.md +0 -45
  196. package/dist/mcp/generated/docs/ai-skill-list.md +0 -75
  197. package/dist/mcp/generated/docs/ai-slash-editor.md +0 -43
  198. package/dist/mcp/generated/docs/ai-slash-menu.md +0 -42
@@ -0,0 +1,340 @@
1
+ # FileContent 文件内容
2
+
3
+ > 能力域:媒体文件 | 未从包入口导出:内部组件,请通过上层组件使用 | since 1.0.0
4
+
5
+ 渲染文件附件,支持图片预览、上传中/失败态和下载事件。 源码位置:src/components/chat-content/file-content/file-content.vue。
6
+
7
+ **关联**:image-preview(点击图片缩略图打开全屏预览)、user-message(用户消息只读展示附件列表)
8
+
9
+ ---
10
+
11
+ # FileContent 文件内容展示
12
+ ## 源码事实
13
+
14
+ - **源码位置**:`src/components/chat-content/file-content/file-content.vue`
15
+ - **能力域**:媒体文件
16
+ - **能力说明**:渲染文件附件,支持图片预览、上传中/失败态和下载事件。
17
+
18
+ > **能力域**:媒体文件
19
+
20
+ 文件列表展示组件,支持图片缩略图预览、点击图片全屏预览(`ImagePreview`)、文件卡片展示(类型图标 / 文件名 / 文件大小)、上传中/失败态、图片加载失败占位和删除操作。
21
+
22
+ 内部由三个子组件承载单项渲染:
23
+
24
+ | 子组件 | 源码位置 | 职责 |
25
+ | ------------------ | ------------------------------------------------------------------- | --------------------------------------------- |
26
+ | `UploadImageItem` | `src/components/chat-content/file-content/upload-image-item.vue` | 图片缩略图、上传中遮罩、失败占位、hover 删除徽标 |
27
+ | `UploadFileItem` | `src/components/chat-content/file-content/upload-file-item.vue` | 180px 文件卡片(`FileIcon` + 文件名 + 大小 / 失败文案) |
28
+ | `UploadSpinner` | `src/components/chat-content/file-content/upload-spinner.vue` | 16px 白色环形 loading,文件与图片共用 |
29
+
30
+ ## 渲染决策逻辑
31
+
32
+ 先分组、再渲染。设计稿要求**图片始终排在文件前方**,两类各自成行:
33
+
34
+ ```
35
+ splitUploadFiles(files) // 单次遍历
36
+ ├── 图片组(.ai-files-content-row.is-images)
37
+ │ 判定依据:mimeType 或 file.file?.type 以 'image/' 开头
38
+ │ src:file.url 优先,否则用本地 File 的 blob URL(按 key 缓存,移除 / 卸载时 revoke)
39
+ │ 加载失败或 status=error → 错误占位(粉色背景 + 红色边框 + 灰色图标),且不进入预览列表
40
+ │ status=pending → 半透明遮罩 + 16px 环形 loading,禁止点击预览
41
+ └── 文件组(.ai-files-content-row.is-files)
42
+ 文件卡片:类型图标(FileIcon,按文件名解析扩展名)+ 文件名 + 文件大小
43
+ status=pending → 半透明遮罩 + 16px 环形 loading
44
+ status=error → 浅红底 + 红边框,第二行展示「上传失败」
45
+ ```
46
+
47
+ > **是否为图片只看 MIME,不看 `url`。** 解除上传类型限制后,任意文件上传成功都会拿到 `url`,若按 `url` 判断会把 PDF / DOC 渲染成破图。因此 `url` 只决定 `<img src>` 从哪里来,不参与图片判定。
48
+
49
+ ## 基础用法(文件卡片)
50
+
51
+ MIME 类型非 `image/*` 的文件,渲染为固定宽 180px 的文件卡片(类型图标 + 文件名 + 大小)。类型图标与文件产物侧栏共用 `FileIcon` 的扩展名映射,`pdf` / `py` / `docx` 等各有专属图标,未登记的扩展名回退兜底图标:
52
+
53
+ ```vue
54
+ <template>
55
+ <FileContent
56
+ :files="files"
57
+ @delete-file="handleDeleteFile"
58
+ />
59
+ </template>
60
+
61
+ <script setup lang="ts">
62
+ import { ref } from 'vue';
63
+ import { FileContent, type UploadFile } from '@blueking/chat-x';
64
+
65
+ const files = ref<Partial<UploadFile>[]>([
66
+ { file: new File(['content'], 'report.pdf', { type: 'application/pdf' }) },
67
+ { file: new File(['content'], 'data.xlsx', { type: 'application/vnd.ms-excel' }) },
68
+ { file: new File(['readme'], 'README.md', { type: 'text/markdown' }) },
69
+ ]);
70
+
71
+ const handleDeleteFile = (file: Partial<UploadFile>) => {
72
+ files.value = files.value.filter(f => f !== file);
73
+ };
74
+ </script>
75
+ ```
76
+
77
+ **渲染效果**(悬停文件卡片,底色加深并在右上角出现删除徽标)
78
+
79
+ ## 图片文件预览
80
+
81
+ MIME 为 `image/*` 时渲染为图片缩略图(`cursor: zoom-in`)。点击图片可打开全屏预览(内部集成 `ImagePreview` 组件),支持缩放、旋转、下载等操作:
82
+
83
+ ```vue
84
+ <script setup lang="ts">
85
+ import { ref } from 'vue';
86
+ import { type UploadFile } from '@blueking/chat-x';
87
+
88
+ const imageFiles = ref<Partial<UploadFile>[]>([
89
+ {
90
+ url: 'https://example.com/cat.jpg',
91
+ filename: 'cat.jpg',
92
+ mimeType: 'image/jpeg', // 图片判定依据
93
+ file: new File([''], 'cat.jpg', { type: 'image/jpeg' }),
94
+ },
95
+ {
96
+ url: 'https://example.com/dog.png',
97
+ filename: 'dog.png',
98
+ mimeType: 'image/png',
99
+ file: new File([''], 'dog.png', { type: 'image/png' }),
100
+ },
101
+ ]);
102
+ </script>
103
+ ```
104
+
105
+ **渲染效果**
106
+
107
+ ## 图片点击预览
108
+
109
+ 图片模式下点击缩略图会打开全屏预览弹窗。多张图片时支持左右切换。加载失败的图片不会出现在预览列表中:
110
+
111
+ ```vue
112
+ <template>
113
+ <FileContent :files="imageFiles" />
114
+ </template>
115
+
116
+ <script setup lang="ts">
117
+ import { ref } from 'vue';
118
+ import { FileContent, type UploadFile } from '@blueking/chat-x';
119
+
120
+ const imageFiles = ref<Partial<UploadFile>[]>([
121
+ { url: 'https://example.com/cat.jpg', filename: 'cat.jpg', mimeType: 'image/jpeg' },
122
+ { url: 'https://example.com/dog.png', filename: 'dog.png', mimeType: 'image/png' },
123
+ ]);
124
+ </script>
125
+ ```
126
+
127
+ > **预览行为**:组件内部自动维护 `ImagePreview` 实例,无需外部管理预览状态。只有加载成功的图片才会进入预览列表,加载失败的图片被自动过滤。
128
+
129
+ ## 上传中 / 上传失败
130
+
131
+ `FileContent` 消费每项的 `status`(`UploadStatus`)。尺寸不变:文件卡片仍是 180×48,图片仍是定高 48、宽 48~120。loading 用共享的 `UploadSpinner`(16px 白环),不要用 `AiLoading`。删除徽标始终叠在遮罩之上。
132
+
133
+ | status | 文件卡片 | 图片缩略图 |
134
+ | --------- | -------- | ---------- |
135
+ | `pending` | `rgba(0,0,0,0.3)` 遮罩 + spinner | 保留预览图 + `rgba(0,0,0,0.5)` 遮罩 + spinner,点击不打开预览 |
136
+ | `error` | 背景 `#fff0f0`、边框 `#ea3636`,第二行「上传失败」 | 与加载失败相同的破图占位(18px `ImageErrorIcon`) |
137
+ | `success` / 未设置 | 正常卡片 | 正常缩略图,可预览 |
138
+
139
+ 上传中与上传失败的图片都不会进入 `ImagePreview` 列表。`ChatInput` 在存在 `pending` / `error` 附件时会拦截发送(见 [ChatInput](/components/input/chat-input))。
140
+
141
+ ## 图片加载失败
142
+
143
+ `<img>` 触发 `onerror` 时,切换为粉色背景 + 红色边框的错误占位(与 `status=error` 同一套 UI):
144
+
145
+ ## 混合文件(图片 + 文件)
146
+
147
+ 同一列表可同时包含图片和其他文件,组件内部自动把图片排在前一行、文件排在后一行,各行内部横向排列并按需换行:
148
+
149
+ ```vue
150
+ <script setup lang="ts">
151
+ const files = [
152
+ { url: 'https://example.com/photo.jpg', filename: 'photo.jpg', mimeType: 'image/jpeg' },
153
+ { file: new File(['content'], 'report.pdf', { type: 'application/pdf' }) },
154
+ { file: new File(['data'], 'data.xlsx', { type: 'application/vnd.ms-excel' }) },
155
+ ];
156
+ </script>
157
+ ```
158
+
159
+ **渲染效果**
160
+
161
+ ## 只读模式(readonly)
162
+
163
+ 传入 `readonly` 时,隐藏删除按钮,适用于用户消息中展示已发送的文件:
164
+
165
+ ```vue
166
+ <FileContent :files="files" :readonly="true" />
167
+ ```
168
+
169
+ **渲染效果**(悬停无删除按钮)
170
+
171
+ ## 仅有 filename(无 File 对象)
172
+
173
+ 从服务端恢复的历史文件没有 `File` 对象时仍可渲染文件卡片,类型图标从 `filename` 推断。文件大小取 `size` 字段;未下发 `size` 时大小节点不渲染:
174
+
175
+ ```vue
176
+ <script setup lang="ts">
177
+ const remoteFiles = [
178
+ // 无 file 对象,未带 size,文件大小不渲染
179
+ { filename: 'server-report.pdf', mimeType: 'application/pdf' },
180
+ // 带 size 时正常显示「1.00M」
181
+ { filename: 'config.json', mimeType: 'application/json', size: 1024 * 1024 },
182
+ ];
183
+ </script>
184
+ ```
185
+
186
+ **渲染效果**(未带 `size` 的项无大小行)
187
+
188
+ ## 在 ChatInput 中使用
189
+
190
+ `FileContent` 由 `ChatInput` 内部自动渲染在文件预览区(`slot#files` 的默认内容),通常不需要手动引入。当 `ChatInput` 收到上传文件时,自动更新 `uploadFiles` 并渲染:
191
+
192
+ ```vue
193
+ <template>
194
+ <ChatInput
195
+ v-model="inputValue"
196
+ :on-send-message="handleSendMessage"
197
+ :on-upload="handleUpload"
198
+ />
199
+ </template>
200
+ ```
201
+
202
+ 若需自定义文件展示,通过 `slot#files` 替换默认 `FileContent`:
203
+
204
+ ```vue
205
+ <template>
206
+ <ChatInput
207
+ v-model="inputValue"
208
+ :on-upload="handleUpload"
209
+ >
210
+ <template #files="{ files }">
211
+ <!-- 自定义文件列表 UI -->
212
+ <FileContent
213
+ :files="files"
214
+ readonly
215
+ />
216
+ </template>
217
+ </ChatInput>
218
+ </template>
219
+ ```
220
+
221
+ ## 上传文件预览
222
+
223
+ 具有 `outputId` 且不处于上传中 / 失败态的附件,在 `ChatContainer` 内点击会通过统一的文件产物侧栏预览,使用 `onArtifactClick` 获取预览和下载链接。图片缩略图链接失效时仍可按 `outputId` 重新取链;无 `outputId` 的图片继续使用原有图片预览。
224
+
225
+ ## API
226
+
227
+ ### Props
228
+
229
+ | 属性名 | 类型 | 默认值 | 必填 | 说明 |
230
+ | -------- | ----------------------- | --------- | ---- | ------------------------------------------- |
231
+ | files | `Partial<UploadFile>[]` | - | ✅ | 文件列表 |
232
+ | readonly | `boolean` | `false` | - | 只读模式,`true` 时隐藏删除徽标与 hover 态 |
233
+ | variant | `'input' \| 'message'` | `'input'` | - | 展示形态,见下方「展示形态」 |
234
+
235
+ ### 展示形态(variant)
236
+
237
+ 只影响图片缩略图的圆角描边与整体对齐,文件卡片两种形态一致。图片尺寸规则两种形态相同:**定高 48px,宽度按原图比例,并在 48~120px 之间夹取**(竖图不至于过窄,长图不会撑破容器),超出部分由 `object-fit: cover` 裁切。
238
+
239
+ | variant | 使用场景 | 图片圆角 / 描边 | 对齐 |
240
+ | ----------- | ------------------ | --------------- | ------ |
241
+ | `'input'` | 输入框内待发送态 | 8px / `#f0f1f5` | 左对齐 |
242
+ | `'message'` | 用户消息内已发送态 | 4px / `#eaebf0` | 右对齐 |
243
+
244
+ ### Events
245
+
246
+ | 事件名 | 参数 | 触发时机 |
247
+ | ---------- | ----------------------------- | ------------------ |
248
+ | deleteFile | `(file: Partial<UploadFile>)` | 点击删除按钮时触发 |
249
+
250
+ ## 渲染模式详解
251
+
252
+ ### 图片模式
253
+
254
+ | 条件 | 图片 src | 点击行为 |
255
+ | ------------------- | ------------------------------------------------- | -------------- |
256
+ | `file.url` 有值 | `file.url` | 打开全屏预览 |
257
+ | 无 url、有 `File` | `URL.createObjectURL(file.file)`(按 key 缓存) | 打开全屏预览 |
258
+ | 图片加载失败 | 错误占位 | 不进入预览列表 |
259
+ | `status` 为 pending / error | 遮罩 loading 或错误占位 | 不进入预览列表 |
260
+
261
+ blob URL 按附件 key 缓存,同一文件重复渲染不会重复创建;文件被移除或组件卸载时统一 `revokeObjectURL`。
262
+
263
+ ### 文件卡片模式
264
+
265
+ | 字段 | 取值优先级 |
266
+ | -------- | --------------------------------------------- |
267
+ | 文件名 | `file.filename` → `file.file?.name` |
268
+ | 类型图标 | 由文件名解析扩展名,交给 `FileIcon` 映射 |
269
+ | 文件大小 | `file.file?.size` → `file.size`;都没有则不渲染 |
270
+
271
+ ## 类型定义
272
+
273
+ ```typescript
274
+ import type { UploadFile, BinaryInputContent } from '@blueking/chat-x';
275
+
276
+ // 上传状态:ChatInput 写入,FileContent 消费以渲染 pending / error
277
+ enum UploadStatus {
278
+ Pending = 'pending', // 上传中
279
+ Success = 'success', // 上传成功
280
+ Error = 'error', // 上传失败
281
+ }
282
+
283
+ // 上传文件(FileContent 的 files 数组中每一项)
284
+ type UploadFile = BinaryInputContent & {
285
+ file?: File; // 原始 File 对象,无则文件大小不显示
286
+ status?: UploadStatus; // 上传状态(pending 遮罩 loading,error 失败样式)
287
+ };
288
+
289
+ // 二进制内容基础类型
290
+ interface BinaryInputContent {
291
+ type: 'binary';
292
+ url?: string; // 文件访问地址,只决定 <img src> 来源,不参与图片判定
293
+ filename?: string; // 文件名(文件卡片展示 + 类型图标解析)
294
+ mimeType?: string; // MIME 类型(图片判定依据)
295
+ size?: number; // 文件字节数,发送时由原始 File 写入
296
+ }
297
+ ```
298
+
299
+ ## 工具函数(`src/utils/upload-file.ts`)
300
+
301
+ 组件内的取值与分组逻辑都收敛在这里,`ChatInput`、`UserMessage` 共用同一套判定:
302
+
303
+ ```typescript
304
+ import {
305
+ getFileIdentity,
306
+ getUploadFileKey,
307
+ getUploadFileName,
308
+ getUploadFileSize,
309
+ isUploadImageFile,
310
+ splitUploadFiles,
311
+ } from '@blueking/chat-x';
312
+
313
+ // File 身份:文件名 + 大小 + 修改时间,用于去重与列表 key
314
+ getFileIdentity(file); // 'report.pdf_2048_1700000000000'
315
+
316
+ // 附件稳定 key:待发送态用 File 身份(上传成功回填 url 后不变),已发送态退回 url / 文件名
317
+ getUploadFileKey({ file }); // 'report.pdf_2048_1700000000000'
318
+ getUploadFileKey({ url: 'https://x/a.pdf' }); // 'https://x/a.pdf'
319
+
320
+ // 是否按图片渲染:只看 MIME,有 url 也不例外
321
+ isUploadImageFile({ mimeType: 'application/pdf', url: 'https://x/a.pdf' }); // false
322
+
323
+ // 文件名 / 字节数取值优先级
324
+ getUploadFileName({ filename: 'remote.pdf', file }); // 'remote.pdf'
325
+ getUploadFileSize({ size: 2048 }); // 2048
326
+
327
+ // 单次遍历分出图片组与其他文件组(图片在前)
328
+ splitUploadFiles(files); // { imageFiles, otherFiles }
329
+ ```
330
+
331
+ ## 使用场景
332
+
333
+ - **ChatInput 文件预览区**:上传文件后在编辑器上方展示待发送的文件列表(可删除)
334
+ - **用户消息展示**:`UserMessage` 内部以 `readonly` 模式展示已发送的图片和附件
335
+ - **历史消息回放**:服务端返回的文件信息(无 `File` 对象)也能正常渲染文档卡片
336
+
337
+ ## 关联组件
338
+
339
+ - [ImagePreview](/components/medias/image-preview) — 图片全屏预览
340
+ - [UserMessage](/components/message/user-message) — 用户消息内附件展示
@@ -0,0 +1,109 @@
1
+ # FileIcon 文件类型图标
2
+
3
+ > 能力域:辅助能力 | 导入:`import { FileIcon } from '@blueking/chat-x'` | since 1.0.0
4
+
5
+ 按扩展名渲染文件类型图标:内联 svg,尺寸用 1em 跟随外层 font-size; 扩展名解析走 normalizeFileExtension(优先 fileType,缺省回退 fileName,大小写不敏感, 支持 Dockerfile / .gitignore 这类无扩展名或点号开头的文件);未登记类型返回 unknown 兜底图标。 源码位置:src/components/file-icon/file-icon.vue,图标注册表在 src/icons/file-icons.ts。
6
+
7
+ **关联**:file-artifact-panel(文件产物列表与预览头使用该组件展示类型图标)、assistant-message(消息内的文件产物卡片使用该组件)
8
+
9
+ ---
10
+
11
+ # FileIcon 文件类型图标
12
+
13
+ > **能力域**:辅助能力
14
+
15
+ `FileIcon` 按文件扩展名渲染对应的类型图标,用于文件列表、附件卡片、产物预览头等需要「一眼看出这是什么文件」的场景。图标以内联 svg 形式打进包内,不产生额外网络请求,也不需要消费方配置静态资源路径。
16
+
17
+ ## 源码事实
18
+
19
+ - **源码位置**:`src/components/file-icon/file-icon.vue`
20
+ - **图标注册表**:`src/icons/file-icons.ts`(导出 `getFileIconSvg` / `UNKNOWN_FILE_ICON_SVG`)
21
+ - **扩展名解析**:`src/utils/file-type.ts` 的 `normalizeFileExtension`
22
+
23
+ ## 核心能力
24
+
25
+ - **扩展名驱动**:优先取 `fileType`,缺省时回退 `fileName` 推断;大小写不敏感
26
+ - **特殊文件名**:`Dockerfile` / `Makefile` 这类无扩展名文件,以及 `.gitignore` / `.editorconfig` 这类点号开头的文件都能正确命中
27
+ - **多扩展名共用图标**:如 `xlsx` / `xls` / `csv` / `tsv` 共用表格图标,`tsx` / `jsx` 共用 React 图标
28
+ - **兜底不报错**:未登记的扩展名返回 `unknown` 图标,后台新增文件类型时前端不会缺图
29
+ - **尺寸自适应**:内部 svg 固定为 `1em`,直接用外层 `font-size` 控制大小
30
+
31
+ ## 基础用法
32
+
33
+ ```vue
34
+ <template>
35
+ <FileIcon file-type="pdf" />
36
+ </template>
37
+
38
+ <script setup lang="ts">
39
+ import { FileIcon } from '@blueking/chat-x';
40
+ </script>
41
+ ```
42
+
43
+ **渲染效果**
44
+
45
+ ## 从文件名推断
46
+
47
+ 后台未下发 `type` 时传 `fileName` 即可,组件会取最后一段扩展名:
48
+
49
+ ```vue
50
+ <template>
51
+ <!-- 取 xlsx -->
52
+ <FileIcon file-name="季度报告.final.xlsx" />
53
+ <!-- 取 gitignore -->
54
+ <FileIcon file-name=".gitignore" />
55
+ </template>
56
+ ```
57
+
58
+ 两者同时传入时以 `fileType` 优先。
59
+
60
+ ## 控制尺寸
61
+
62
+ 图标宽高为 `1em`,用外层 `font-size` 控制即可,无需改 svg:
63
+
64
+ ```vue
65
+ <template>
66
+ <span style="font-size: 16px"><FileIcon file-type="py" /></span>
67
+ <span style="font-size: 32px"><FileIcon file-type="py" /></span>
68
+ </template>
69
+ ```
70
+
71
+ ## API
72
+
73
+ ### Props
74
+
75
+ | 属性名 | 类型 | 必填 | 默认值 | 说明 |
76
+ | -------- | -------- | ---- | ----------- | -------------------------------------------------------- |
77
+ | fileType | `string` | 否 | `undefined` | 文件类型:扩展名(如 `pdf` / `py`)或无扩展名文件名(如 `Dockerfile`) |
78
+ | fileName | `string` | 否 | `undefined` | 文件名,`fileType` 缺省时用于推断扩展名 |
79
+
80
+ 两者都不传时渲染兜底图标。
81
+
82
+ ### Emits / Slots / Expose
83
+
84
+ - 无。
85
+
86
+ ## 图标覆盖范围
87
+
88
+ | 图标 | 覆盖扩展名 |
89
+ | ---- | ---------- |
90
+ | 文档类 | `pptx` / `docx` / `pdf` / `txt` / `rst` / `md` / `markdown` / `tex` |
91
+ | 表格类 | `xlsx` / `xlsm` / `xls` / `csv` / `tsv` |
92
+ | 前端 | `html` / `htm` / `css` / `scss` / `less` / `js` / `mjs` / `cjs` / `ts` / `tsx` / `jsx` / `vue` / `xml` |
93
+ | 后端 / 系统 | `py` / `go` / `rs` / `rb` / `java` / `kt` / `swift` / `c` / `h` / `cpp` / `hpp` / `cs` / `php` / `lua` / `r` / `scala` / `dart` / `sql` / `sh` / `bash` / `zsh` / `ps1` |
94
+ | 配置 | `json` / `jsonc` / `yaml` / `yml` / `toml` / `ini` / `cfg` / `conf` / `env` / `editorconfig` / `Makefile` |
95
+ | 工具链 | `Dockerfile` / `dockerignore` / `gitignore` |
96
+ | 图片 | `png` / `jpg` / `jpeg` / `svg` |
97
+ | 兜底 | 以上之外的所有类型 |
98
+
99
+ 新增类型时在 `src/icons/file-icons.ts` 的 `FILE_ICON_GROUPS` 里补一行即可;对应 svg 需先放进 `src/svgs/` 并按需 `?raw` 引入(只引实际用到的,避免把整个图标库打进产物)。
100
+
101
+ ## 使用建议
102
+
103
+ - 图标颜色由 svg 自带,不继承 `currentColor`,不要试图用 `color` 覆盖
104
+ - 需要与文件名同行展示时,给父容器设 `display: flex` + `gap`,组件本身已是 `inline-flex` 且 `flex-shrink: 0`
105
+
106
+ ## 关联组件
107
+
108
+ - [FileArtifactPanel](../message/file-artifact-panel.md) — 文件产物列表与预览头使用该组件。
109
+ - [AssistantMessage](../message/assistant-message.md) — 消息内文件产物卡片的图标来源。
@@ -0,0 +1,162 @@
1
+ # FileUploadBtn 文件上传按钮
2
+
3
+ > 能力域:输入交互 | 未从包入口导出:内部组件,请通过上层组件使用 | since 1.0.0
4
+
5
+ 文件选择按钮,封装 input[type=file] 并输出选择事件。 源码位置:src/components/ai-buttons/file-upload-btn/file-upload-btn.vue。
6
+
7
+ **关联**:add-menu-btn(ChatInput 内部已改用 + 号聚合菜单承载上传入口)、chat-input(输入区附件上传按钮常见挂载位置)、file-content(选中文件常以列表形式展示待发送内容)
8
+
9
+ ---
10
+
11
+ # FileUploadBtn 文件上传按钮
12
+ ## 源码事实
13
+
14
+ - **源码位置**:`src/components/ai-buttons/file-upload-btn/file-upload-btn.vue`
15
+ - **能力域**:输入交互
16
+ - **能力说明**:文件选择按钮,封装 input[type=file] 并输出选择事件。
17
+
18
+ > **能力域**:输入交互
19
+
20
+ ::: warning ChatInput 已不再使用本按钮
21
+ 输入区重构后,`ChatInput` 的上传入口改为左下角 [AddMenuBtn](/components/input/add-menu-btn) 聚合菜单里的「文件」项(内部走自持的隐藏 `input[type=file]`)。本组件仍保留在源码中并可用于自建输入区,但**不会**出现在 `ChatInput` 的默认布局里,也**未从包入口导出**——文档站示例经相对路径引入。
22
+ :::
23
+
24
+ 文件上传触发按钮,点击后弹出系统文件选择框。内部包含隐藏的 `<input type="file">` 与可见的图标按钮;**不限制文件类型**,在按钮层只对**单文件**做大小与空文件过滤,**已选文件个数上限**由上层统一校验并提示,避免按钮与输入区各弹一条错误提示。
25
+
26
+ ## 组件结构
27
+
28
+ ```
29
+ .ai-file-upload-btn(display: flex,align-items: center)
30
+ ├── input[type="file"](.file-upload-btn-input,display: none,multiple,:accept)
31
+ │ accept 缺省时不下发该属性,系统选择框不过滤任何类型
32
+ │ 触发后走 handleFileInputChange → 校验 → emit upload → target.value = ''
33
+ └── span.ai-shortcut-btn.file-upload-btn-icon(热区 32×32px / 圆角 8px;图标字号跟随 --ai-icon-size-sm:small=16px、normal=18px;color: #979ba5;hover: #f0f1f5)
34
+ v-tippy: "上传文件,最多支持 {count} 个,单个最大 {size}MB"
35
+ ({count} / {size} 由 MAX_UPLOAD_FILES 与 MAX_UPLOAD_FILE_SIZE 运行时填充,theme: ai-chat-box,offset: [0, 16],可通过 tippyOptions 扩展)
36
+ @click → fileInputRef.click()
37
+ └── <slot> 默认:FileUploadIcon
38
+ ```
39
+
40
+ ## 文件校验逻辑
41
+
42
+ ```
43
+ 用户选择文件
44
+
45
+ ├─ 遍历所选文件:size > 0 且 size < MAX_UPLOAD_FILE_SIZE(45MB)→ 加入 toEmit
46
+ │ size 为 0 或 ≥ 上限 → sizeRejected += 1
47
+
48
+ ├─ sizeRejected > 0 → bkui-vue Message.error(formatUploadNotAddedMessage,说明可能超大或超出个数等)
49
+
50
+ ├─ toEmit.length > 0 → emit('upload', toEmit)
51
+
52
+ └─ target.value = ''(重置 input,允许再次选择同一文件)
53
+ ```
54
+
55
+ **关键边界行为**:
56
+
57
+ | 场景 | 结果 |
58
+ | ------------------------------------------------------------ | -------------------------------------------------------------------- |
59
+ | 一次多选超过上层允许个数 | 由**上层**(如输入区)toast 并丢弃 / 不计入,不在本按钮内按个数提前拦截 |
60
+ | 部分文件因空文件或单文件超大被过滤 | 弹出错误 toast;若仍有合法文件,**仍触发** `upload`(payload 为合法子集) |
61
+ | 全部被过滤(均为空或超大) | 仅 toast,**不触发** `upload` |
62
+ | `file.size === 0` | 计入未添加提示,不进入 `upload` payload |
63
+ | `file.size >= MAX_UPLOAD_FILE_SIZE`(与全局常量一致,45MB) | 计入未添加提示,不进入 `upload` payload(比较为严格 `<`) |
64
+ | 选择后取消 | `files.length === 0`,不触发 `upload` |
65
+
66
+ > `multiple` prop 声明存在但当前模板中 `input` 的 `multiple` 属性为**硬编码**(非 `:multiple="multiple"` 绑定),始终允许多选,该 prop 暂时无实际效果。
67
+
68
+ > **文件类型不做限制**:组件不再默认 `accept="image/*"`,任意类型文件都可选择。若业务需要收窄,显式传入 `accept`。个数上限由上层控制(`MAX_UPLOAD_FILES`),详见 [ChatInput 文件上传](/components/input/chat-input#file-upload)。
69
+
70
+ ## 基础用法
71
+
72
+ ```vue
73
+ <template>
74
+ <FileUploadBtn @upload="handleUpload" />
75
+ </template>
76
+
77
+ <script setup lang="ts">
78
+ const handleUpload = (files: File[]) => {
79
+ console.log(
80
+ '选中文件:',
81
+ files.map(f => `${f.name}(${f.size}B)`),
82
+ );
83
+ };
84
+ </script>
85
+ ```
86
+
87
+ ## 限制文件类型
88
+
89
+ 默认**不限制**文件类型。需要收窄时通过 `accept` 属性控制系统文件选择框的过滤条件,遵循 `<input type="file">` 的 `accept` 规范:
90
+
91
+ ```vue
92
+ <template>
93
+ <!-- 不限制类型(默认,不下发 accept) -->
94
+ <FileUploadBtn @upload="handleUpload" />
95
+
96
+ <!-- 仅图片 -->
97
+ <FileUploadBtn
98
+ accept="image/*"
99
+ @upload="handleUpload"
100
+ />
101
+
102
+ <!-- 文档类型 -->
103
+ <FileUploadBtn
104
+ accept=".pdf,.doc,.docx,.xlsx,.pptx"
105
+ @upload="handleUpload"
106
+ />
107
+ </template>
108
+ ```
109
+
110
+ > `accept` 仅影响文件选择框的过滤 UI,不做服务端验证,请在 `upload` 回调中自行校验 MIME 类型。
111
+
112
+ ## 自定义图标
113
+
114
+ 通过默认插槽替换上传图标:
115
+
116
+ ```vue
117
+ <template>
118
+ <FileUploadBtn @upload="handleUpload">
119
+ <span style="font-size: 16px; line-height: 1;">📎</span>
120
+ </FileUploadBtn>
121
+ </template>
122
+ ```
123
+
124
+ ## API
125
+
126
+ ### Props
127
+
128
+ | 属性名 | 类型 | 默认值 | 说明 |
129
+ | ------------ | -------------- | ------ | -------------------------------------------------------------------------- |
130
+ | accept | `string` | — | 文件选择框过滤类型,遵循 `<input accept>` 规范;缺省时不下发,不限制类型 |
131
+ | multiple | `boolean` | `true` | 声明属性(当前版本未实际绑定到 input,始终多选) |
132
+ | tippyOptions | `AITippyProps` | — | 扩展 tooltip 配置,会与内置配置合并 |
133
+
134
+ ### Events
135
+
136
+ | 事件名 | 参数 | 说明 |
137
+ | ------ | ----------------- | ----------------------------------------------------------------------------------------- |
138
+ | upload | `(files: File[])` | 当存在至少一个合法文件时触发;`files` 为过滤掉空文件与单文件超大(`size >= MAX_UPLOAD_FILE_SIZE`,45MB)后的数组;个数截断不在此组件内完成 |
139
+
140
+ ### Slots
141
+
142
+ | 插槽名 | 说明 |
143
+ | ------- | ----------------------------------------------- |
144
+ | default | 自定义按钮图标内容,默认为内置 `FileUploadIcon` |
145
+
146
+ ## 使用场景
147
+
148
+ 仅在**自建输入区**时使用。若使用 `ChatInput`,上传能力由 `supportUpload`(默认 `true`)开启,入口是 + 号菜单里的「文件」项、拖拽与粘贴,无需再挂本按钮。
149
+
150
+ ## 类型定义
151
+
152
+ ```typescript
153
+ import type { TippyOptions } from 'vue-tippy';
154
+
155
+ type AITippyProps = Partial<Pick<TippyOptions, 'appendTo' | 'placement' | 'zIndex'>>;
156
+ ```
157
+
158
+ ## 关联组件
159
+
160
+ - [AddMenuBtn](/components/input/add-menu-btn) — `ChatInput` 现行的上传 / 资源入口
161
+ - [ChatInput](/components/input/chat-input) — 上传能力与校验规则
162
+ - [FileContent](/components/medias/file-content) — 选中文件列表展示