@blueking/chat-x 0.0.48-beta.1 → 0.0.49-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.
- package/dist/ag-ui/types/constants.d.ts +1 -0
- package/dist/ag-ui/types/file.d.ts +23 -0
- package/dist/ag-ui/types/index.d.ts +1 -0
- package/dist/ag-ui/types/messages.d.ts +2 -0
- package/dist/components/chat-message/assistant-message/assistant-message.vue.d.ts +12 -1
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-file-card.vue.d.ts +12 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/artifact-preview-host.vue.d.ts +7 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/preview-strategy.d.ts +9 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/html-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/markdown-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/txt-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/renderers/url-iframe-preview.vue.d.ts +6 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/artifact-preview/use-artifact-preview-loader.d.ts +23 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue.d.ts +12 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/file-icon.d.ts +29 -0
- package/dist/components/chat-message/assistant-message/message-artifacts/message-artifacts.vue.d.ts +9 -0
- package/dist/components/chat-message/interrupt-message/user-question/use-user-question.d.ts +7 -2
- package/dist/components/chat-message/user-message/user-message.vue.d.ts +14 -2
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/use-artifact-preview.d.ts +56 -0
- package/dist/composables/use-custom-tab.d.ts +2 -0
- package/dist/composables/use-message-group.d.ts +433 -0
- package/dist/icons/file.d.ts +24 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/index.css +1 -1
- package/dist/index.js +2217 -1689
- package/dist/index.js.map +1 -1
- package/dist/lang/lang.d.ts +8 -1
- package/dist/mcp/generated/docs/activity-message.md +122 -97
- package/dist/mcp/generated/docs/assistant-message.md +125 -62
- package/dist/mcp/generated/docs/chat-container.md +97 -18
- package/dist/mcp/generated/docs/chat-input.md +2 -10
- package/dist/mcp/generated/docs/constants.md +3 -1
- package/dist/mcp/generated/docs/content-render.md +2 -10
- package/dist/mcp/generated/docs/file-artifact-panel.md +275 -0
- package/dist/mcp/generated/docs/info-message.md +29 -12
- package/dist/mcp/generated/docs/interrupt.md +1 -0
- package/dist/mcp/generated/docs/loading-message.md +36 -17
- package/dist/mcp/generated/docs/message-container.md +4 -21
- package/dist/mcp/generated/docs/message-render.md +47 -59
- package/dist/mcp/generated/docs/messages.md +5 -0
- package/dist/mcp/generated/docs/reasoning-message.md +17 -20
- package/dist/mcp/generated/docs/tool-message.md +61 -45
- package/dist/mcp/generated/docs/toolcall-render.md +8 -8
- package/dist/mcp/generated/docs/use-artifact-preview.md +232 -0
- package/dist/mcp/generated/docs/use-custom-tab.md +18 -5
- package/dist/mcp/generated/docs/use-message-group.md +29 -0
- package/dist/mcp/generated/docs/user-message.md +185 -121
- package/dist/mcp/generated/docs/user-question-card.md +6 -3
- package/dist/mcp/generated/index.json +83 -13
- package/dist/mcp/index.js +0 -0
- package/package.json +20 -21
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
汇总当前会话所有 AssistantMessage 的 artifacts(按 outputId 去重),支持关键词搜索、列表选中与下载; 预览区委托 ArtifactPreviewHost:按类型走 text_from_download(html / markdown / md / txt / json) 或 preview_url_iframe(其余类型);download_url / preview_url 经 onArtifactClick 异步获取(TTL 缓存,重试 force); 预览重载键为 outputId:type;常规 resolveArtifactUrls 只传 file。 源码位置:src/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **assistant-message** — 文件产物来源于 AssistantMessage.property.artifacts
|
|
8
|
+
- **chat-container** — 面板挂载在侧栏「文件产物」Tab(固定、不可关闭),并通过 onArtifactClick 异步取链
|
|
9
|
+
- **execution-summary** — 同为 ChatContainer 侧栏 Tab 面板,交互形态一致
|
|
10
|
+
- **message-loading** — ArtifactPreviewHost 取链 / 拉取正文过程使用 MessageLoading
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
<!-- FULL DOC -->
|
|
14
|
+
|
|
15
|
+
# FileArtifactPanel 文件产物预览
|
|
16
|
+
|
|
17
|
+
## 源码事实
|
|
18
|
+
|
|
19
|
+
- **源码位置**:`src/components/chat-message/assistant-message/message-artifacts/file-artifact-panel.vue`
|
|
20
|
+
- **能力域**:消息系统
|
|
21
|
+
- **能力说明**:汇总当前会话全部文件产物;左侧列表搜索与选中,右侧预览委托内部 `ArtifactPreviewHost`。
|
|
22
|
+
|
|
23
|
+
> **导出说明**:内部侧栏面板组件,**通常不直接使用**;由 `ChatContainer` 在「文件产物」Tab 内自动挂载。预览加载与渲染为同目录下 `artifact-preview/` 内部实现,不单独导出。
|
|
24
|
+
|
|
25
|
+
点击 AI 回复中的[文件卡片](/components/message/assistant-message)后,`ChatContainer` 侧栏会弹出固定的「文件产物」Tab,聚合展示当前会话**所有** `AssistantMessage` 的文件产物(按 `outputId` 去重),并命中被点击的文件进行预览。
|
|
26
|
+
|
|
27
|
+
面板左侧为可搜索的文件列表,右侧为预览区。通常不需要直接使用,由 `ChatContainer` 在侧栏内自动渲染。
|
|
28
|
+
|
|
29
|
+
## 核心能力
|
|
30
|
+
|
|
31
|
+
- **会话级聚合**:拍平当前会话所有 `AssistantMessage.property.artifacts`,以 `outputId` 去重后统一在一个列表内展示
|
|
32
|
+
- **唯一命中**:以 `outputId` 作为会话内唯一键(同 `outputId` 视为同一文件);文件名可能重复,不可作唯一键
|
|
33
|
+
- **关键词搜索**:按文件名实时过滤列表
|
|
34
|
+
- **异步取链**:`AIFileInfo` 本身不含 `url` / `previewUrl`,通过 `ChatContainer` 的 `onArtifactClick` 按 `outputId` 获取 `download_url` / `preview_url`(TTL 8 分钟缓存;预览重试会 `force` 刷新)
|
|
35
|
+
- **职责拆分**:
|
|
36
|
+
- **面板本身**:列表、搜索、预览头(文件名 / 图标 / 下载)
|
|
37
|
+
- **`ArtifactPreviewHost`**:按策略加载正文或预览 URL,分派到对应 renderer;展示 loading / empty / error(含重试)
|
|
38
|
+
- **未传 `onArtifactClick`**:下载按钮隐藏,预览区展示无数据
|
|
39
|
+
|
|
40
|
+
## 基础用法
|
|
41
|
+
|
|
42
|
+
面板**未从包入口导出**,业务侧请走下方「业务接入」;下列示例仅用于文档站 / 本地调试(与 `ExecutionSummary` 文档站写法一致:相对路径引入 + 自行挂 Provider)。
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<template>
|
|
46
|
+
<div style="height: 480px; border: 1px solid #dcdee5; border-radius: 8px; overflow: hidden;">
|
|
47
|
+
<FileArtifactPanel
|
|
48
|
+
:active-id="activeArtifactId"
|
|
49
|
+
:artifacts="sessionArtifacts"
|
|
50
|
+
@select="handleSelect"
|
|
51
|
+
/>
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<script setup lang="ts">
|
|
56
|
+
import { shallowRef } from 'vue'
|
|
57
|
+
import { useArtifactPreviewProvider } from '@blueking/chat-x'
|
|
58
|
+
import type { AIFileInfo, SessionArtifact } from '@blueking/chat-x'
|
|
59
|
+
// 内部组件:仅文档 / 调试;业务请用 ChatContainer 自动挂载
|
|
60
|
+
import FileArtifactPanel from './message-artifacts/file-artifact-panel.vue'
|
|
61
|
+
|
|
62
|
+
const sessionArtifacts: SessionArtifact[] = [
|
|
63
|
+
{ name: '周报.html', outputId: 'a-html', size: 10240, type: 'html' },
|
|
64
|
+
{ name: '说明.md', outputId: 'a-md', size: 8192, type: 'md' },
|
|
65
|
+
{ name: '纪要.txt', outputId: 'a-txt', size: 4096, type: 'txt' },
|
|
66
|
+
{ name: '配置.json', outputId: 'a-json', size: 2048, type: 'json' },
|
|
67
|
+
{ name: '立项.pdf', outputId: 'a-pdf', size: 204800, type: 'pdf' },
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
useArtifactPreviewProvider({
|
|
71
|
+
getOnArtifactClick: () => async file => {
|
|
72
|
+
// 文本类返回可 fetch 的 download_url;iframe 类返回 preview_url
|
|
73
|
+
const res = await api.getArtifactUrls(file.outputId)
|
|
74
|
+
return { download_url: res.download_url, preview_url: res.preview_url }
|
|
75
|
+
},
|
|
76
|
+
onOpen: () => {},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const activeArtifactId = shallowRef(sessionArtifacts[0].outputId)
|
|
80
|
+
const handleSelect = (id: string) => {
|
|
81
|
+
activeArtifactId.value = id
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**渲染效果**(点击左侧列表切换类型;文本类直渲染,PDF 走 iframe。Mock 取链约 600ms)
|
|
87
|
+
|
|
88
|
+
## 业务接入(ChatContainer)
|
|
89
|
+
|
|
90
|
+
日常用法是给容器传 `messages`(含 `property.artifacts`)与 `onArtifactClick`,点击文件卡片即可打开侧栏面板:
|
|
91
|
+
|
|
92
|
+
```vue
|
|
93
|
+
<template>
|
|
94
|
+
<ChatContainer
|
|
95
|
+
v-model="input"
|
|
96
|
+
:messages="messages"
|
|
97
|
+
:on-artifact-click="onArtifactClick"
|
|
98
|
+
@send-message="handleSend"
|
|
99
|
+
/>
|
|
100
|
+
</template>
|
|
101
|
+
|
|
102
|
+
<script setup lang="ts">
|
|
103
|
+
import { ref, shallowRef } from 'vue'
|
|
104
|
+
import {
|
|
105
|
+
ChatContainer,
|
|
106
|
+
MessageRole,
|
|
107
|
+
MessageStatus,
|
|
108
|
+
type AIFileInfo,
|
|
109
|
+
type Message,
|
|
110
|
+
} from '@blueking/chat-x'
|
|
111
|
+
|
|
112
|
+
const input = ref('')
|
|
113
|
+
const messages = shallowRef<Message[]>([
|
|
114
|
+
{
|
|
115
|
+
id: 'u1',
|
|
116
|
+
messageId: 'u1',
|
|
117
|
+
role: MessageRole.User,
|
|
118
|
+
status: MessageStatus.Complete,
|
|
119
|
+
content: '整理本周评审材料',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'a1',
|
|
123
|
+
messageId: 'a1',
|
|
124
|
+
uid: 'assistant-uid-1',
|
|
125
|
+
role: MessageRole.Assistant,
|
|
126
|
+
status: MessageStatus.Complete,
|
|
127
|
+
content: '已生成评审材料,点击卡片可在侧栏预览:',
|
|
128
|
+
property: {
|
|
129
|
+
artifacts: [
|
|
130
|
+
{ name: '周报.html', outputId: 'a-html', size: 10240, type: 'html' },
|
|
131
|
+
{ name: '说明.md', outputId: 'a-md', size: 8192, type: 'md' },
|
|
132
|
+
{ name: '配置.json', outputId: 'a-json', size: 2048, type: 'json' },
|
|
133
|
+
{ name: '立项.pdf', outputId: 'a-pdf', size: 204800, type: 'pdf' },
|
|
134
|
+
] satisfies AIFileInfo[],
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
])
|
|
138
|
+
|
|
139
|
+
const onArtifactClick = async (file: AIFileInfo) => {
|
|
140
|
+
const res = await api.getArtifactUrls(file.outputId)
|
|
141
|
+
return {
|
|
142
|
+
download_url: res.download_url,
|
|
143
|
+
preview_url: res.preview_url,
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const handleSend = () => {
|
|
148
|
+
/* ... */
|
|
149
|
+
}
|
|
150
|
+
</script>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 触发链路
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
ArtifactFileCard(点击文件卡片)
|
|
157
|
+
└─ useArtifactPreviewConsumer().openPreview({ file })
|
|
158
|
+
└─ useArtifactPreviewProvider(ChatContainer 内)
|
|
159
|
+
├─ 记录命中文件 activeArtifactId = file.outputId
|
|
160
|
+
└─ onOpen → addCustomTab('file-artifact') 展开并选中侧栏 Tab
|
|
161
|
+
└─ FileArtifactPanel
|
|
162
|
+
├─ 列表 @select → setActiveArtifactId(outputId)
|
|
163
|
+
├─ 下载 → resolveArtifactUrls + triggerArtifactDownload
|
|
164
|
+
└─ ArtifactPreviewHost
|
|
165
|
+
├─ useArtifactPreviewLoader(策略 + fetch / 取链,防竞态)
|
|
166
|
+
└─ HtmlPreview | MarkdownPreview | TxtPreview | UrlIframePreview
|
|
167
|
+
|
|
168
|
+
sessionArtifacts 有产物时
|
|
169
|
+
└─ ensureCustomTab('file-artifact') 静默挂上,不抢当前选中(如执行情况)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- 文件卡片通过 `useArtifactPreviewConsumer` 注入预览上下文,无 Provider 时卡片不可点击(兜底 `undefined`)
|
|
173
|
+
- `ChatContainer` 通过 `useArtifactPreviewProvider` 提供上下文,并把「打开侧栏 Tab」这一副作用以 `onOpen` 注入,保持 composable 职责单一
|
|
174
|
+
- 侧栏「文件产物」Tab 固定不可关闭,`order: -1` 排在「执行情况」之前;会话切换或无文件产物时自动移除
|
|
175
|
+
|
|
176
|
+
## 唯一键规则
|
|
177
|
+
|
|
178
|
+
会话内以 **`outputId`** 作为文件产物唯一键:
|
|
179
|
+
|
|
180
|
+
- 同一 `outputId` 在多条消息中出现时,聚合列表去重并保留最后一次出现的文件信息
|
|
181
|
+
- `activeId`、列表 `:key`、`select` 事件参数均使用 `outputId`
|
|
182
|
+
- 文件名可能重复,**不可**作为唯一键
|
|
183
|
+
|
|
184
|
+
## 预览机制
|
|
185
|
+
|
|
186
|
+
预览由内部 `getArtifactPreviewStrategy(type)` 决定 **加载方式** 与 **渲染器**;面板不直接写死类型分支。
|
|
187
|
+
|
|
188
|
+
| 文件类型 | load | 取链字段 | renderer |
|
|
189
|
+
| -------- | ---- | -------- | -------- |
|
|
190
|
+
| `html` | `text_from_download` | `download_url` → `fetch` 正文 | `HtmlPreview`(`<iframe srcdoc>`) |
|
|
191
|
+
| `markdown` / `md` | `text_from_download` | 同上 | `MarkdownPreview`(`MarkdownContent`) |
|
|
192
|
+
| `txt` / `json` | `text_from_download` | 同上 | `TxtPreview`(`<pre>`) |
|
|
193
|
+
| 其余(如 `pdf` / `jpg`) | `preview_url_iframe` | `preview_url` | `UrlIframePreview`(`<iframe src>`,一般为后台转好的 PDF) |
|
|
194
|
+
|
|
195
|
+
> `md`(`AIFileType.Md`)为后台扩展名别名,与 `markdown`(`AIFileType.Markdown`)等价,共用 Markdown 直渲染。
|
|
196
|
+
|
|
197
|
+
### 加载态
|
|
198
|
+
|
|
199
|
+
| status | 表现 |
|
|
200
|
+
| ------ | ---- |
|
|
201
|
+
| `loading` | 预览区 [MessageLoading](/components/helper/message-loading) |
|
|
202
|
+
| `ready` | 对应 renderer 渲染 |
|
|
203
|
+
| `empty` | 「暂无可预览的文件」(无文件 / 未传 `onArtifactClick` / 缺所需 URL) |
|
|
204
|
+
| `error` | 「预览加载失败」+ 重试按钮 |
|
|
205
|
+
|
|
206
|
+
### 重载与取链约定
|
|
207
|
+
|
|
208
|
+
- **重载键**:`ArtifactPreviewHost` 以 `` `${outputId}:${type}` `` 监听文件变化;`outputId` 或 `type` 任一变化会重新 `load()`,仅改文件名等其它字段不会
|
|
209
|
+
- **常规取链**:`resolveArtifactUrls(file)`,只传文件,不传第二参
|
|
210
|
+
- **重试 / 强刷**:错误态点击重试走 `load({ force: true })` → `resolveArtifactUrls(file, { force: true })`,绕过 TTL 缓存重新取链
|
|
211
|
+
- **竞态**:切换文件时 `useArtifactPreviewLoader` 用 `loadSeq` + `AbortController` 中断上一次 `fetch`,避免过期结果覆盖最新内容
|
|
212
|
+
|
|
213
|
+
下载图标仍由面板用 bkui `Loading` spin 单独表达。
|
|
214
|
+
|
|
215
|
+
## 内部结构(不导出)
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
message-artifacts/
|
|
219
|
+
├── file-artifact-panel.vue # 列表 + 下载头 + 挂载 Host
|
|
220
|
+
└── artifact-preview/
|
|
221
|
+
├── artifact-preview-host.vue # 状态机 UI + 分派 renderer
|
|
222
|
+
├── preview-strategy.ts # getArtifactPreviewStrategy
|
|
223
|
+
├── use-artifact-preview-loader.ts
|
|
224
|
+
└── renderers/
|
|
225
|
+
├── html-preview.vue
|
|
226
|
+
├── markdown-preview.vue
|
|
227
|
+
├── txt-preview.vue
|
|
228
|
+
└── url-iframe-preview.vue
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## API
|
|
232
|
+
|
|
233
|
+
### Props
|
|
234
|
+
|
|
235
|
+
| 属性名 | 类型 | 必填 | 说明 |
|
|
236
|
+
| --------- | ------------------- | ---- | -------------------------------------- |
|
|
237
|
+
| activeId | `string` | ✓ | 当前命中的文件 `outputId` |
|
|
238
|
+
| artifacts | `SessionArtifact[]` | ✓ | 当前会话全部文件产物(已按 `outputId` 去重) |
|
|
239
|
+
|
|
240
|
+
### Events
|
|
241
|
+
|
|
242
|
+
| 事件名 | 参数 | 说明 |
|
|
243
|
+
| ------ | ----------------- | -------------------------- |
|
|
244
|
+
| select | `(id: string)` | 列表内切换选中文件,参数为文件 `outputId` |
|
|
245
|
+
|
|
246
|
+
### Slots / Expose
|
|
247
|
+
|
|
248
|
+
无。
|
|
249
|
+
|
|
250
|
+
## 类型定义
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import type { AIFileInfo, SessionArtifact } from '@blueking/chat-x';
|
|
254
|
+
|
|
255
|
+
// 会话级文件产物:拍平去重后即为 AIFileInfo
|
|
256
|
+
type SessionArtifact = AIFileInfo;
|
|
257
|
+
|
|
258
|
+
type AIFileInfo = {
|
|
259
|
+
name: string;
|
|
260
|
+
outputId: string;
|
|
261
|
+
size: number;
|
|
262
|
+
type: AIFileType;
|
|
263
|
+
};
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## 关联 Composable
|
|
267
|
+
|
|
268
|
+
预览**命中与取链**由 [useArtifactPreview](/composables/use-artifact-preview) 提供(Provider / Consumer + `ARTIFACT_PREVIEW_TOKEN`)。**正文加载与渲染**由内部 `useArtifactPreviewLoader` + `ArtifactPreviewHost` 完成,不在该 composable 内。
|
|
269
|
+
|
|
270
|
+
## 关联组件
|
|
271
|
+
|
|
272
|
+
- [AssistantMessage](/components/message/assistant-message) — 文件产物来源(`property.artifacts`)
|
|
273
|
+
- [ChatContainer](/components/setup/chat-container) — 侧栏「文件产物」Tab 挂载场景,提供 `onArtifactClick`
|
|
274
|
+
- [MessageLoading](/components/helper/message-loading) — Host 预览区异步加载态
|
|
275
|
+
- [ExecutionSummary](/components/agent/execution-summary) — 同为侧栏 Tab 面板
|
|
@@ -11,37 +11,45 @@
|
|
|
11
11
|
<!-- FULL DOC -->
|
|
12
12
|
|
|
13
13
|
# InfoMessage 信息消息
|
|
14
|
+
|
|
14
15
|
## 源码事实
|
|
15
16
|
|
|
16
17
|
- **源码位置**:`src/components/chat-message/info-message/info-message.vue`
|
|
17
18
|
- **能力域**:消息系统
|
|
18
19
|
- **能力说明**:渲染居中的系统信息提示。
|
|
19
20
|
|
|
20
|
-
>
|
|
21
|
+
> **导出说明**:`InfoMessage` **未**从包入口导出(入口同名是 TS interface)。消费方经 `MessageRender` / `MessageContainer` 使用。下文 `InfoMessageComp` 为文档站内部示例。
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
系统信息分隔组件,在聊天消息列表中以**左右虚线夹中文案**的形式展示非对话类信息(会话重置、时间节点、状态变更等)。
|
|
23
24
|
|
|
24
25
|
## 视觉原理
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
根节点 `.ai-info-message` 为横向 flex:两侧通过 `::before` / `::after` 拉伸出虚线(主题边框色),中间 `.ai-info-message-body` 承载文案(主题次要文案色)。整块正常占位,避免旧实现 `height: 0` 导致内容被裁切遮挡:
|
|
27
28
|
|
|
28
29
|
```
|
|
29
|
-
|
|
30
|
+
─────── 以下是新的对话 ───────
|
|
30
31
|
```
|
|
31
32
|
|
|
33
|
+
多行时,多条 `.ai-info-message-content` 在 body 内纵向排列(`gap: 4px`),两侧虚线仍夹住整块文案区域。
|
|
32
34
|
## 基础用法
|
|
33
35
|
|
|
34
36
|
`content` 传入字符串,渲染单行分隔信息:
|
|
35
37
|
|
|
36
38
|
```vue
|
|
37
39
|
<template>
|
|
38
|
-
<
|
|
40
|
+
<MessageRender :message="message" />
|
|
39
41
|
</template>
|
|
40
42
|
|
|
41
43
|
<script setup lang="ts">
|
|
42
|
-
import {
|
|
43
|
-
|
|
44
|
-
const
|
|
44
|
+
import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
45
|
+
|
|
46
|
+
const message = {
|
|
47
|
+
id: '1',
|
|
48
|
+
messageId: '1',
|
|
49
|
+
role: MessageRole.Info,
|
|
50
|
+
content: '以下是新的对话',
|
|
51
|
+
status: MessageStatus.Complete,
|
|
52
|
+
};
|
|
45
53
|
</script>
|
|
46
54
|
```
|
|
47
55
|
|
|
@@ -49,15 +57,24 @@
|
|
|
49
57
|
|
|
50
58
|
## 多行信息
|
|
51
59
|
|
|
52
|
-
`content`
|
|
60
|
+
`content` 传入字符串数组时,每个元素渲染为一行居中文案,在中间 body 内纵向排列,两侧虚线夹住整块区域:
|
|
53
61
|
|
|
54
62
|
```vue
|
|
55
63
|
<template>
|
|
56
|
-
<
|
|
64
|
+
<MessageRender :message="message" />
|
|
57
65
|
</template>
|
|
58
66
|
|
|
59
67
|
<script setup lang="ts">
|
|
60
|
-
import {
|
|
68
|
+
import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
69
|
+
|
|
70
|
+
// 运行时 content 兼容 string[](TS 类型声明多为 string)
|
|
71
|
+
const message = {
|
|
72
|
+
id: '1',
|
|
73
|
+
messageId: '1',
|
|
74
|
+
role: MessageRole.Info,
|
|
75
|
+
content: ['会话已重置', '以下是新的对话'],
|
|
76
|
+
status: MessageStatus.Complete,
|
|
77
|
+
};
|
|
61
78
|
</script>
|
|
62
79
|
```
|
|
63
80
|
|
|
@@ -118,7 +135,7 @@
|
|
|
118
135
|
|
|
119
136
|
| 属性名 | 类型 | 说明 |
|
|
120
137
|
| --------- | -------------------- | ------------------------------------------------------------------ |
|
|
121
|
-
| content | `string \| string[]` |
|
|
138
|
+
| content | `string \| string[]` | 信息内容。字符串渲染单行;数组在中间区域纵向多行展示,两侧虚线夹住整块 |
|
|
122
139
|
| id | `number \| string` | 消息 ID(接收但不使用,由 MessageContainer 管理) |
|
|
123
140
|
| messageId | `number \| string` | 消息唯一标识(接收但不使用) |
|
|
124
141
|
| status | `MessageStatus` | 消息状态(接收但不使用,组件无状态相关渲染逻辑) |
|
|
@@ -138,6 +138,7 @@ type UserQuestionOptionItem = {
|
|
|
138
138
|
- 前端会为每道**选择题**追加 `label: 'others'` 的自由输入项;后端无需重复下发该选项。
|
|
139
139
|
- 当用户选择 Others 时,`answer[].description` 为用户输入文本。
|
|
140
140
|
- 业务可通过 `UserQuestionCard` 的 `#question` slot 渲染自定义表单;作答有效时调用 `setAnswer` 回传 `UserQuestionAnswerItem`,无效时传 `undefined`。
|
|
141
|
+
- UI 一次只展示一题:标题栏 `< 当前题 / 总题数 >` 切换;单选预设选项作答后自动跳下一题,多选 / Others 需手动切换(协议字段不变)。
|
|
141
142
|
|
|
142
143
|
## Interrupt
|
|
143
144
|
|
|
@@ -12,46 +12,60 @@
|
|
|
12
12
|
<!-- FULL DOC -->
|
|
13
13
|
|
|
14
14
|
# LoadingMessage 加载中消息
|
|
15
|
+
|
|
15
16
|
## 源码事实
|
|
16
17
|
|
|
17
18
|
- **源码位置**:`src/components/chat-message/loading-message/loading-message.vue`
|
|
18
19
|
- **能力域**:消息系统
|
|
19
20
|
- **能力说明**:消息列表中的加载占位,默认使用 AiLoading,也支持默认插槽覆盖。
|
|
20
21
|
|
|
21
|
-
>
|
|
22
|
+
> **导出说明**:`LoadingMessage` **未**从包入口导出。消费方经 `MessageRender`(`role: 'loading'`)或由 `MessageContainer` 自动注入。下文 `LoadingMessageComp` 为文档站内部示例。
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
加载等待状态组件:`AiLoading`(18px)+ 默认文案「请求中...」。可通过默认插槽自定义文案。
|
|
24
25
|
|
|
25
|
-
>
|
|
26
|
+
> **提示**:通常**不需要手动使用**,`MessageContainer` / `useMessageGroup` 会在满足条件时自动注入。
|
|
26
27
|
|
|
27
28
|
## 渲染效果
|
|
28
29
|
|
|
29
30
|
## 基础用法
|
|
30
31
|
|
|
31
|
-
组件无 Props
|
|
32
|
+
组件无 Props。文档站内部示例:
|
|
33
|
+
|
|
34
|
+
```vue
|
|
35
|
+
<template>
|
|
36
|
+
<LoadingMessageComp />
|
|
37
|
+
</template>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
消费方经 `MessageRender`:
|
|
32
41
|
|
|
33
42
|
```vue
|
|
34
43
|
<template>
|
|
35
|
-
<
|
|
44
|
+
<MessageRender
|
|
45
|
+
:message="{
|
|
46
|
+
id: 'loading',
|
|
47
|
+
messageId: '',
|
|
48
|
+
role: MessageRole.Loading,
|
|
49
|
+
content: '',
|
|
50
|
+
status: MessageStatus.Pending,
|
|
51
|
+
}"
|
|
52
|
+
/>
|
|
36
53
|
</template>
|
|
37
54
|
|
|
38
55
|
<script setup lang="ts">
|
|
39
|
-
import {
|
|
56
|
+
import { MessageRender, MessageRole, MessageStatus } from '@blueking/chat-x';
|
|
40
57
|
</script>
|
|
41
58
|
```
|
|
42
59
|
|
|
43
60
|
## 自定义加载文案
|
|
44
61
|
|
|
45
|
-
|
|
62
|
+
通过默认插槽覆盖「请求中...」:
|
|
46
63
|
|
|
47
64
|
```vue
|
|
48
65
|
<template>
|
|
49
|
-
|
|
66
|
+
<!-- 文档站内部示例 -->
|
|
67
|
+
<LoadingMessageComp>正在思考中,请稍候...</LoadingMessageComp>
|
|
50
68
|
</template>
|
|
51
|
-
|
|
52
|
-
<script setup lang="ts">
|
|
53
|
-
import { LoadingMessage } from '@blueking/chat-x';
|
|
54
|
-
</script>
|
|
55
69
|
```
|
|
56
70
|
|
|
57
71
|
## 动画说明
|
|
@@ -67,15 +81,18 @@
|
|
|
67
81
|
|
|
68
82
|
## 在 MessageContainer 中的自动注入
|
|
69
83
|
|
|
70
|
-
`
|
|
84
|
+
`useMessageGroup` 构建分组时,若**最后一条为用户消息**且 **`renderMode !== RenderMode.Share`**,自动在末尾追加 Loading 组:
|
|
71
85
|
|
|
72
86
|
```typescript
|
|
73
|
-
//
|
|
74
|
-
|
|
87
|
+
// use-message-group.ts(简化)
|
|
88
|
+
const shouldAppendLoading =
|
|
89
|
+
messages.at(-1)?.role === MessageRole.User && renderMode !== RenderMode.Share;
|
|
90
|
+
|
|
91
|
+
if (shouldAppendLoading) {
|
|
75
92
|
list.push({
|
|
76
93
|
messages: [
|
|
77
94
|
{
|
|
78
|
-
role: MessageRole.Loading,
|
|
95
|
+
role: MessageRole.Loading,
|
|
79
96
|
content: '',
|
|
80
97
|
status: MessageStatus.Pending,
|
|
81
98
|
id: 'loading',
|
|
@@ -87,7 +104,8 @@ if (messages.at(-1)?.role === MessageRole.User) {
|
|
|
87
104
|
}
|
|
88
105
|
```
|
|
89
106
|
|
|
90
|
-
|
|
107
|
+
- 下一条 AI 消息到来后,末尾不再是 user,Loading 组自动消失
|
|
108
|
+
- **分享预览**(`renderMode === RenderMode.Share`)**不会**注入 Loading,避免分享页出现「请求中」占位
|
|
91
109
|
|
|
92
110
|
**触发示例**:
|
|
93
111
|
|
|
@@ -127,6 +145,7 @@ if (messages.at(-1)?.role === MessageRole.User) {
|
|
|
127
145
|
- **默认插槽**:可通过默认插槽自定义加载文案,未传入时显示内置的 "请求中..."
|
|
128
146
|
- **i18n 支持**:默认文案 "请求中..." 通过内置 `t()` 函数处理,英文环境自动显示 "Requesting..."
|
|
129
147
|
- **选择模式**:`MessageContainer` 开启 `enableSelection` 时,Loading 消息组不显示复选框
|
|
148
|
+
- **分享模式**:`renderMode === RenderMode.Share` 时不自动注入 Loading
|
|
130
149
|
- **自动生命周期**:Loading 组随消息列表变化自动插入/移除,无需手动控制
|
|
131
150
|
|
|
132
151
|
## API
|
|
@@ -613,29 +613,12 @@ enum MessageToolsStatus {
|
|
|
613
613
|
Hidden = 'hidden',
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
-
// 消息角色
|
|
617
|
-
|
|
618
|
-
User = 'user',
|
|
619
|
-
Assistant = 'assistant',
|
|
620
|
-
Tool = 'tool',
|
|
621
|
-
Reasoning = 'reasoning',
|
|
622
|
-
Activity = 'activity',
|
|
623
|
-
Info = 'info',
|
|
624
|
-
Interrupt = 'interrupt',
|
|
625
|
-
Loading = 'loading',
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
// 消息状态
|
|
629
|
-
enum MessageStatus {
|
|
630
|
-
Pending = 'pending',
|
|
631
|
-
Streaming = 'streaming',
|
|
632
|
-
Complete = 'complete',
|
|
633
|
-
Error = 'error',
|
|
634
|
-
Stop = 'stop',
|
|
635
|
-
Disabled = 'disabled',
|
|
636
|
-
}
|
|
616
|
+
// 消息角色 / 消息状态完整枚举见常量文档,勿在此维护副本
|
|
617
|
+
// MessageRole、MessageStatus → ../../types/constants
|
|
637
618
|
```
|
|
638
619
|
|
|
620
|
+
> `MessageRole` / `MessageStatus` 完整取值见 [常量枚举](../../types/constants)。
|
|
621
|
+
|
|
639
622
|
## 关联组件
|
|
640
623
|
|
|
641
624
|
- [MessageRender](/components/message/message-render) — 按组渲染每条消息时委托使用
|