@blueking/chat-x 0.0.50 → 0.0.51-beta.2

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 (147) hide show
  1. package/dist/ag-ui/types/contents.d.ts +2 -0
  2. package/dist/ag-ui/types/messages.d.ts +5 -0
  3. package/dist/common/constants.d.ts +1 -1
  4. package/dist/components/ai-buttons/file-upload-btn/file-upload-btn.vue.d.ts +0 -2
  5. package/dist/components/chat-content/file-content/file-content.vue.d.ts +5 -2
  6. package/dist/components/chat-content/file-content/upload-file-item.vue.d.ts +12 -0
  7. package/dist/components/chat-content/file-content/upload-image-item.vue.d.ts +21 -0
  8. package/dist/components/chat-input/ai-slash-editor/ai-slash-editor.vue.d.ts +1 -1
  9. package/dist/components/chat-input/build-default-placeholder.d.ts +7 -0
  10. package/dist/components/chat-input/chat-input.vue.d.ts +1 -1
  11. package/dist/components/chat-message/message-container/message-container.vue.d.ts +1 -0
  12. package/dist/components/chat-message/message-render/message-render.vue.d.ts +2 -0
  13. package/dist/components/chat-message/user-message/user-message.vue.d.ts +3 -1
  14. package/dist/components/index.d.ts +2 -1
  15. package/dist/components/message-tools/message-time/format-message-time.d.ts +8 -0
  16. package/dist/components/message-tools/message-time/message-time.vue.d.ts +8 -0
  17. package/dist/components/message-tools/message-tools.vue.d.ts +11 -1
  18. package/dist/composables/use-custom-tab.d.ts +5 -3
  19. package/dist/composables/use-global-config.d.ts +3 -0
  20. package/dist/composables/use-message-group.d.ts +150 -72
  21. package/dist/icons/execution.d.ts +6 -0
  22. package/dist/icons/tools.d.ts +3 -0
  23. package/dist/index.css +1 -1
  24. package/dist/index.js +3124 -2837
  25. package/dist/index.js.map +1 -1
  26. package/dist/lang/lang.d.ts +8 -7
  27. package/dist/mcp/generated/docs/ai-slash-input.md +2 -0
  28. package/dist/mcp/generated/docs/assistant-message.md +9 -7
  29. package/dist/mcp/generated/docs/chat-container.md +38 -32
  30. package/dist/mcp/generated/docs/chat-input.md +18 -12
  31. package/dist/mcp/generated/docs/cite-content.md +3 -3
  32. package/dist/mcp/generated/docs/desc-panel.md +32 -10
  33. package/dist/mcp/generated/docs/execution-summary.md +3 -3
  34. package/dist/mcp/generated/docs/file-artifact-panel.md +6 -4
  35. package/dist/mcp/generated/docs/file-content.md +89 -73
  36. package/dist/mcp/generated/docs/file-upload-btn.md +16 -18
  37. package/dist/mcp/generated/docs/message-container.md +3 -0
  38. package/dist/mcp/generated/docs/message-render.md +2 -1
  39. package/dist/mcp/generated/docs/message-time.md +180 -0
  40. package/dist/mcp/generated/docs/message-tools.md +47 -12
  41. package/dist/mcp/generated/docs/messages.md +9 -0
  42. package/dist/mcp/generated/docs/toolcall-render.md +82 -43
  43. package/dist/mcp/generated/docs/use-artifact-preview.md +19 -17
  44. package/dist/mcp/generated/docs/use-custom-tab.md +12 -8
  45. package/dist/mcp/generated/docs/use-global-config.md +15 -5
  46. package/dist/mcp/generated/docs/user-message.md +9 -0
  47. package/dist/mcp/generated/docs/user-question-card.md +2 -0
  48. package/dist/mcp/generated/index.json +46 -6
  49. package/dist/types/input.d.ts +6 -0
  50. package/dist/utils/file.d.ts +7 -1
  51. package/dist/utils/index.d.ts +2 -0
  52. package/dist/utils/merge-tools-by-id.d.ts +6 -0
  53. package/dist/utils/upload-file.d.ts +35 -0
  54. package/package.json +3 -2
  55. package/skills/blueking-chat-x/SKILL.md +139 -0
  56. package/skills/blueking-chat-x/references/_index.md +131 -0
  57. package/skills/blueking-chat-x/references/components/activity-layout.md +134 -0
  58. package/skills/blueking-chat-x/references/components/activity-message.md +486 -0
  59. package/skills/blueking-chat-x/references/components/ai-image.md +230 -0
  60. package/skills/blueking-chat-x/references/components/ai-loading.md +131 -0
  61. package/skills/blueking-chat-x/references/components/ai-prompt-list.md +44 -0
  62. package/skills/blueking-chat-x/references/components/ai-selection.md +439 -0
  63. package/skills/blueking-chat-x/references/components/ai-skill-list.md +73 -0
  64. package/skills/blueking-chat-x/references/components/ai-slash-editor.md +43 -0
  65. package/skills/blueking-chat-x/references/components/ai-slash-input.md +56 -0
  66. package/skills/blueking-chat-x/references/components/ai-slash-menu.md +42 -0
  67. package/skills/blueking-chat-x/references/components/animation-text.md +202 -0
  68. package/skills/blueking-chat-x/references/components/assistant-message.md +498 -0
  69. package/skills/blueking-chat-x/references/components/chat-container.md +869 -0
  70. package/skills/blueking-chat-x/references/components/chat-input.md +769 -0
  71. package/skills/blueking-chat-x/references/components/cite-content.md +142 -0
  72. package/skills/blueking-chat-x/references/components/code-content.md +211 -0
  73. package/skills/blueking-chat-x/references/components/common-error-content.md +73 -0
  74. package/skills/blueking-chat-x/references/components/content-render.md +233 -0
  75. package/skills/blueking-chat-x/references/components/delete-tool.md +191 -0
  76. package/skills/blueking-chat-x/references/components/desc-panel.md +162 -0
  77. package/skills/blueking-chat-x/references/components/detail-section.md +91 -0
  78. package/skills/blueking-chat-x/references/components/execution-summary.md +128 -0
  79. package/skills/blueking-chat-x/references/components/file-artifact-panel.md +289 -0
  80. package/skills/blueking-chat-x/references/components/file-content.md +319 -0
  81. package/skills/blueking-chat-x/references/components/file-icon.md +109 -0
  82. package/skills/blueking-chat-x/references/components/file-upload-btn.md +159 -0
  83. package/skills/blueking-chat-x/references/components/flow-agent-content.md +264 -0
  84. package/skills/blueking-chat-x/references/components/flow-agent-node-detail.md +236 -0
  85. package/skills/blueking-chat-x/references/components/highlight-keyword.md +146 -0
  86. package/skills/blueking-chat-x/references/components/image-content.md +182 -0
  87. package/skills/blueking-chat-x/references/components/image-preview-group.md +184 -0
  88. package/skills/blueking-chat-x/references/components/image-preview.md +226 -0
  89. package/skills/blueking-chat-x/references/components/info-message.md +144 -0
  90. package/skills/blueking-chat-x/references/components/input-attachment.md +49 -0
  91. package/skills/blueking-chat-x/references/components/input-info-alert.md +42 -0
  92. package/skills/blueking-chat-x/references/components/interrupt-message.md +212 -0
  93. package/skills/blueking-chat-x/references/components/key-value-content.md +128 -0
  94. package/skills/blueking-chat-x/references/components/knowledge-rag-content.md +122 -0
  95. package/skills/blueking-chat-x/references/components/latex-content.md +200 -0
  96. package/skills/blueking-chat-x/references/components/loading-message.md +192 -0
  97. package/skills/blueking-chat-x/references/components/markdown-content.md +232 -0
  98. package/skills/blueking-chat-x/references/components/mermaid-content.md +189 -0
  99. package/skills/blueking-chat-x/references/components/message-container.md +645 -0
  100. package/skills/blueking-chat-x/references/components/message-loading.md +118 -0
  101. package/skills/blueking-chat-x/references/components/message-render.md +327 -0
  102. package/skills/blueking-chat-x/references/components/message-time.md +177 -0
  103. package/skills/blueking-chat-x/references/components/message-tools.md +416 -0
  104. package/skills/blueking-chat-x/references/components/model-selector.md +155 -0
  105. package/skills/blueking-chat-x/references/components/preview-toolbar.md +42 -0
  106. package/skills/blueking-chat-x/references/components/questions-container.md +85 -0
  107. package/skills/blueking-chat-x/references/components/reasoning-message.md +232 -0
  108. package/skills/blueking-chat-x/references/components/reference-content.md +135 -0
  109. package/skills/blueking-chat-x/references/components/reference-doc-content.md +109 -0
  110. package/skills/blueking-chat-x/references/components/scroll-btn.md +159 -0
  111. package/skills/blueking-chat-x/references/components/selection-footer.md +78 -0
  112. package/skills/blueking-chat-x/references/components/selection-question.md +88 -0
  113. package/skills/blueking-chat-x/references/components/shortcut-btn.md +204 -0
  114. package/skills/blueking-chat-x/references/components/shortcut-btns.md +266 -0
  115. package/skills/blueking-chat-x/references/components/shortcut-render.md +424 -0
  116. package/skills/blueking-chat-x/references/components/simple-table.md +101 -0
  117. package/skills/blueking-chat-x/references/components/text-content.md +77 -0
  118. package/skills/blueking-chat-x/references/components/tool-approval-card.md +183 -0
  119. package/skills/blueking-chat-x/references/components/tool-btn.md +317 -0
  120. package/skills/blueking-chat-x/references/components/tool-message.md +235 -0
  121. package/skills/blueking-chat-x/references/components/toolcall-render.md +348 -0
  122. package/skills/blueking-chat-x/references/components/user-feedback.md +233 -0
  123. package/skills/blueking-chat-x/references/components/user-message.md +424 -0
  124. package/skills/blueking-chat-x/references/components/user-question-answered-card.md +104 -0
  125. package/skills/blueking-chat-x/references/components/user-question-card.md +231 -0
  126. package/skills/blueking-chat-x/references/components/user-question-choice.md +105 -0
  127. package/skills/blueking-chat-x/references/components/user-question-option.md +42 -0
  128. package/skills/blueking-chat-x/references/components/vnode-renderer.md +122 -0
  129. package/skills/blueking-chat-x/references/composables/use-animation-text.md +196 -0
  130. package/skills/blueking-chat-x/references/composables/use-artifact-preview.md +231 -0
  131. package/skills/blueking-chat-x/references/composables/use-clipboard.md +203 -0
  132. package/skills/blueking-chat-x/references/composables/use-command-selection.md +150 -0
  133. package/skills/blueking-chat-x/references/composables/use-container-scroll.md +57 -0
  134. package/skills/blueking-chat-x/references/composables/use-custom-tab.md +158 -0
  135. package/skills/blueking-chat-x/references/composables/use-flow-node-actions.md +157 -0
  136. package/skills/blueking-chat-x/references/composables/use-full-screen.md +112 -0
  137. package/skills/blueking-chat-x/references/composables/use-global-config.md +148 -0
  138. package/skills/blueking-chat-x/references/composables/use-menu-keydown.md +163 -0
  139. package/skills/blueking-chat-x/references/composables/use-message-group.md +247 -0
  140. package/skills/blueking-chat-x/references/composables/use-observer-visible-list.md +188 -0
  141. package/skills/blueking-chat-x/references/composables/use-parent-scrolling.md +46 -0
  142. package/skills/blueking-chat-x/references/theme/theme.md +431 -0
  143. package/skills/blueking-chat-x/references/types/constants.md +307 -0
  144. package/skills/blueking-chat-x/references/types/interrupt.md +379 -0
  145. package/skills/blueking-chat-x/references/types/messages.md +553 -0
  146. package/skills/blueking-chat-x/references/types/schema.md +91 -0
  147. package/skills/blueking-chat-x/scripts/generate-references.mjs +314 -0
@@ -0,0 +1,233 @@
1
+ # UserFeedback 用户反馈
2
+
3
+ > 能力域:工具与反馈 | 导入:`import { UserFeedback } from '@blueking/chat-x'` | since 1.0.0
4
+
5
+ 用户反馈弹层,提交踩/反馈原因。 源码位置:src/components/message-tools/user-feedback/user-feedback.vue。
6
+
7
+ **关联**:message-tools(点赞/踩操作触发并收集反馈)
8
+
9
+ ---
10
+
11
+ # MessageUserFeedback 用户反馈
12
+ ## 源码事实
13
+
14
+ - **源码位置**:`src/components/message-tools/user-feedback/user-feedback.vue`
15
+ - **能力域**:工具与反馈
16
+ - **能力说明**:用户反馈弹层,提交踩/反馈原因。
17
+
18
+ > **能力域**:工具与反馈
19
+
20
+ AI 消息点赞/踩后收集用户具体反馈原因的弹出面板。支持多选预设原因标签、补充文字说明(textarea)、异步加载原因列表(骨架屏)。
21
+
22
+ > **通常不需要直接使用。** `MessageTools` 在用户点击 `like`/`unlike` 工具按钮时,会通过内置 Tippy 弹出层自动呈现本组件,并驱动 `loading` 和 `reasonList`。
23
+
24
+ ## 组件结构
25
+
26
+ ```
27
+ .ai-user-feedback(width: 400px,padding: 16px,gap: 16px)
28
+ ├── .ai-feedback-title(font-size: 16px,color: #313238)
29
+ │ props.title
30
+
31
+ ├── .ai-feedback-reason-list(flex-wrap,gap: 4px)
32
+ │ loading=true → 8 × .reason-item.ai-skeleton-element(每项 width: 70px)
33
+ │ loading=false → v-for reasonList → .reason-item
34
+ │ is-active(已选):color #1768ef,bg #e1ecff
35
+ │ :hover :同上(与 is-active 共享样式)
36
+
37
+ ├── .ai-feedback-other
38
+ │ bkui-vue Input(type=textarea,rows=3,placeholder="说出您的想法")
39
+ │ → v-model 绑定内部 shallowRef otherReason
40
+
41
+ └── .ai-feedback-footer(justify-content: flex-end,gap: 8px)
42
+ Button primary "提交"(width: 64px,disabled:selectedReasons 空且 otherReason 空)
43
+ Button default "取消"(width: 64px)
44
+ ```
45
+
46
+ ## 基础用法
47
+
48
+ ```vue
49
+ <template>
50
+ <MessageUserFeedback
51
+ title="什么原因让你满意?"
52
+ :reason-list="reasonList"
53
+ @submit="handleSubmit"
54
+ @cancel="handleCancel"
55
+ />
56
+ </template>
57
+
58
+ <script setup lang="ts">
59
+ import { MessageUserFeedback } from '@blueking/chat-x';
60
+
61
+ const reasonList = ['回答准确', '信息全面', '表达清晰', '解决了问题', '示例恰当'];
62
+
63
+ const handleSubmit = (selectedReasons: string[], otherReason: string) => {
64
+ // selectedReasons: 当前已勾选的原因(提交后组件不自动清空)
65
+ // otherReason: textarea 中的补充说明(可为空字符串)
66
+ console.log('已选原因:', selectedReasons, '补充说明:', otherReason);
67
+ };
68
+
69
+ const handleCancel = () => {
70
+ // cancel 触发前组件已清空 selectedReasons 和 otherReason
71
+ console.log('用户取消了反馈');
72
+ };
73
+ </script>
74
+ ```
75
+
76
+ **满意反馈**
77
+
78
+ **不满意反馈**
79
+
80
+ ## 加载状态
81
+
82
+ 原因列表通常需要异步获取,将 `loading` 设为 `true` 时渲染 **8 个**骨架屏占位块(固定数量,与 `reasonList` 无关),数据就绪后切换为 `false`:
83
+
84
+ ```vue
85
+ <template>
86
+ <MessageUserFeedback
87
+ title="什么原因让你满意?"
88
+ :reason-list="reasonList"
89
+ :loading="isLoading"
90
+ @submit="handleSubmit"
91
+ @cancel="handleCancel"
92
+ />
93
+ </template>
94
+
95
+ <script setup lang="ts">
96
+ import { ref } from 'vue';
97
+ import { MessageUserFeedback } from '@blueking/chat-x';
98
+
99
+ const isLoading = ref(true);
100
+ const reasonList = ref<string[]>([]);
101
+
102
+ async function fetchReasons() {
103
+ isLoading.value = true;
104
+ try {
105
+ reasonList.value = await fetchFeedbackReasons();
106
+ } finally {
107
+ isLoading.value = false;
108
+ }
109
+ }
110
+ </script>
111
+ ```
112
+
113
+ **骨架屏效果**
114
+
115
+ ## 交互说明
116
+
117
+ | 操作 | 行为说明 |
118
+ | ------------ | ------------------------------------------------------------------------------------------------------------- |
119
+ | 点击原因标签 | **多选**,高亮(`is-active`);再次点击取消选中;hover 效果与选中态相同 |
120
+ | 填写补充说明 | 可选;不选任何标签时,仅有补充说明文本也可解锁提交按钮 |
121
+ | 点击提交 | `selectedReasons.length === 0 && otherReason === ''` 时禁用;点击后触发 `submit` 事件,**组件不自动清空状态** |
122
+ | 点击取消 | 先将 `selectedReasons` 和 `otherReason` 清空(两者均重置),再触发 `cancel` 事件 |
123
+
124
+ > **提交与取消的状态差异**:点击"提交"后内部 `selectedReasons` / `otherReason` **不重置**,由父组件决定后续行为(如关闭弹层);点击"取消"则**立即重置**两者,再触发事件。
125
+
126
+ ## 与 MessageTools 配合使用
127
+
128
+ `MessageUserFeedback` 在实际场景中由 `MessageTools` 驱动,整体流程:
129
+
130
+ ```
131
+ 用户点击 like / unlike
132
+
133
+ MessageTools 内部:loading=true,弹出反馈面板(骨架屏)
134
+
135
+ 调用 onAction(tool) → 返回 string[](支持 async)
136
+
137
+ loading=false,展示原因标签列表
138
+
139
+ 用户选择原因 → 点击提交
140
+
141
+ 触发 onAgentFeedback(tool, messages, reasonList, otherReason)
142
+ ```
143
+
144
+ ```vue
145
+ <template>
146
+ <MessageContainer
147
+ :messages="messages"
148
+ :on-agent-action="handleAgentAction"
149
+ :on-agent-feedback="handleFeedback"
150
+ />
151
+ </template>
152
+
153
+ <script setup lang="ts">
154
+ import { MessageContainer, type IToolBtn, type Message } from '@blueking/chat-x';
155
+
156
+ const messages: Message[] = [
157
+ /* ... */
158
+ ];
159
+
160
+ // 点击 like/unlike 时调用,返回原因列表(支持异步)
161
+ const handleAgentAction = async (tool: IToolBtn): Promise<string[]> => {
162
+ if (tool.id === 'like') {
163
+ return ['回答准确', '信息全面', '表达清晰', '解决了问题'];
164
+ }
165
+ if (tool.id === 'unlike') {
166
+ return ['信息错误', '回答不相关', '解释不清楚', '没有解决问题'];
167
+ }
168
+ return [];
169
+ };
170
+
171
+ // 用户提交反馈后触发
172
+ const handleFeedback = (tool: IToolBtn, messages: Message[], reasonList: string[], otherReason: string) => {
173
+ console.log(`${tool.id} 反馈:`, { reasonList, otherReason });
174
+ // 上报到后端
175
+ };
176
+ </script>
177
+ ```
178
+
179
+ 若需在自定义位置独立使用,可配合 `vue-tippy`:
180
+
181
+ ```vue
182
+ <template>
183
+ <Tippy
184
+ :arrow="false"
185
+ interactive
186
+ trigger="click"
187
+ theme="ai-chat-box-light light"
188
+ :offset="[0, 6]"
189
+ :append-to="() => document.body"
190
+ >
191
+ <button>👍 点赞</button>
192
+ <template #content>
193
+ <MessageUserFeedback
194
+ title="什么原因让你满意?"
195
+ :reason-list="reasonList"
196
+ :loading="isLoading"
197
+ @submit="handleSubmit"
198
+ @cancel="handleCancel"
199
+ />
200
+ </template>
201
+ </Tippy>
202
+ </template>
203
+ ```
204
+
205
+ ## API
206
+
207
+ ### Props
208
+
209
+ | 属性名 | 类型 | 必填 | 默认值 | 说明 |
210
+ | ---------- | ---------- | ---- | ------- | ------------------------------------------------------ |
211
+ | title | `string` | ✓ | — | 面板标题文本 |
212
+ | reasonList | `string[]` | ✓ | — | 预设原因标签列表;`loading=true` 时列表不渲染 |
213
+ | loading | `boolean` | — | `false` | `true` 时显示 8 个骨架屏占位块,隐藏 `reasonList` 内容 |
214
+
215
+ ### Events
216
+
217
+ | 事件名 | 参数签名 | 触发时机 |
218
+ | ------ | --------------------------------------------- | ----------------------------------------------------------- |
219
+ | submit | `(reasonList: string[], otherReason: string)` | 点击提交按钮时(至少一项原因或补充说明不为空) |
220
+ | cancel | — | 点击取消按钮时(内部已重置 selectedReasons 和 otherReason) |
221
+
222
+ ### 内部状态
223
+
224
+ 以下为组件内部 `shallowRef` 状态,不暴露为 props/emits:
225
+
226
+ | 状态名 | 类型 | 说明 |
227
+ | --------------- | ---------- | ------------------------------------------- |
228
+ | selectedReasons | `string[]` | 当前已选原因列表;取消时重置,提交时不重置 |
229
+ | otherReason | `string` | textarea 补充说明;取消时重置,提交时不重置 |
230
+
231
+ ## 关联组件
232
+
233
+ - [MessageTools](/components/feedback/message-tools) — 点赞/踩入口与反馈联动
@@ -0,0 +1,424 @@
1
+ # UserMessage 用户消息
2
+
3
+ > 能力域:消息系统 | 导入:`import { UserMessage } from '@blueking/chat-x'` | since 0.0.20
4
+
5
+ 渲染用户消息:纯文本(非 Markdown)、键值引用、二进制附件与编辑态 ChatInput / ShortcutRender; 工具栏含 copy / cite / edit / delete。源码位置:src/components/chat-message/user-message/user-message.vue。
6
+
7
+ **关联**:message-render(由 MessageRender 在 role 为 user 时创建)、message-tools(消息工具栏交互与状态由 MessageTools 体系承载)、message-time(createdAt 经工具栏 prepend 插槽展示)、message-container(嵌入列表时由 MessageContainer 管理分组与多选)、chat-input(编辑态普通消息使用 ChatInput)
8
+
9
+ ---
10
+
11
+ # UserMessage 用户消息
12
+
13
+ ## 源码事实
14
+
15
+ - **源码位置**:`src/components/chat-message/user-message/user-message.vue`
16
+ - **能力域**:消息系统
17
+ - **能力说明**:渲染用户消息:纯文本、键值引用、文件附件与编辑态输入(**不**渲染 Markdown)。
18
+
19
+ > **导出说明**:`UserMessage` **未**从 `@blueking/chat-x` 包入口导出(入口同名是 TS interface)。消费方请用 `MessageRender` / `MessageContainer`。下文 `UserMessageComp` 为文档站内部相对路径示例。
20
+
21
+ 用户消息展示组件,右对齐。支持纯文本、多媒体(图片/文件)、文本引用、结构化引用、快捷指令,以及内联编辑。
22
+
23
+ ## 组件结构
24
+
25
+ **正常模式**
26
+
27
+ ```
28
+ .ai-user-message(align-items: flex-end,gap: 6px,font-size: 12px)
29
+ ├── CiteContent(v-if:cite 为字符串)
30
+ │ 紧凑条带(高 28px,灰色 #f5f7fa),引用图标 + 单行截断文本
31
+
32
+ ├── [Binary 图片区] v-if binaryImageFiles.length
33
+ │ .ai-user-message-binary-files → FileContent(readonly=true,图片统一渲染,支持点击预览)
34
+
35
+ ├── [Binary 非图片文件区] v-for binaryNonImageFiles
36
+ │ .ai-user-message-binary-files → FileContent(readonly=true,每个文件独立渲染)
37
+
38
+ ├── .ai-user-message-content(气泡:bg #e1ecff,padding 8×12,border-radius 4px)
39
+ │ v-if: cite 为数组 → KeyValueContent(title + key/value 列表)
40
+ │ v-else-if: content → TextContent × N(textParts 中每个文本片段一个实例)
41
+
42
+ └── MessageTools(.ai-user-message-tools)
43
+ v-if: messageToolsStatus !== 'hidden'
44
+ visibility: hidden(默认)→ visible(:hover 时)
45
+ tools: [copy, cite, edit, delete],updateTools: []
46
+ #prepend slot → MessageTime(createdAt,工具图标左侧)
47
+ ```
48
+
49
+ > **时间随工具栏显隐**:时间位于工具栏内,与工具按钮共用 `visibility` 控制,因此同样在悬停消息时才可见。
50
+
51
+ **编辑模式**(点击 `edit` 按钮后 `isEdit=true`)
52
+
53
+ ```
54
+ .ai-user-message
55
+ ├── CiteContent(同上,不受编辑模式影响)
56
+
57
+ ├── ShortcutRender(v-if: shortcut 有值)
58
+ │ @close → isEdit=false
59
+ │ @submit(formModel) → onShortcutConfirm(formModel) + isEdit=false
60
+
61
+ └── ChatInput(v-else,带自定义 #send-icon slot)
62
+ v-model: editContent(取 textParts[0],即第一个文本片段)
63
+ defaultUploadFiles: binaryFiles
64
+ #send-icon slot → .user-edit-footer
65
+ Button "取消" → isEdit=false
66
+ Button primary "发送" → chatInputRef.triggerSendMessage() + isEdit=false
67
+ ```
68
+
69
+ ## 基础用法
70
+
71
+ `content` 为字符串时,通过 `TextContent` 以**纯文本**插值渲染(`{{ content }}`),**不**走 Markdown。
72
+
73
+ ```vue
74
+ <template>
75
+ <MessageRender
76
+ :message="message"
77
+ :on-action="handleAction"
78
+ />
79
+ </template>
80
+
81
+ <script setup lang="ts">
82
+ import { MessageRender, MessageRole, MessageStatus, type IToolBtn } from '@blueking/chat-x';
83
+
84
+ const message = {
85
+ id: '1',
86
+ messageId: '1',
87
+ role: MessageRole.User,
88
+ content: '你好,请帮我分析以下这段 Python 代码的性能瓶颈。',
89
+ status: MessageStatus.Complete,
90
+ };
91
+
92
+ const handleAction = async (tool: IToolBtn) => {
93
+ // copy / edit 有内置行为;cite / delete 需业务侧处理
94
+ console.log('工具操作:', tool.id);
95
+ };
96
+ </script>
97
+ ```
98
+
99
+ > **工具栏**:悬停时显示「复制」「引用」「编辑」「删除」(CSS `visibility`,始终占位)。
100
+
101
+ ## 多媒体消息
102
+
103
+ `content` 为数组时,同时支持文本(`type: 'text'`)和二进制文件(`type: 'binary'`)。组件将 `binary` 项按图片和非图片分为两组:
104
+
105
+ - **图片文件**(`binaryImageFiles`):判断 `url` 存在或 `mimeType` / `file.type` 以 `image/` 开头的文件,统一放入一个 `FileContent`(`readonly=true`)中渲染,支持点击缩略图全屏预览
106
+ - **非图片文件**(`binaryNonImageFiles`):每个文件单独渲染在 `FileContent`(`readonly=true`)中
107
+
108
+ `text` 项经 `textParts` 计算属性统一为 `string[]`,按顺序各渲染一个 `TextContent`。
109
+
110
+ ```vue
111
+ <script setup lang="ts">
112
+ import { MessageRender, MessageContentType, MessageRole, MessageStatus } from '@blueking/chat-x';
113
+
114
+ const message = {
115
+ id: '1',
116
+ messageId: '1',
117
+ role: MessageRole.User,
118
+ status: MessageStatus.Complete,
119
+ content: [
120
+ {
121
+ type: MessageContentType.Binary,
122
+ url: 'https://example.com/screenshot.png',
123
+ mimeType: 'image/png',
124
+ filename: 'screenshot.png',
125
+ },
126
+ {
127
+ type: MessageContentType.Text,
128
+ text: '请帮我分析这张架构图,指出其中的问题。',
129
+ },
130
+ ],
131
+ };
132
+ </script>
133
+ ```
134
+
135
+ ## 带引用的消息
136
+
137
+ 通过 `property.extra.cite` 传入引用内容,支持两种格式,渲染位置不同:
138
+
139
+ | `cite` 类型 | 渲染组件 | 渲染位置 |
140
+ | ------------------------- | ------------------------------------------------ | ---------------- |
141
+ | `string` | `CiteContent`(紧凑条带,高 28px,文本单行截断) | 气泡**外部上方** |
142
+ | `{ title?, data[] }` 对象 | `KeyValueContent`(键值对列表) | 气泡**内部** |
143
+
144
+ ### 文本引用
145
+
146
+ `cite` 为字符串时,在气泡上方显示一个带引用图标的灰色条带(`#f5f7fa`),文本过长时截断。
147
+
148
+ ```vue
149
+ <script setup lang="ts">
150
+ // 消费方将 property 挂在 message 上,经 MessageRender 透传
151
+ const message = {
152
+ role: 'user',
153
+ content: '这段代码每次循环都发起请求,应该如何优化?',
154
+ property: {
155
+ extra: {
156
+ cite: '// 原始代码\nfor (let i = 0; i < arr.length; i++) {\n fetch(`/api/${arr[i]}`)\n}',
157
+ },
158
+ },
159
+ };
160
+ </script>
161
+ ```
162
+
163
+ ### 结构化引用(键值对)
164
+
165
+ `cite` 为对象 `{ title?, data: { key, value }[] }` 时,引用内容渲染在气泡**内部**(`KeyValueContent` 组件):
166
+
167
+ ```vue
168
+ <script setup lang="ts">
169
+ const message = {
170
+ role: 'user',
171
+ content: '请帮我分析这份报表的数据趋势。',
172
+ property: {
173
+ extra: {
174
+ cite: {
175
+ title: '销售数据分析',
176
+ type: 'structured',
177
+ data: [
178
+ { key: '报表名称', value: '2024 年 Q4 销售报表' },
179
+ { key: '时间范围', value: '2024年10月 - 12月' },
180
+ { key: '数据量', value: '12,580 条' },
181
+ ],
182
+ },
183
+ },
184
+ },
185
+ };
186
+ </script>
187
+ ```
188
+
189
+ ## 快捷指令消息
190
+
191
+ 当消息来自快捷指令时,`property.extra.shortcut` 中携带快捷指令对象。在**编辑模式**下,组件渲染 `ShortcutRender` 代替普通 `ChatInput`。
192
+
193
+ `shortcut` computed 支持两条来源路径:
194
+
195
+ ```
196
+ 1. property.extra.shortcut 有值 → 直接使用
197
+ 2. property.extra.cite 为对象 + property.extra.context 有值
198
+ → 从 cite.data 和 context 动态构建 ShortcutComponent[] 数组
199
+ ```
200
+
201
+ ```vue
202
+ <script setup lang="ts">
203
+ const message = {
204
+ role: 'user',
205
+ content: '请帮我翻译这段文字',
206
+ property: {
207
+ extra: {
208
+ shortcut: {
209
+ id: 'translate',
210
+ name: '翻译',
211
+ components: [
212
+ {
213
+ type: 'select',
214
+ key: 'targetLang',
215
+ name: '目标语言',
216
+ default: 'en',
217
+ options: [
218
+ { label: '英文', value: 'en' },
219
+ { label: '中文', value: 'zh' },
220
+ ],
221
+ },
222
+ {
223
+ type: 'textarea',
224
+ key: 'content',
225
+ name: '翻译内容',
226
+ fillBack: true,
227
+ default: '请帮我翻译这段文字',
228
+ },
229
+ ],
230
+ formModel: { targetLang: 'en', content: '请帮我翻译这段文字' },
231
+ },
232
+ },
233
+ },
234
+ };
235
+ </script>
236
+ ```
237
+
238
+ ## 消息编辑
239
+
240
+ 点击「编辑」按钮后进入编辑模式,根据消息类型呈现不同界面:
241
+
242
+ | 消息类型 | 编辑界面 | 确认回调 |
243
+ | -------------------------------------------- | ----------------------------------------------------- | ------------------- |
244
+ | 普通文本 / 含文件消息 | `ChatInput`(自定义 `#send-icon`,含"取消/发送"按钮) | `onInputConfirm` |
245
+ | 含 `property.extra.shortcut` 或 cite+context | `ShortcutRender` | `onShortcutConfirm` |
246
+
247
+ **`editContent` 的初始化逻辑**(仅文本部分,二进制文件通过 `defaultUploadFiles` 恢复):
248
+
249
+ ```
250
+ textParts 有值 → editContent = textParts[0](取第一个文本片段)
251
+ binaryFiles 有值 → 进入编辑模式(editContent 可为空)
252
+ ```
253
+
254
+ `textParts` 由 `content` 统一计算:`string` 转为单元素数组,`InputContent[]` 则过滤出 `type: 'text'` 且非空的项并映射为 `string[]`。
255
+
256
+ ```vue
257
+ <template>
258
+ <MessageRender
259
+ :message="message"
260
+ :on-action="handleAction"
261
+ :on-input-confirm="handleInputConfirm"
262
+ :on-shortcut-confirm="handleShortcutConfirm"
263
+ />
264
+ </template>
265
+
266
+ <script setup lang="ts">
267
+ import {
268
+ MessageRender,
269
+ MessageRole,
270
+ MessageStatus,
271
+ type IToolBtn,
272
+ type TagSchema,
273
+ type UserMessage,
274
+ } from '@blueking/chat-x';
275
+
276
+ const message = {
277
+ id: '1',
278
+ messageId: '1',
279
+ role: MessageRole.User,
280
+ content: '请帮我优化这段代码',
281
+ status: MessageStatus.Complete,
282
+ };
283
+
284
+ const handleAction = async (tool: IToolBtn) => {
285
+ // edit → 组件内切编辑态;copy → 组件内复制
286
+ // cite / delete → 无内置行为,业务侧处理(如删除会话消息)
287
+ console.log('工具:', tool.id);
288
+ };
289
+
290
+ const handleInputConfirm = async (content: UserMessage['content'], docSchema: TagSchema) => {
291
+ console.log('编辑后内容:', content, docSchema);
292
+ };
293
+
294
+ const handleShortcutConfirm = async (formModel: Record<string, unknown>) => {
295
+ console.log('快捷指令表单:', formModel);
296
+ };
297
+ </script>
298
+ ```
299
+
300
+ ## 工具按钮
301
+
302
+ 工具栏使用 CSS `visibility` 控制可见性(非 `display`),始终占位,hover 时显示:
303
+
304
+ **内置工具列表(`CONST_USER_MESSAGE_TOOLS`)**
305
+
306
+ | 工具 ID | 名称 | 内置行为 |
307
+ | -------- | ---- | -------------------------------------------- |
308
+ | `copy` | 复制 | 字符串直接复制;数组 `JSON.stringify` 后复制 |
309
+ | `cite` | 引用 | 无内置行为,需通过 `onAction` 外部处理 |
310
+ | `edit` | 编辑 | 切换 `isEdit=true`,进入编辑模式 |
311
+ | `delete` | 删除 | 无内置行为,需通过 `onAction` 外部处理 |
312
+
313
+ 可通过 `messageTools` 按 id 覆盖/追加,`{ id: 'edit', hidden: true }` 可隐藏内置项。
314
+
315
+ ```vue
316
+ <!-- 经 MessageRender 控制工具栏状态 -->
317
+ <MessageRender
318
+ :message="message"
319
+ message-tools-status="hidden"
320
+ />
321
+ <MessageRender
322
+ :message="message"
323
+ message-tools-status="disabled"
324
+ />
325
+ ```
326
+
327
+ ## supportUpload 透传
328
+
329
+ 编辑态 `ChatInput` 的上传能力来自 `injectGlobalConfig().supportUpload`(通常由 `ChatContainer` 的 `supportUpload` prop 注册)。自定义 `#message` 插槽时须把同一配置链路保留,否则编辑态会与主输入区不一致。
330
+
331
+ ```vue
332
+ <template>
333
+ <ChatContainer
334
+ :messages="messages"
335
+ :support-upload="true"
336
+ :on-agent-action="handleAgentAction"
337
+ :on-user-action="handleUserAction"
338
+ >
339
+ <template #message="{ message, messageToolsStatus, onInterruptResume }">
340
+ <MessageRender
341
+ :message="message"
342
+ :message-tools-status="messageToolsStatus"
343
+ :on-action="handleUserAction"
344
+ :on-input-confirm="(content, docSchema) => handleUserInputConfirm(message, content, docSchema)"
345
+ :on-shortcut-confirm="formModel => handleUserShortcutConfirm(message, formModel)"
346
+ :on-interrupt-resume="onInterruptResume"
347
+ />
348
+ </template>
349
+ </ChatContainer>
350
+ </template>
351
+ ```
352
+
353
+ ## API
354
+
355
+ ### Props
356
+
357
+ | 属性名 | 类型 | 说明 |
358
+ | ------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
359
+ | content | `string \| InputContent[]` | 消息内容,字符串或含 text/binary 的数组 |
360
+ | createdAt | `number \| string` | 消息创建时间,经 `MessageTools` 的 `#prepend` 插槽交给 `MessageTime` 渲染在工具图标左侧;无值时不展示 |
361
+ | property | `{ extra?: MessageExtra; artifacts?: AIFileInfo[] }` | 附加属性;本组件消费 `extra.cite` / `shortcut` / `context` |
362
+ | messageTools | `IToolBtn[]` | 自定义用户消息工具组;按 id 与 `CONST_USER_MESSAGE_TOOLS` 合并,`{ id, hidden: true }` 可隐藏 |
363
+ | messageToolsStatus | `MessageToolsStatus` | 工具按钮状态,`disabled` 禁用、`hidden` 从 DOM 移除 |
364
+ | onAction | `MessageToolsProps['onAction']` | 工具回调;`copy`/`edit` 有内置行为,`cite`/`delete` 需外部处理 |
365
+ | onInputConfirm | `(content: UserMessage['content'], docSchema: TagSchema) => Promise<void>` | 普通消息编辑确认回调 |
366
+ | onShortcutConfirm | `(formModel: Record<string, unknown>) => Promise<void>` | 快捷指令消息编辑确认回调 |
367
+ | tippyOptions | `Partial<Omit<TippyOptions, 'getReferenceClientRect' \| 'triggerTarget'>>` | 自定义工具栏 Tippy 配置,透传给内部 `MessageTools` |
368
+
369
+ ### Events / Slots / Expose
370
+
371
+ 无。
372
+
373
+ ### 全局配置依赖
374
+
375
+ 编辑态 `ChatInput` 通过 `injectGlobalConfig()` 读取 `supportUpload`。祖先需已 `useGlobalConfig()`(通常由 `ChatContainer` 注册)。
376
+
377
+ ## 类型定义
378
+
379
+ ```typescript
380
+ // 文本内容项
381
+ interface TextInputContent {
382
+ type: 'text';
383
+ text: string;
384
+ }
385
+
386
+ // 二进制内容项(图片、文件)
387
+ interface BinaryContent {
388
+ type: 'binary';
389
+ url?: string;
390
+ mimeType?: string;
391
+ filename?: string;
392
+ }
393
+
394
+ type InputContent = TextInputContent | BinaryContent;
395
+
396
+ // property.extra(与源码 BaseMessage.property.extra 对齐)
397
+ type MessageExtra = {
398
+ // 文本引用 或 结构化引用(互斥 union,不是两个同名字段)
399
+ cite?:
400
+ | string
401
+ | {
402
+ title: string;
403
+ type: 'structured';
404
+ data: Array<{ key: string; value: string }>;
405
+ };
406
+ command?: string;
407
+ pause?: boolean;
408
+ shortcut?: Partial<Shortcut>;
409
+ context?: Array<{
410
+ __key: string;
411
+ __label: string;
412
+ __value: string;
413
+ fillBack?: boolean;
414
+ context_type?: string;
415
+ }>;
416
+ };
417
+ ```
418
+
419
+ ## 关联组件
420
+
421
+ - [MessageRender](/components/message/message-render) — user 角色由其实例化
422
+ - [MessageTools](/components/feedback/message-tools) — 工具栏交互
423
+ - [MessageTime](/components/feedback/message-time) — 工具栏左侧的消息时间
424
+ - [MessageContainer](/components/setup/message-container) — 列表与多选容器